我的代码将引用 Microsoft Unity,但我确信它非常适用于所有 DI 框架。如果您正确使用 DI,则无需调用 new BusinessObject(new dataContext),DI 关联将为您处理一切。
我的示例会有点长,因为我将粘贴一些用于运行由 Unity 完全加载的 DI 的模型视图演示器网站的代码。(如果你想要完整的源代码,请查看我的博客并从我的 Assembla SVN 服务器下载)
加载容器(可以是我喜欢的代码或使用配置)
protected void Application_Start(object sender, EventArgs e)
{
Application.GetContainer()
// presenters / controllers are per request
.RegisterType<IEmployeeController, EmployeeController>(new ContextLifetimeManager<IEmployeeController>())
//Data Providers are Per session
.RegisterType<IEmployeeDataProvider, EmployeeDataProvider>(new SessionLifetimeManager<IEmployeeDataProvider>())
//Session Factory is life time
.RegisterType<INHibernateSessionManager, NHibernateSessionManager>(new ContainerControlledLifetimeManager());
}
自定义 HTTP 模块在 OnPreRequest 调用期间为每个页面调用 Unity BuildUp 方法。
private static void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
var handler = HttpContext.Current.Handler;
HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler);
// User Controls are ready to be built up after the page initialization is complete
var page = HttpContext.Current.Handler as Page;
if (page != null)
{
page.InitComplete += OnPageInitComplete;
}
}
用 [Dependency] 属性装饰的页面容器展示器
public partial class Employees : Page, IEmployeeView
{
private EmployeePresenter _presenter;
[Dependency]
public EmployeePresenter Presenter
{
set
{
_presenter = value;
_presenter.View = this;
}
}
}
带有 InjectionConstructor 方法的 Presenter
public class EmployeePresenter : Presenter<IEmployeeView>
{
private readonly IEmployeeController _controller;
[InjectionConstructor]
}
public EmployeePresenter(IEmployeeController controller)
{
_controller = controller;
}
控制器跟风
public class EmployeeController : IEmployeeController
{
private readonly IEmployeeDataProvider _provider;
[InjectionConstructor]
public EmployeeController(IEmployeeDataProvider DataProvider)
{
_provider = DataProvider;
}
}
与提供者相同
public class EmployeeController : IEmployeeController
{
private readonly IEmployeeDataProvider _provider;
[InjectionConstructor]
public EmployeeController(IEmployeeDataProvider DataProvider)
{
_provider = DataProvider;
}
}
最后是会话管理器,它只包含一个常规构造函数。
public class NHibernateSessionManager : INHibernateSessionManager
{
private readonly ISessionFactory _sessionFactory;
public NHibernateSessionManager()
{
_sessionFactory = GetSessionFactory();
}
}
那么当一个页面请求启动时,HttpModule 在页面上调用 BuildUp() 方法会发生什么。然后,Unity 会看到标有 Dependency 属性的 Property,并将检查它的容器以查看其中是否存在 EmployeePresenter 对象。
由于容器中没有这样的对象,因此它将尝试创建一个 EmployeePresenter。在检查创建它在 Presenter 中看到的类时,它需要一个需要将 IEmployeeController 注入其中的构造函数。由于容器实际上有一个控制器的管理器,它将查看容器中是否存在它的实例,而在页面请求的开头不存在,因此它将实例化控制器。
然后,Unity 将看到控制器需要注入 IEmployeeDataProvider,它将继续此过程,直到最终到达 Provider 需要注入会话管理器的地步。由于会话管理器不再需要注入,Unity 将创建会话管理器的一个实例,将其存储在容器中,因为它给定了 ContainerLifeTimeManager,将其注入提供者并存储该实例,依此类推,直到它完成创建一个页面的 EmployeePresenter 依赖项。