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

时间:2018-03-29 17:21:45

标签: c# .net inversion-of-control unity-container

我有一个带有两个构造函数参数的FaxService类。

public FaxService(string phone, IFaxProvider faxProvider)

如何配置Unity为第一个参数发送字符串,为第二个参数发送IFaxProvider实例?我意识到我可以注入另一个提供字符串的服务,但我正在寻找一个解决方案,我不必更改FaxService构造函数参数。

这就是我到目前为止......

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 { }

但它会抛出......

Unity.Exceptions.ResolutionFailedException   的HResult = 0x80131500   消息=依赖关系的解决方案失败,键入=&#39; ConsoleApp3.IFaxService&#39;,name =&#39;(none)&#39;。 在解决时发生异常。

enter image description here

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

  

我正在寻找一种解决方案,我无需更改FaxService构造函数参数。

如果没有至少指定所有构造函数参数的类型,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>();

每次构造函数更改时,参数列表都需要更改。

解决方法

如果构造函数更改为FaxService,则不想更改DI注册,请构建一个抽象工厂以将字符串/原始参数与服务分开。通过工厂的构造函数参数传递服务。通过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);
    }
}

然后注册如下:

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

另一种可能性是使用一个DI容器,它允许你指定构造函数参数的部分列表(Autofac,Ninject,StructureMap和Castle Windsor都可以开箱即用)。