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

时间:2012-12-09 01:16:47

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

我们有一个MVC3控制器,其中有一些“常见”工作,我们将其转入控制器构造函数。一些常见的工作是由一个失败耦合的类(比如ourService)完成的,它通过Unity动态解析(用于IoC /依赖注入)。在Controller的构造函数中ourService为空(即未解析)但它在通常的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 !!
            ...
    }
    ...
}

问题

  1. 为什么Unity解析行为有这种不同?我希望能有一致的行为。
  2. 如何解决这个问题,以便即使在控制器的构造函数中Unity也能解决这个问题?
  3. 我们设置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>();
        ...
    }
    

    IOurService.cs

    public interface IOurService
    {
        bool SomeWork(int anInt);
    }
    

    OurService.cs

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

3 个答案:

答案 0 :(得分: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
            ...
    }
    ...
}

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

答案 1 :(得分:1)

您正在使用属性注入(通过使用Dependency属性)而不是构造函数注入,因此直到实例化控制器之后才会解析依赖项。如果您想要访问依赖项是构造函数,只需将其添加到ctor:

private readonly IOurService _ourService { get; set; }

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

答案 2 :(得分:0)

我担心Unity要在构造函数上工作,实例本身必须使用Unity解析。构造函数中的Service属性为null的事实支持这一想法。如果您自己致电控制器(不使用Unity),Unity没有时间解决该问题。