1

我们有一个 MVC3 控制器,其中有一些我们在控制器构造函数中滚动的“常见”工作。其中一些常见工作是由通过 Unity 动态解析的松散耦合类(例如ourService)完成的(用于 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 !!
            ...
    }
    ...
}

问题

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

我们设置 Unity 2.0 的方式是:

全球.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);
}

我们的服务.cs

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

3 回答 3

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为公开的可获取和可设置属性,以防您的代码的其他部分需要访问它。另一方面,如果它只能在类中访问(并且仅出于 Unity 的目的而公开),那么随着构造函数注入的引入,最好将其设为private readonly字段。

于 2012-12-09T01:35:16.497 回答
1

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

private readonly IOurService _ourService { get; set; }

public Testing123Controller(IOurService ourService)
{
  _ourService = ourService;
  _ourService.SomeWork(1); // ourService=null here !!
  ...
}
于 2012-12-09T01:24:04.707 回答
0

恐怕要让 Unity 在构造函数上工作,必须使用 Unity 解析实例本身。Service 属性在构造函数中的事实null支持了这个想法。如果您自己调用控制器(不使用 Unity),Unity 没有时间解析该属性。

于 2012-12-09T01:24:30.590 回答