当密钥类需要Session(或其他特定于上下文的变量)时如何设置IoC

我试图弄清楚如何在依赖类可以根据应用程序中的某个变量(在本例中为Session状态)进行更改的情况下使用IoC。 例如,我们的每个客户端都有一个不同的数据库,因此与数据库的连接需要建立在其Session中存储的值上(特别是因为如果某些用户拥有多个业务,并且可以在数据库之间切换,则可能有多个数据库) 。

以下是我们当前如何设置此结构的一般示例:

public class MyTestController : ControllerBase { Repository _rep; public MyTest(Repository rep) { _rep = rep; } public MyTest() { string connString = String.Format("Server={0}; Database={1};" , SessionContainer.ServerName, SessionContainer.DatabaseName; var dc = new DataContext(connString); _rep = new Repository(dc); } public int SampleFn() { return _rep.GetCountOfEmployees(); } } public class Repository { DataContext _context; public Repository(DataContext context) { _context = context; } } 

我们能够使用IoC设置它并消除默认的c-tors? 如果是这样,怎么样? 我没有像这样使用DI的问题,但是我想探索一下StructureMap或Unity的可能性(注意:我们通常将db / server传递给构建datacontext的工厂类…上面的例子只是为了简洁)。

如何创建存储库实例及其生命周期与Controller无关。

在容器中注册组件时,应指定组件的生命周期。 根据您的实现,您可以选择设置存储库的生命周期以跟随会话。

在任何情况下,您都可以使用工厂从会话中创建存储库,但是从Controller外部执行此操作。

你肯定需要摆脱默认的构造函数。


我不记得如何在Unity或StructureMap中做到这一点,所以这里是Castle Windsor的例子。

定义抽象工厂:

 public interface IRepositoryFactory { Repository Create(); } 

和实施

 public class MyRepositoryFactory : IRepositoryFactory { private readonly HttpContextBase httpContext; public MyRepositoryFactory(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } this.httpContext = httpContext; } #region IRepositoryFactory Members public Repository Create() { // return Repository created from this.httpContext } #endregion } 

现在注册所有的东西

 container.AddFacility(); container.Register(Component.For() .ImplementedBy() .LifeStyle.PerWebRequest); container.Register(Component.For() .UsingFactory((IRepositoryFactory f) => f.Create()) .LifeStyle.PerWebRequest); 

在这里,我使用了PerWebRequest的生活方式,但如果你想进行优化,你可能想要创建一个自定义的PerWebSession生活方式。 这在Castle中并不难做到,但我不记得其他DI容器有多难。

您还需要注册HttpContextBase,因为MyRepositoryFactory依赖于它。