我有一个应用程序可能需要连接到多个数据库。但是每个模块只会连接到一个数据库。所以我认为将数据库隔离到每个模块中可能是有意义的,这样每个模块都会自动解析自己的数据库,我不需要为命名注册而烦恼。但令我惊讶的是,Autofac 的模块似乎更像是一个代码模块而不是一个逻辑模块(我在这里错了吗?):IA
[Test]
public void test_module_can_act_as_scope_container()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new Module1());
IContainer c = builder.Build();
var o = c.ResolveNamed<CB>("One");
Assert.That(o.A.Name, Is.EqualTo("One"));
builder = new ContainerBuilder();
builder.RegisterModule(new Module1());
builder.RegisterModule(new Module2());
c = builder.Build();
var t = c.ResolveNamed<CB>("One");
Assert.That(t.A.Name, Is.EqualTo("Two"));
}
以及使用的接口(interface)/模块:
public interface IA
{
string Name { get; set; }
}
public class CA : IA
{
public string Name { get; set; }
}
public class CB
{
public CB(IA a)
{
A = a;
}
public IA A { get; private set; }
}
public class Module1 : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(c => new CA() { Name = "One" }).As<IA>();
builder.RegisterType<CB>().Named("One", typeof(CB));
}
}
public class Module2 : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(c => new CA() { Name = "Two" }).As<IA>();
builder.RegisterType<CB>().Named("Two", typeof(CB));
}
}
最佳答案
是的,你是对的。
模块仅用于将配置拆分为一些独立的部分。它们不以任何方式限定配置范围。拥有模块实际上与合并所有模块相同 Load
方法的代码合并到一个配置方法中,然后构建容器。
在你的情况下你的 Module2
实际上覆盖了 IA
的注册来自 Module1
的界面.
我也一直有兴趣找到问题的解决方案。我采用以下方法:
键控服务
var key = new object();
builder.Register(c => new CA() { Name = "Two" }).Keyed<IA>(key);
builder.RegisterType<CB>().Named("Two", typeof(CB))
.WithParameter(new ResolvedParameter(
(pi, ctx) => pi.Type == typeof(IA),
(pi, ctx) => ctx.ResolveKeyed<IA>(key)
));
优点:
您可以控制哪些 IA
实例将被注入(inject)到每个模块中。
对比:
- 代码很多
- 它不会生成
IA
组件“内部”到模块 - 其他模块仍然可以使用简单的Resolve<IA>
解析它.模块不是孤立的。
希望对你有帮助
更新
在某些情况下,从设计的角度来看,这样做可能更容易,坦率地说更正确:
代表注册
builder.Register(ctx => new CB(new CA { Name = "Two" }))
.Named("Two", typeof(CB));
优点:
- 您没有公开您的模块特定
CA
到其他模块
对比:
- 如果
CA
和CB
有复杂的依赖关系和大量的构造函数参数,你最终会得到一堆乱七八糟的构造代码 - 如果您需要使用
CA
在模块内的多个位置,您必须找到避免复制粘贴的方法
嵌套容器实例
还有一个选择是拥有一个独立的 Container
在每个模块内。这样所有模块都可以拥有自己的私有(private)容器配置。但是,据我所知,Autofac 不提供任何内置方法以某种方式链接多个 Container
实例。虽然我认为实现这个应该不是很困难。
关于c# - Module 是 Autofac 的绑定(bind)上下文吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9094057/