说我在AutoFac(简化)中注册了以下内容:
对象A - >对象B - >对象C - >对象D
现在假设我想创建第二个对象A(让它称之为对象P),它是对象A的虚拟克隆,除了一个区别:
对象A - >对象B - > 对象F - >对象D
有没有办法获取现有的AutoFac对象并以这种方式克隆它?我在"现实生活中工作的对象图"比这个例子复杂了许多个数量级,如果没有必要,我不会复制一堆注册逻辑。
答案 0 :(得分:2)
虽然你可能会使用component metadata来实现这种情况,但最简单的方法是使用嵌套的生命周期范围并覆盖注册。
当您开始新的生命周期范围时,您可以传入一个lambda表达式,该表达式允许您即时向该范围添加新注册。此时你将覆盖"对象C"注册"对象F。"
这是一个有效的例子。首先,让我们定义一些接口和实现。您会注意到层次结构中的第三项服务IThird
有两个实现 - ObjectC
和ObjectF
- 以匹配您的问题:
public interface IFirst
{
ISecond Child { get; }
void WriteHierarchy();
}
public interface ISecond
{
IThird Child { get; }
}
public interface IThird
{
IFourth Child { get; }
}
public interface IFourth
{
}
public class ObjectA : IFirst
{
public ObjectA(ISecond child)
{
this.Child = child;
}
public ISecond Child { get; private set; }
public void WriteHierarchy()
{
Console.WriteLine("{0} -> {1} -> {2} -> {3}",
this.GetType().Name,
this.Child.GetType().Name,
this.Child.Child.GetType().Name,
this.Child.Child.Child.GetType().Name);
}
}
public class ObjectB : ISecond
{
public ObjectB(IThird child)
{
this.Child = child;
}
public IThird Child { get; private set; }
}
public class ObjectC : IThird
{
public ObjectC(IFourth child)
{
this.Child = child;
}
public IFourth Child { get; private set; }
}
public class ObjectF : IThird
{
public ObjectF(IFourth child)
{
this.Child = child;
}
public IFourth Child { get; private set; }
}
public class ObjectD : IFourth
{
}
有了这个,您可以看到我们要做的就是解决该顶级项目IFirst
,并且我们会写出层次结构。
这是显示" swap"的实际工作代码。层次结构中的第三个项目:
var builder = new ContainerBuilder();
builder.RegisterType<ObjectA>().As<IFirst>();
builder.RegisterType<ObjectB>().As<ISecond>();
builder.RegisterType<ObjectC>().As<IThird>();
builder.RegisterType<ObjectD>().As<IFourth>();
var container = builder.Build();
// It's always good to use lifetime scopes and not
// resolve directly from a container. You can see
// here that I'm not doing anything special - this
// lifetime scope will have the "default registrations."
using(var scope = container.BeginLifetimeScope())
{
// This will print:
// ObjectA -> ObjectB -> ObjectC -> ObjectD
var obj = scope.Resolve<IFirst>();
obj.WriteHierarchy();
}
// You can pass override registrations when you begin
// a new lifetime scope. In this case, I'm overriding
// the one service type deep in the hierarchy.
using(var scope = container.BeginLifetimeScope(
b => b.RegisterType<ObjectF>().As<IThird>()))
{
// This will print:
// ObjectA -> ObjectB -> ObjectF -> ObjectD
var obj = scope.Resolve<IFirst>();
obj.WriteHierarchy();
}