我有两个独立的项目......一个项目使用Simple Injector,另一个项目使用Unity。从简单的注入器项目,我试图使用Unity为其DI注册位于项目内的类的接口/实现。我可以成功地执行此操作并获得对该类的访问权限,但该类中标记为Unity [Dependency]的任何内容都无法解析。我可以将这些依赖项注册到Simple Injector容器,但是一旦使用Unity进入类就会丢失它。
示例:
Project1 (使用Simple Injector)
public class StartUp {
var container = new Container();
container.RegisterSingleton(typeof(IGenericRepo<>), typeof(GenericRepo));
container.RegisterSingleton<IService, Service>();
//more code below etc...
}
public class TestController
{
private readonly IService service;
public TestController(IService service)
{
this.service = service;
}
public void TestMethod()
{
var test = service.GetEverything();
}
}
Project2 (使用Unity)
public class Service : IService
{
[Dependency]
public IGenericRepo<ServiceObj> _serviceRepo { private get; set; }
public IQueryable<ServiceObj> GetEverything()
{
return _serviceRepo.Get();
}
}
通过上面的示例,我可以在Project 2中找到GetEverything方法,但是_serviceRepo依赖性为null。有没有办法让它知道使用注册的GenericRepo&lt;&gt;来自Project1?
这可能吗?
谢谢! 莱恩
答案 0 :(得分:1)
如果我理解正确,Project 2是一些共享项目,在其他使用Unity for Dependency Injection的项目中使用。在这种情况下,Unity通过使用DependencyAttribute
注释属性来使用属性注入。
Simple Injector能够进行属性注入。但是,属性注入只应用于可选的依赖项。当你遇到NullReferenceException
时,这种依赖不是可选的!
所以你应该将IGenericRepo<ServiceObj>
移动到IService
的构造函数。这使IService
的用户明白需要存储库才能正常运行。当你单元测试IService
时,这变得特别有用,因为构造函数在这种情况下会清楚地传达它需要一个存储库。
通过将依赖项移动到构造函数,Simple Injector将正确注入存储库,或者如果配置无效,则抛出ActivationException
。
您可以通过调用container.Verify()
进行测试,我建议您这样做,您可以在此处阅读:Verify the container’s configuration。这将使应用程序转到fail fast。
如果项目2无法重构或者由于某些其他令人信服的原因,构造函数注入不是一个选项,Simple Injector确实支持属性注入。然而,它确实不支持这种开箱即用的功能。 Simple Injector的设计原则之一是to never fail silently,因此只建议Explicit property injection。这将使容器有机会使用其Diagnostic Services并在配置无效时快速失败。
正如您在参考文档中所读到的,有两种方法可以进行属性注入:
container.RegisterInitializer()
IPropertySelectionBehavior
选项2将允许Simple Injector自动使用Diagnostics Services检查依赖项。验证所有'初始化程序'时也会执行,但不检查lambda中的代码的生活方式等。
Simple Injector不鼓励其用户依赖容器,因此它不包含任何可以开箱即用的Atrributes
,例如Unity具有DependencyAttribute
所以你有两个选择:
IPropertySelectionBehavior
的实现来搜索Unity DependencyAttribute
Attribute
,并注释此自定义属性的_serviceRepo
。 1和2之间的唯一区别是搜索哪个属性。
如果无法触摸项目2,则无法选择选项2。实施IPropertySelectionBehavior
非常简单:
// custom attribute only for option 1
public class ImportAttribute : Attribute { }
class UnityDependencyPropertySelectionBehavior : IPropertySelectionBehavior
{
public bool SelectProperty(Type type, PropertyInfo prop)
{
return prop.GetCustomAttributes(typeof(DependencyAttribute)).Any();
}
}
您可以使用此自定义IPropertySelectionBehavior
配置容器:
container.Options.PropertySelectionBehavior =
new UnityDependencyPropertySelectionBehavior();
总结一下:
将依赖项移动到构造函数,因为它不是可选的依赖项。换句话说使用构造函数注入!
如果有令人信服的理由不执行此工作IPropertySelectionBehavior