我有一个根项目 (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
的服务上进行配置可能是一个更好的主意吗?
在这种情况下(有点极端),内部使用类的配置怎么样?
最佳答案
假设这些扩展方法是在您的应用程序的 Composition Root 中定义的,为什么不直接从 AddModuleA
和 AddModuleB
中删除对 AddDependencyZ
的调用呢?
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 中的注册阶段):
services.AddModuleA();
services.AddModuleB();
services.AddDependencyZ();
这是否违反了最少知识原则?是的,确实如此,但这是使用 DI 容器的众多缺点之一。
我推荐Pure DI而不是使用 DI 容器。这将使问题消失,因为OP中的所有代码都是多余的。
关于design-patterns - 处理具有项目之间共享依赖关系的 IoC 配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56280553/