简体   繁体   English

配置 Unity 以解析构造函数参数和接口

[英]configure Unity to resolve a constructor parameter and interface

I have a FaxService class that takes two constructor parameters.我有一个采用两个构造函数参数的 FaxService 类。

public FaxService(string phone, IFaxProvider faxProvider)

How is Unity configured to send a string for the first parameter and an IFaxProvider instance for the second? Unity 如何配置为发送第一个参数的字符串和第二个参数的 IFaxProvider 实例? I realize I can inject another service that provides the string, but I am looking for a solution where I don't have to change the FaxService constructor parameters.我意识到我可以注入另一个提供字符串的服务,但我正在寻找一种无需更改 FaxService 构造函数参数的解决方案。

This is what I have so far...这是我到目前为止...

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();

        var phone = "214-123-4567";
        container.RegisterType<IFaxProvider, EFaxProvider>();
        container.RegisterType<IFaxService, FaxService>(phone);

        var fax = container.Resolve<IFaxService>();
    }
}

public interface IFaxService { }

public interface IFaxProvider { }

public class FaxService : IFaxService
{
    public FaxService(string phone, IFaxProvider faxProvider) { }
}

public class EFaxProvider : IFaxProvider { }

but it throws...但它抛出...

Unity.Exceptions.ResolutionFailedException HResult=0x80131500 Unity.Exceptions.ResolutionFailedException HResult=0x80131500
Message=Resolution of the dependency failed, type = 'ConsoleApp3.IFaxService', name = '(none)'.消息=依赖项解析失败,类型 = 'ConsoleApp3.IFaxService',名称 = '(无)'。 Exception occurred while: while resolving.异常发生时:解决时。

在此处输入图片说明

var container = new UnityContainer();
var phone = "214-123-4567";
container.RegisterType<IFaxProvider, EFaxProvider>();
container.RegisterType<IFaxService, FaxService>(new InjectionConstructor(phone, typeof(IFaxProvider)));

var fax = container.Resolve<IFaxService>();

I am looking for a solution where I don't have to change the FaxService constructor parameters.我正在寻找一种无需更改 FaxService 构造函数参数的解决方案。

There is nothing built into Unity to do this without specifying at least the types of all constructor parameters. Unity 中没有任何内置功能可以在不指定至少所有构造函数参数的类型的情况下执行此操作。

var container = new UnityContainer();
var phone = "214-123-4567";
container.RegisterType<IFaxService, FaxService>(new InjectionConstructor(phone, typeof(IFaxProvider)));
container.RegisterType<IFaxProvider, EFaxProvider>();

var fax = container.Resolve<IFaxService>();

The list of parameters would need to change every time the constructor changes.每次构造函数更改时,参数列表都需要更改。

Workaround解决方法

If you don't want to change your DI registration if the constructor changes for FaxService , build an abstract factory to separate the string/primitive parameters from the services.如果您不想在FaxService的构造函数更改时更改 DI 注册,请构建一个抽象工厂以将字符串/原始参数与服务分开。 Pass services through the constructor parameters of the factory.通过工厂的构造函数参数传递服务。 Pass string and primitive parameter types through the Build method parameters.通过Build方法参数传递字符串和原始参数类型。

public class FaxServiceFactory
{
    private readonly IFaxProvider faxProvider;
    public FaxServiceFactory(IFaxProvider faxProvider)
    {
        this.faxProvider = faxProvider ?? throw new ArgumentNullException(nameof(faxProvider));
    }

    public IFaxService Create(string phone)
    {
        return new FaxService(phone, this.faxProvider);
    }
}

And then register like:然后像这样注册:

var container = new UnityContainer();

var phone = "214-123-4567";
container.RegisterType<FaxServiceFactory>();
container.RegisterType<IFaxProvider, EFaxProvider>();
container.RegisterInstance<IFaxService>(container.Resolve<FaxServiceFactory>().Create(phone));

var fax = container.Resolve<IFaxService>();

Another possibility is to use a DI container that allows you to specify partial lists of constructor parameters (Autofac, Ninject, StructureMap, and Castle Windsor all do this out of the box).另一种可能性是使用 DI 容器,它允许您指定构造函数参数的部分列表(Autofac、Ninject、StructureMap 和 Castle Windsor 都开箱即用)。

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

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