在Autofac中,我如何在调用Build后更改已注册的实例?

33

那么假设我有这段代码:

var builder = new ContainerBuilder();
builder.RegisterInstance(new MyType());
var container = builder.Build();

后来,我想要更改所有在container上调用的将来解析的MyType实例。

3个回答

48

当您想要更改注册信息时,请创建一个新的ContainerBuilder,注册新实例,并调用Update,并传入容器:

// at some later point...
builder = new ContainerBuilder();
builder.RegisterInstance(myType2);
builder.Update(container);

4
更新(container)已过时,建议重新构建容器。 - Jim Speaker
当有500个单元测试用例需要运行时,我认为为每个用例重建容器将非常低效。在这种情况下,跨用例覆盖服务是一个可考虑的解决方法。 - Jijie Chen
请注意,参见此讨论 https://github.com/autofac/Autofac/issues/811#issuecomment-272428072 - Jijie Chen

21

另一种方法是注册一个委托,该委托能够更改容器提供的基础实例。考虑以下代码:

 var theInstance = new MyType();
 var builder = new ContainerBuilder();
 builder.Register(context => theInstance);
 builder.Register<Action<MyType>>(context => newInstance => theInstance = newInstance);
 var container = builder.Build();

现在你可以解析该操作以获取可更改注册的委托:

 var updateInstance = c.Resolve<Action<MyType>>();
 updateInstance(new MyType());

注意: 如果您能详细说明更改实例的时间原因,或许我们甚至可以找到更好的解决方案。


当需要运行500个单元测试用例时,我认为为每个用例重建容器将是低效的。在这种情况下,跨用例覆盖服务是一个可行的解决方法。 - Jijie Chen
@JijieChen,那500个单元测试真的需要完整的构建容器才能运行吗?如果是这样,我会觉得我在这些测试中做得太多了,因此它们更类似于集成测试而不是单元测试。 - Peter Lillevold
1
我不完全同意你的看法,这些情况更像是集成测试。考虑一个类'C'有5个依赖项,在单元测试场景下,你需要手动声明这些对象并将它们添加到'C'中。在重构过程中,很可能需要改变所有的测试用例...这是代价高昂的。通过重用从DI解析出来的依赖实例和覆盖你想要自定义以满足你的测试用例的实例之间的平衡,来完成这个任务。 - Jijie Chen
@JijieChen 我同意,这可能会成为一个维护问题。虽然有人可能会认为太多的依赖实际上是一种代码异味,并且可能表明您的类正在做太多的事情。但我想那是另一个讨论主题了。 - Peter Lillevold

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接