Unity没有解决MVC3控制器构造函数中的依赖关系

Dee*_*101 1 asp.net-mvc dependency-injection unity-container

我们有一个MVC3控制器,其中有一些"常见"工作,我们已经进入控制器构造函数.一些常见的工作是由一个失败耦合的类(比如说ourService)通过Unity动态解决(对于IoC /依赖注入).ourService在Controller的构造函数中为null(即未解析)但它在通常的Controller方法中正确解析.下面的简单演示代码显示了问题:

public class Testing123Controller : BaseController
{
    [Dependency]
    public IOurService ourService { get; set; }

    public Testing123Controller()
    {
            ourService.SomeWork(1); // ourService=null here !!
            ...
    }

    public ActionResult Index()
    {
            ourService.SomeWork(1); // resolved properly here here !!
            ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 为什么Unity解析行为有这种不同?我期待一致的行为.
  2. 我如何修复它,以便Unity即使在控制器的构造函数中也能解决这个问题?

我们设置Unity 2.0的方式是:

Global.asax中

Application_Start()
{
    ...
    Container = new UnityContainer();
    UnityBootstrapper.ConfigureContainer(Container);
    DependencyResolver.SetResolver(new UnityDependencyResolver(Container));
    ...
}

public static void ConfigureContainer(UnityContainer container)
{
    ...
    container.RegisterType<IOurService, OurService>();
    ...
}
Run Code Online (Sandbox Code Playgroud)

IOurService.cs

public interface IOurService
{
    bool SomeWork(int anInt);
}
Run Code Online (Sandbox Code Playgroud)

OurService.cs

public class OurService: IOurService
{
    public bool SomeWork(int anInt)
    {
        return ++anInt; //Whew! Time for a break ...
    }
}
Run Code Online (Sandbox Code Playgroud)

Cha*_*nga 5

作为类的基本原则,在可以设置实例属性之前,必须实例化实例.

Unity需要设置依赖项属性,但在实例完全实例化之前它不能这样做 - 即构造函数必须已完成执行.

如果你在构造函数中引用依赖属性,那么这还为时过早 - Unity尚无法设置它 - 因此它将被取消设置(即null).

如果需要在构造函数中使用依赖项,则必须使用构造函数注入.虽然通常使用构造函数注入通常是更好的方法:

public class Testing123Controller : BaseController
{
    public IOurService ourService { get; set; }

    public Testing123Controller(IOurService ourService)
    {
            this.ourService = ourService;
            this.ourService.SomeWork(1); // ourService no longer null here
            ...
    }

    public ActionResult Index()
    {
            ourService.SomeWork(1); // also resolved properly here
            ...
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

注意:在示例中,我将其保留ourService为可公开获取和可设置的属性,以防代码的其他部分需要访问它.另一方面,如果它只在类中访问(并且仅为了Unity目的而公开),那么引入构造函数注入时,最好将其作为private readonly字段.