Dav*_*nde 4 c# autofac autofac-module
考虑我有一个使用三个库 lib1、lib2 和 lib3 的应用程序。在每个库中,我都实现了一个Module注册在该库中实现的依赖项。
其中一些实现有自己的依赖项,例如,lib2 和 lib3 可能都需要 lib1 中存在的一些实现。
我的问题是,我是否让 lib2 和 lib3 中的模块在 lib1 中注册模块作为其Load实现的一部分?如果我的应用程序注册了 lib2 和 lib3 的模块,这是否会注册该模块两次?
或者我是否避免让一个模块注册另一个模块,将它留给应用程序,但缺点是启动时可能会丢失某些注册?
小智 5
我知道的有点晚了,但我认为回答这个问题可能会很好,而不仅仅是引用关于多重组合根源如何邪恶的经文......
如果我的应用程序注册了 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
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在IComponentRegistry/ ContainerBuidler(Module基类内部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...
}
Run Code Online (Sandbox Code Playgroud)
然后输出变成:
Registering Lib2Module
Registering Lib1Module
Registering Lib3Module
Registering Lib1Module
Run Code Online (Sandbox Code Playgroud)
显然,如果 Lib2Module/Lib3Module 可以成为其他模块的依赖项,则必须将类似的代码放入它们的 Load 方法中,同样,如果任何模块使用AttachToRegistrationSource和/或 AttachToComponentRegistration希望确保它们只运行一次,它们也需要检查。或者(如果这是您需要做的很多事情,可能最好)您可以创建自己的类实现IModule并在Configure.
我确实在生产代码中使用了这种模式来减少重复量,因为我有多个入口点,它们有自己的组合根(例如,一个 web api、一个 web 应用程序和一个重复的控制台应用程序),但它们共享一个大块代码,我可以忍受这使我成为 DI 纯粹主义者中不受欢迎的角色。