Unity 未解析 MVC3 控制器构造函数中的依赖项



我们有一个MVC3控制器,其中有一些"常见"工作,我们将其纳入控制器构造函数中。一些常见的工作是由一个通过Unity(用于IoC/Dependency注入)动态解析的失耦合类(比如ourService)完成的。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的方式是:

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);
}

我们的服务.cs

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

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

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字段。

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

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

恐怕Unity要处理构造函数,实例本身必须使用Unity进行解析。构造函数中的Service属性是null,这一事实支持了这一想法。如果你自己打电话给管理员(不是与Unity),Unity没有时间解决财产问题。

最新更新