应用程序对象中的Unity RegisterInstance

时间:2012-06-25 08:45:24

标签: asp.net dependency-injection unity-container

我想过应用依赖注入并在我正在处理的项目中使用Unity。在Global.asax文件的Application_Start事件中注册了类型,并将Unity Conatiner保存在Application对象全局变量中。但是在解析presenter实例之前,我需要将当前webform的实例作为构造函数参数传递给演示者。我在页面的OnInit事件中这样做。

protected override void OnInit(EventArgs e)
{
    IUnityContainer container = (IUnityContainer)
        HttpContext.Current.Application["container"];

    container.RegisterInstance<IAddRoleView>(this, 
        new ExternallyControlledLifetimeManager());

    _presenter = container.Resolve<AddRolePresenter>();
    base.OnInit(e);
}

我的问题是:

  1. 请求后,AddRoleView实例会发生什么 提供服务?
  2. 是垃圾收集还是Unity容器 作为Unity Conatiner,在应用程序关闭之前保留一个引用 实例已保存在应用程序对象中?

1 个答案:

答案 0 :(得分:1)

你在做什么是行不通的。您正在将容器中的页面实例注册为单例。这不行。根据Unity的构建方式,它将在您第二次调用RegisterInstance<IAddRoleView>时抛出异常,永久缓存所有已注册的实例,或替换先前的实现。但即使它取代了之前的注册,您的代码中也会出现并发错误,因为可能会在为此AddRolePreventer实例解析的Page中注入不同的页面。

我明白你想要实现的目标。你想要解析AddRolePresenter,并希望将页面注入到演示者的构造函数中。您通过构造函数使两个类型彼此依赖,这会导致循环依赖。您需要通过将页面注入演示者的属性来打破此依赖关系周期。但是不要让Unity将页面注入构造函数;手动执行此操作:

_presenter = container.Resolve<AddRolePresenter>();
_presenter.View = this;

一些提示:

  • 在初始化阶段之后(在Application_Start运行之后)阻止进行任何注册。在初始化阶段之后添加注册通常被认为是不好的做法,因为它会使配置变得脆弱,并且难以维护。
  • 移动此页面初始化,将演示者解析为页面的构造函数。这使您可以更轻松地验证是否可以创建页面并在启动应用程序期间(甚至在单元测试中)执行此操作。查看实例here以查看如何执行此操作的示例(它是另一个DI框架的文档,但它也适用于Unity)。
  • 防止将容器存储在HttpContext.Application字典中。这使得在错误的地方使用容器变得太容易了,并且将您的应用程序与Unity结合得太多了。这可以防止您进行重构或将Unity更改为另一个框架(您将来肯定会做的事情)。再看看this example。它还显示了将容器与Web窗体集成的更好方法