2

Начал изучать принципы DI и работу с IoC контейнерами. Вопрос следующего характера: Пусть у меня есть некая библиотека классов MyClassLibrary, там представлены следующие классы:

public class DefaultDownloader : IDownloader
{
    public string DownloadSomething(string param)
    {
        return $"{nameof(DefaultDownloader)} {param}";
    }
}

public static class MyContainer
{
    public static IContainer Container { get; set; }

    static MyContainer()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<DefaultDownloader>().As<IDownloader>();
        builder.RegisterType<FirstSource>().AsSelf();
        builder.RegisterType<SecondSource>().AsSelf();
        Container = builder.Build();
    }

}

public class SourceControl
{
    public string GetAllInfo(string param)
    {
        string toReturn = "";
        using (var scope = MyContainer.Container.BeginLifetimeScope())
        {
            var source1 = scope.Resolve<FirstSource>();
            var source2 = scope.Resolve<SecondSource>();
            toReturn += source1.DownloadInformation("FirstSource");
            toReturn += " "+ source2.DownloadInformation("SecondSource");
        }

        return toReturn;
    }
}

public class FirstSource
{
    private readonly IDownloader downloader;

    public FirstSource(IDownloader downloader)
    {
        this.downloader = downloader;
    }

    public string DownloadInformation(string param)
    {
        return downloader.DownloadSomething(param);
    }
}

public class SecondSource
{
    private readonly IDownloader downloader;

    public SecondSource(IDownloader downloader)
    {
        this.downloader = downloader;
    }

    public string DownloadInformation(string param)
    {
        return downloader.DownloadSomething(param);
    }
}

public interface IDownloader
{
    string DownloadSomething(string param);
}

Этими классами можно пользоваться и по отдельности, но есть еще один класс (SourceControl), который позволяет забирать информацию со всех источников. В классе необходимо создать экземпляры источников (FirstSource, SecondSource) и вызвать некоторые методы оттуда. Соответственно, в этом же классе придется внедрять зависимости в FirstSource и SecondSource.

Использование извне:

class Program
{
    private static IContainer Container { get; set; }

    public static void ConfigureContainer()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<MySecondDownloader>().As<IDownloader>();
        builder.RegisterType<FirstSource>().AsSelf();
        builder.RegisterType<SecondSource>().AsSelf();
        Container = builder.Build();
    }

    static void Main(string[] args)
    {
        // Следующие две строчки можно закомментировать, чтобы использовать
        // "стандартный" контейнер
        ConfigureContainer();
        MyContainer.Container = Container;

        SourceControl sourceControl = new SourceControl();
        Console.WriteLine(sourceControl.GetAllInfo("Main"));

        Console.ReadLine();
    }
}

public class MyFirstDownloader : IDownloader
{
    public string DownloadSomething(string param)
    {
        return $"{nameof(MyFirstDownloader)} {param} - MODIFIED! (1)";
    }
}

public class MySecondDownloader : IDownloader
{
    public string DownloadSomething(string param)
    {
        return $"{nameof(MySecondDownloader)} {param} - MODIFIED! (2)";
    }
}

Вопрос: Как это более правильно сделать с точки зрения логики и DI. В качестве IoC контейнера планирую использовать autofac. И правильно ли я сейчас это делаю?

  • 2
  • выделяете интерфейс для источников 2) регистрируете их под этим интерфейсом 3) В новом классе получаете все зарегистрированные реализации интерфейса источника. Все
  • – tym32167 Sep 01 '19 at 15:24
  • 1
  • @tym32167 А если эти два класса реализуют обобщенный интерфейс IGetMaxInfo<T>? – PracticeMakesPerfect Sep 01 '19 at 15:31
  • ну пусть реализуют, какие проблемы с этим? – tym32167 Sep 01 '19 at 15:34
  • @tym32167 Честно говоря, немного не понял первый комментарий. Можете, пожалуйста, чуть-чуть по-подробнее объяснить, если не сложно, конечно? – PracticeMakesPerfect Sep 01 '19 at 15:38
  • давайте так: вы пишете ваш класс но есть еще один класс, который позволяет забирать информацию со всех источников, запускаете его, и если с ним возникают проблемы - обновляете вопрос и тогда будем смотреть. Пока что я проблемы в вашем вопросе не вижу. – tym32167 Sep 01 '19 at 15:46
  • @tym32167 Я правильно понимаю, что Resolve логику я должен буду поместить в этот класс, который занимается созданием экземпляров FirstSource и SecondSource. Как мне правильно сделать в этом классе ссылку на мой container, и где его правильней было объявить для последующего использования? – PracticeMakesPerfect Sep 01 '19 at 15:51
  • @tym32167 Я написал свою реализацию и поместил в вопрос, т.е. скорректировал его. Я правильно делаю или нет? – PracticeMakesPerfect Sep 01 '19 at 17:22