Как разрешить зависимость в библиотеке классов из контейнера, настроенного при запуске? - PullRequest
0 голосов
/ 05 июня 2018

Цель заключается в использовании IoC и возможности [макетировать зависимости] для модульного тестирования.

Проект: .NET Core Web API с несколькими библиотеками классов

Я использую Microsoft.Extensions.DependencyInjection для моего IoC, и я хотел бы продолжать использовать его, если он поддерживает то, что я пытаюсь выполнить.

Проблема: по крайней мере один класс в моих сборках (библиотеках классов) имеет зависимость, котораянужно издеваться (например, с помощью Moq).Я полностью понимаю, что могу использовать инжектор конструктора для внедрения интерфейса, но это не соответствует сценарию.

То, что я просто пытаюсь выполнить в своей сборке, это разрешить зависимость с помощью контейнера, который я инициировал в своем классе запуска Web-API.

Как бы я это сделал?И если это невозможно, что может быть другим способом сделать то же самое, то есть издеваться над моим принтером, не используя инъекцию зависимостей?

Ниже приведен пример кода, который, надеюсь, немного прояснит это.

Startup.cs веб-API (содержит ссылку на сборку, которая определяет принтер)

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPrinter, Printer>();
}

В другой сборке я хотел бы разрешить экземпляр Printer, используя тот же контейнер.

    public interface IPrinter
    {
        void Print(string text);
    }

    public class Printer : IPrinter
    {
        public void Print(string text)
        {
            Console.WriteLine("Printing: " + text);
        }
    }


    public class Task
    {
        public void PrintSomething(string text)
        {
            //do not 'new up' but resolve it from the container of Startup.cs
            var printer = new Printer(); 
            printer.Print(text);
        }
    }

1 Ответ

0 голосов
/ 06 июня 2018

Это проблема дизайна, замаскированная под XY проблемой .

Вы уже сбили Принцип явных зависимостей

Методы и классы должны явно требовать (обычно через параметры метода или параметры конструктора) любых взаимодействующих объектов, в которых они нуждаются для правильного функционирования.

public class PrintTask {
    private readonly IPrinter printer;

    public PrintTask(IPrinter printer) {
        this.printer = printer;
    }

    public void PrintSomething(string text) {
        printer.Print(text);
    }
}

Что позволит зависимому классу, уже зарегистрированномус контейнером

public void ConfigureServices(IServiceCollection services) {
    services.AddScoped<IPrinter, Printer>();
    services.AddScoped<PrintTask>();
}

из гибкого развязанного класса, чьи зависимости можно легко смоделировать и внедрить.

Внедрение зависимостей - лучший выбор, но есть и анти-паттерн Service Locator., что, хотя и выполнимо, обычно не рекомендуется.

...