Обработка конфигурации IoC с общими зависимостями между проектами - PullRequest
1 голос
/ 23 мая 2019

У меня есть корневой проект (root), некоторые модули (A, B), и эти модули имеют некоторые внешние зависимости (Z). Я использую контейнер IoC.

Я использую C # здесь, но это общий вопрос шаблона. Допустим, мой контейнер services, и я могу инициализировать конфигурацию IoC с использованием методов расширения. Так что в root проекте я пишу:

services.AddModuleA();
services.AddModuleB();

В модуле A У меня есть этот метод:

public static void AddModuleA(this IServiceCollection services)
{
    // Init module internal services.
    //services.AddScoped<IA1Service, A1Service>();
    //...

    // Init module external dependencies.
    services.AddDependencyZ();
}

В модуле B У меня есть похожий метод:

public static void AddModuleB(this IServiceCollection services)
{
    // Init module internal services.
    //...

    // Init module external dependencies.
    services.AddDependencyZ();
}

Очевидно, что Z зависимость уже была добавлена, поэтому это говорит мне, что я не должен настраивать ее внутри метода расширения модуля, и мне лучше объявить ее конфигурацию в root проекте:

services.AddModuleA();
services.AddModuleB();
services.AddDependencyZ();

Но не нарушает ли это принцип Наименьшего Знания? Импорт и настройка модуля A (или B) приведет к каскадному явному объявлению всех конфигураций зависимостей.

И связанный с этим вопрос, объявляет ли методы расширения AddModuleA() и AddModuleB() плохой шаблон вообще? Может быть, лучше настроить непосредственно на root только те службы, которые я буду использовать? И в этом случае (немного экстремально), как насчет конфигурации внутреннего использования только класса?

1 Ответ

1 голос
/ 04 июня 2019

Предположим, что эти методы расширения определены в Root Composition вашего приложения, почему бы вам просто не удалить вызов AddDependencyZ из AddModuleA и AddModuleB?

public static void AddModuleA(this IServiceCollection services)
{
    // Init module internal services.
    //services.AddScoped<IA1Service, A1Service>();
    //...
}

public static void AddModuleB(this IServiceCollection services)
{
    // Init module internal services.
    //...
}

После этого вы настроите контейнер в корне композиции (это фаза Register в шаблоне RRR ):

services.AddModuleA();
services.AddModuleB();
services.AddDependencyZ();

Это нарушает принцип Наименьшего Знания? Да, это так, но это один из многих недостатков использования DI-контейнера.

Я рекомендую PI DI вместо использования DI-контейнера. Это может привести к исчезновению проблемы, поскольку весь код в OP будет избыточным.

...