Передача сервисов с использованием внедрения зависимостей и шаблона фабрики в ASP.NET

Я использую ядро ​​ASP.NET, я знаю, что такой механизм ведения журнала уже предоставляется платформой, но использую это, чтобы проиллюстрировать мою проблему.

Я использую шаблон Factory для создания класса Logger, так как я не знаю тип ведения журнала (потому что он хранится в БД).

Контракт ILogger

Log(string msg)

Затем LoggerFactory вернет ILogger после создания Logger на основе параметра, переданного из БД:

public class LoggerFactory
{
    public static Contracts.ILogger BuildLogger(LogType type)
    {
        return GetLogger(type);
    }

//other code is omitted, GetLogger will return an implementation of the related logger

Теперь, когда мне нужно использовать Logger, я должен сделать это следующим образом:

  public class MyService
{
    private ILogger _logger
    public MyService()
    {
        _logger = LoggerFactory.BuildLogger("myType");
    }

Но я намерен оставить свои классы без какой-либо реализации, мне нужно использовать Constructor DI в MyService и мне нужно внедрить все зависимости при запуске:

    services.AddTransient<Contracts.ILogger, LoggerFactory.BuildLogger("param") > ();

Но это не сработает, нам нужно пройти конкретную реализацию. Как заставить это работать, используя DI, есть ли лучший подход для реализации этого?

1 ответ

Решение

В вашем подходе есть пара ошибок:

Вместо этого ваш сервис должен выглядеть следующим образом:

public class MyService
{
    private ILogger _logger;
    public MyService(ILogger logger)
    {
        _logger = logger;
    }
}

Это значительно упрощает всех потребителей, которые зависят от ILogger, Это также означает, что получение права ILogger за MyService становится ответственным за Корень Композиции, который является правильным местом для получения этих знаний.

Это, однако, означает, что вам может потребоваться перейти от встроенного DI-контейнера ASP.NET Core к более многофункциональной DI-библиотеке, поскольку встроенный контейнер не способен выполнять контекстную регистрацию для ILogger при этом библиотека автоматически связывает и другие зависимости конструктора.

С контейнером ASP.NET Core DI вы можете подключать свои службы только с помощью делегата. Например:

services.AddTransient<MyService>(c => new MyService(
    BuildLogger(typeof(MyService).Name),
    c.GetRequiredService<ISomeOtherDependency>(),
    c.GetRequiredService<IYetAnotherOne>());
Другие вопросы по тегам