通过项目之间的共享依赖项处理IoC配置

时间:2019-05-23 17:51:00

标签: design-patterns dependency-injection configuration inversion-of-control

我有一个根项目(root),一些模块(AB),并且这些模块具有一些外部依赖项(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 个答案:

答案 0 :(得分:1)

假设这些扩展方法是在应用程序的Composition Root中定义的,为什么不从AddDependencyZAddModuleA中删除对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.
    //...
}

然后,您将在编写时在“合成根目录”中配置容器(这是RRR pattern中的 Register 阶段):

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

这是否违反了最低知识原则?是的,的确如此,但这是使用DI容器的众多缺点之一。

我建议使用Pure DI,而不要使用DI容器。这将使问题消失,因为OP中的所有代码都是多余的。