如何使用Unity一次注入两个实现?

时间:2019-01-31 19:52:59

标签: c# interface unity-container

我有一个IConsole界面,描述了如何向控制台编写内容,还有一个实现,upperCaseConsole

使用Unity将IConsole注入Foo类中。

public interface IConsole {
 void WriteLine(string text);   
}

public class upperCaseConsole: IConsole {
    public void WriteLine(string text){
    Console.WriteLine(text.ToUpper());  
    }
}

public class Foo{
 private readonly IConsole console;
    public Foo(IConsole console){
    this.console = console; 
    }

    public void WriteStuff(string stuff){
    console.WriteLine(stuff);
    }
}

我现在想更改文本写入控制台的方式。我已经很好地将实现与foo分离了,我可以注入一个新的实现,例如说lowerCaseConsole

public class lowerCaseConsole: IConsole {
    public void WriteLine(string text){
    Console.WriteLine(text.ToLower());  
    }
}

我的问题是,尽管进行了最好的测试,但我不确定lowerCaseConsole是否能胜任这项工作,并且我希望同时运行这两种实现。

如何做到不复制Foo中的所有代码?

我想避免类似的事情:

public class Foo{
     private readonly IConsole lowerConsole;
     private readonly IConsole upperConsole;

        public Foo([Dependency("lower")] IConsole lowerConsole,
             [Dependency("upper")] IConsole upperConsole){
        this.lowerConsole = lowerConsole;
        this.upperConsole = upperConsole;   
        }

        public void WriteStuff(string stuff){
        lowerConsole.WriteLine(stuff);
        upperConsole.WriteLine(stuff);
        }
    }

注意:现实生活中的情况是,我将继续进行数据库更改。我想透明地开始写入新数据库,看看情况如何,但为了以防万一,请继续写入当前数据库。

2 个答案:

答案 0 :(得分:4)

一个选择是创建第三个实现,其中包含另外两个的私有成员,对它的WriteLine方法的调用只会转发给其他两个类型。

public class BothCaseConsole : IConsole
{
    private readonly LowerCaseConsole lcc = new LowerCaseConsole();
    private readonly UpperCaseConsole ucc = new UpperCaseConsole();

    public void WriteLine(string text)
    {
        lcc.WriteLine(text);
        ucc.WriteLine(text);
    }
}

然后将这种类型注入Foo中:

new Foo(new BothCaseConsole()).WriteStuff("Stuff to write");

enter image description here

答案 1 :(得分:1)

您可以使用命名注册来注入IEnumerable<IConsole>。这种方法可以通过更多的实现轻松扩展...或者您可以轻松地删除其中之一...

container.RegisterType<IConsole, LowerConsole>("LowerConsole");
container.RegisterType<IConsole, UpperConsole>("UpperConsole");
container.RegisterType<IEnumerable<IConsole>, IConsole[]>();

然后,Foo的ctor变得有些不同,WriteStuff方法也变得...

public Foo(IEnumerable<IConsole> consoles)
{
    this.consoles = consoles; 
}

public void WriteStuff(string stuff)
{
    foreach(var console in consoles)
    {
        console.WriteLine(stuff);
    }
}