我知道有点晚了,但我认为回答这个问题可能会很好,而不是仅仅引用关于多个组合根源如何邪恶的经文......
如果我的应用注册了 lib2 和 lib3 的模块,这是否会注册该模块两次?
使用 Autofac 4.8.1 测试,它确实:
public class Lib1Module: Module
{
protected override void Load(ContainerBuilder builder)
{
Console.WriteLine("Registering Lib1Module");
// Register Types...
}
}
public class Lib2Module: Module
{
protected override void Load(ContainerBuilder builder)
{
Console.WriteLine("Registering Lib2Module");
builder.RegisterModule<Lib1Module>();
// Register Types...
}
}
public class Lib3Module: Module
{
protected override void Load(ContainerBuilder builder)
{
Console.WriteLine("Registering Lib3Module");
builder.RegisterModule<Lib1Module>();
// Register Types...
}
}
public class Program
{
public void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterModule<Lib2Module>();
builder.RegisterModule<Lib3Module>();
using(var container = builder.Build())
{
// Do Stuff
}
}
}
输出:
Registering Lib2Module
Registering Lib1Module
Registering Lib3Module
Registering Lib1Module
IComponentRegistry
您可以在/上使用 Properties 字典ContainerBuidler
(基类在内部使用 -source的属性Module
创建它传递给的 Container 构建器)来解决此问题并强制对模块进行单一注册,如果Method of更改为:Load
IComponentRegistry
Load
Lib1Module
protected override void Load(ContainerBuilder builder)
{
if (builder.Properties.ContainsKey(GetType().AssemblyQualifiedName))
{
return;
}
builder.Properties.Add(GetType().AssemblyQualifiedName, null);
Console.WriteLine("Registering Lib1Module");
// Register Types...
}
然后输出变为:
Registering Lib2Module
Registering Lib1Module
Registering Lib3Module
显然,如果 Lib2Module/Lib3Module 可以成为其他模块的依赖项,则必须将类似的代码放入它们的 Load 方法中,并且类似地,如果使用任何模块AttachToRegistrationSource
和/或 AttachToComponentRegistration
希望确保它们仅在它们也需要检查时运行。或者(如果这是您需要做的很多事情,可能最好)您可以创建自己的类实现IModule
并在Configure
.
我肯定在生产代码中使用了这种模式来减少重复量,因为我有多个入口点,它们有自己的组合根(例如,Web api、Web 应用程序和重复出现的控制台应用程序),但它们共享很大一部分代码,我可以忍受这使我成为 DI 纯粹主义者中不受欢迎的角色。