C# 使用Unity进行属性依赖项注入的正确方法

C# 使用Unity进行属性依赖项注入的正确方法,c#,dependency-injection,unity-container,ioc-container,C#,Dependency Injection,Unity Container,Ioc Container,我有一个类需要依赖注入。由于该类已经是另一个抽象的实现,并且它的“兄弟”实现可能不共享相同的依赖项,因此我尝试使用属性注入,而不是构造函数注入 (所有这些类/接口名称仅用于说明) 我的IProvider摘要: public interface IProvider { void ProviderMethod(); } 我的IProvider实现(带有我想要注入的IData依赖项): public class ProviderClass : IProvider { // How d

我有一个类需要依赖注入。由于该类已经是另一个抽象的实现,并且它的“兄弟”实现可能不共享相同的依赖项,因此我尝试使用属性注入,而不是构造函数注入

(所有这些类/接口名称仅用于说明)

我的IProvider摘要:

public interface IProvider
{
    void ProviderMethod();
}
我的IProvider实现(带有我想要注入的IData依赖项)

public class ProviderClass : IProvider
{
    // How do I inject this dependency?
    [Dependency]
    public IData data { get; set; }

    public void ProviderMethod()
    {
        // Can't do this as data == null!
        data.DataMethod();
    }
}
另一个IProvider实现(示例显示它没有相同的依赖项):

IData抽象和实现示例:

public interface IData
{
    void DataMethod();
}

public class DataClass : IData
{
    public void DataMethod();
}
我需要知道的是:如何使用Unity(我选择的IOC容器)成功地将属性依赖项(IData)注入ProviderClass

我尝试了所有的Unity注册选项(RegisterType、RegisterInstance、Resolve…),但是我的注入属性总是以NULL结束。我想把这件事做好,而不是强迫随机代码进入,直到它能够正常工作

或者有没有更好的方法将(可选)依赖项注入到“兄弟”类中


顺便说一句,我最初的IProvider实现是通过一个抽象工厂创建的,所以这可能是我应该关注IData依赖的另一个领域(?)

您仍然应该使用构造函数注入,因为

您正试图在
IProviderFactory
实现中进行阻止,您可能不想将容器注入工厂以防止落入容器

但是,如果您在内部定义了
IProviderFactory
实现,则会阻止自己执行服务定位器,即使您注入了容器,因为

因此,您应该尽可能靠近Unity配置来定义您的
ProviderFactory
实现,它应该如下所示:

public class ProviderFactory : IProviderFactory
{
    private readonly Dictionary<string, Type> providerTypes;
    private readonly Container container;

    public ProviderFactory(Dictionary<string, Type> providerTypes, 
        Container container) {
        this.providerTypes = providerTypes;
        this.container = container;
    }

    public IProvider CreateProvider(string name) {
        return (IProvider)this.container.Resolve(this.providerTypes[name]);
    }
}
公共类ProviderFactory:IPProviderFactory
{
专用只读词典提供程序类型;
专用只读容器;
公共ProviderFactory(字典providerTypes,
集装箱(集装箱){
this.providerTypes=providerTypes;
this.container=容器;
}
公共IProvider CreateProvider(字符串名称){
返回(IPProvider)this.container.Resolve(this.providerTypes[name]);
}
}

此实现可以在Unity中注册为singleton。这使您不必在远离服务定位器的情况下向工厂过度注入构造函数。

您仍然应该使用构造函数注入,因为

您正试图在
IProviderFactory
实现中进行阻止,您可能不想将容器注入工厂以防止落入容器

但是,如果您在内部定义了
IProviderFactory
实现,则会阻止自己执行服务定位器,即使您注入了容器,因为

因此,您应该尽可能靠近Unity配置来定义您的
ProviderFactory
实现,它应该如下所示:

public class ProviderFactory : IProviderFactory
{
    private readonly Dictionary<string, Type> providerTypes;
    private readonly Container container;

    public ProviderFactory(Dictionary<string, Type> providerTypes, 
        Container container) {
        this.providerTypes = providerTypes;
        this.container = container;
    }

    public IProvider CreateProvider(string name) {
        return (IProvider)this.container.Resolve(this.providerTypes[name]);
    }
}
公共类ProviderFactory:IPProviderFactory
{
专用只读词典提供程序类型;
专用只读容器;
公共ProviderFactory(字典providerTypes,
集装箱(集装箱){
this.providerTypes=providerTypes;
this.container=容器;
}
公共IProvider CreateProvider(字符串名称){
返回(IPProvider)this.container.Resolve(this.providerTypes[name]);
}
}

此实现可以在Unity中注册为singleton。这使您不必在远离服务定位器的情况下向工厂过度注入构造函数。

我不清楚您为什么不进行构造函数注入。你能详细说明一下吗?主要是因为依赖项是可选的,其他IProvider实现可能有许多自己的依赖项,这些依赖项对于它们的类来说是唯一的。IProvider实现从抽象工厂(比如IProviderFactory)返回;随着每个新的IProvider实现的添加,工厂将不得不在其自己的注入策略中适应它们不断增长的数量(潜在的构造函数参数膨胀?)。使用Unity进行属性依赖项注入的正确方法是:让解析的类型包含正确的配置,而不要重复自己。例如,如果您需要横切关注点来将日志注入多个对象,您可以使用拦截器。我不清楚为什么不进行构造函数注入。你能详细说明一下吗?主要是因为依赖项是可选的,其他IProvider实现可能有许多自己的依赖项,这些依赖项对于它们的类来说是唯一的。IProvider实现从抽象工厂(比如IProviderFactory)返回;随着每个新的IProvider实现的添加,工厂将不得不在其自己的注入策略中适应它们不断增长的数量(潜在的构造函数参数膨胀?)。使用Unity进行属性依赖项注入的正确方法是:让解析的类型包含正确的配置,而不要重复自己。例如,如果您需要横切关注点将日志记录注入多个对象,则可以使用拦截器。