Как я могу внедрить две реализации как один раз с Unity? - PullRequest
0 голосов
/ 31 января 2019

У меня есть интерфейс IConsole, описывающий, как записывать данные в консоль, и одна реализация, upperCaseConsole.

IConsole внедряется в класс Foo с использованием Unity.

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 голосов
/ 31 января 2019

Один из вариантов - создать третью реализацию, содержащую частные члены двух других, и вызовы этого метода 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

0 голосов
/ 31 января 2019

Вы можете использовать именованную регистрацию для ввода IEnumerable<IConsole>.Этот подход легко расширяется с помощью большего количества реализаций ... или вы можете легко удалить одну из них ...

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

, тогда ctor Foo станет немного другим, а также метод WriteStuff...

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

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