繁体   English   中英

依赖注入-当实现使用Unity for DI时如何使用简单注入器注入接口实现

[英]Dependency Injection - How to inject implementation of interface using Simple Injector when the implementation uses Unity for DI

我有两个独立的项目...一个项目正在使用Simple Injector,另一个项目正在使用Unity。 在简单的注射器项目中,我试图使用Unity的DI注册位于项目内的类的接口/实现。 我可以成功完成此操作并获得对该类的访问权限,但是该类中标记为Unity [Dependency]的所有内容均无法解决。 我可以将那些依赖项注册到Simple Injector容器,但是一旦使用Unity进入类,它就会丢失它。

例:

Project1 (使用简单注入器)

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。 是否有办法知道使用Project1中注册的GenericRepo <>?

这可能吗?

谢谢! 瑞安

如果我理解正确,Project 2是一些共享项目,该项目在使用Unity进行依赖注入的其他项目中使用。 在这种情况下,Unity通过使用DependencyAttribute注释属性来使用属性注入。

简单注入器能够执行属性注入。 但是,属性注入仅应用于可选依赖项。 当您遇到NullReferenceException此依赖项不是可选的!

因此,您应该将IGenericRepo<ServiceObj>移至IService的构造函数。 这使IService用户清楚需要一个存储库才能正常运行。 当您对IService时,此功能特别有用,因为在这种情况下,构造函数将明确传达其需要存储库的信息。

通过将依赖关系移至构造函数,Simple Injector将正确注入存储库,或者如果配置无效,则抛出ActivationException

您可以通过调用container.Verify()进行测试,并且我建议这样做,您可以在此处阅读: 验证容器的配置 这将使应用程序快速失败

如果无法重构项目2或由于其他一些令人信服的原因而无法选择构造函数注入,那么Simple Injector会支持属性注入。 但是,它不支持这种现成的方式。 Simple Injector的设计原则之一是永不默默地失败 ,因此建议只使用Explicit属性注入 这将使容器有机会使用其诊断服务,并且在配置无效的情况下快速失败。

正如您可以在参考文档中阅读的那样,有两种方法可以进行属性注入:

  1. 通过使用对container.RegisterInitializer()的调用来注册初始化程序。
  2. 通过实现IPropertySelectionBehavior

选项2将让Simple Injector使用Diagnostics Services自动检查依赖项。 验证所有“初始化程序”也都执行时,但不检查lambda中的代码的生活方式等。

Simple Injector不鼓励其用户依赖容器,因此它不包含任何可直接使用的Atrributes ,例如Unity具有DependencyAttribute

因此,您在这里有2个选项:

  1. 让项目1还获得对Unity的依赖关系(它已经间接地拥有它了!,),并创建IPropertySelectionBehavior的实现以搜索Unity DependencyAttribute
  2. 在项目2中创建您自己的自定义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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM