C# 克隆现有的AutoFac对象(一次注册除外)
假设我在AutoFac中注册了以下内容(简化): 对象A-->对象B-->对象C-->对象D 现在假设我想创建第二个对象a(我们称之为对象p),它是对象a的虚拟克隆,除了一个区别: 对象A-->对象B-->对象F-->对象DC# 克隆现有的AutoFac对象(一次注册除外),c#,inversion-of-control,autofac,C#,Inversion Of Control,Autofac,假设我在AutoFac中注册了以下内容(简化): 对象A-->对象B-->对象C-->对象D 现在假设我想创建第二个对象a(我们称之为对象p),它是对象a的虚拟克隆,除了一个区别: 对象A-->对象B-->对象F-->对象D 是否有办法获取现有的AutoFac对象并以这种方式克隆它?我在“真实生活”中使用的对象图比这个例子复杂很多数量级,如果没有必要,我宁愿不复制一堆注册逻辑。虽然你可能会疯狂/幻想使用它来实现这一点,最简单的方法是使用嵌套的生存期范围和覆盖注册 当您开始一个新的生存期作用域时,
是否有办法获取现有的AutoFac对象并以这种方式克隆它?我在“真实生活”中使用的对象图比这个例子复杂很多数量级,如果没有必要,我宁愿不复制一堆注册逻辑。虽然你可能会疯狂/幻想使用它来实现这一点,最简单的方法是使用嵌套的生存期范围和覆盖注册 当您开始一个新的生存期作用域时,您可以传入一个lambda表达式,该表达式允许您动态地向该作用域添加新的注册。此时,您将用“对象F”覆盖“对象C”注册 这里有一个有效的例子。首先,让我们定义一些接口和实现。您会注意到层次结构中的第三个服务,
ITIRD
,有两个实现-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
,然后我们将写出层次结构
下面是显示层次结构中第三项的“交换”的实际工作代码:
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();
}
var builder=newcontainerbuilder();
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
var container=builder.Build();
//使用生存期作用域总是好的,而不是
//直接从容器解析。你可以看到
//在这里,我没有做任何特别的事情-这个
//生存期范围将具有“默认注册”
使用(var scope=container.BeginLifetimeScope())
{
//这将打印:
//ObjectA->ObjectB->ObjectC->ObjectD
var obj=scope.Resolve();
obj.WriteHierarchy();
}
//开始时可以传递覆盖注册
//新的生命周期范围。在这种情况下,我将覆盖
//层次结构中最深层的一种服务类型。
使用(var scope=container.BeginLifetimeScope)(
b=>b.RegisterType().As())
{
//这将打印:
//ObjectA->ObjectB->ObjectF->ObjectD
var obj=scope.Resolve();
obj.WriteHierarchy();
}
您是想从同一个容器中解析不同的对象图,还是想找出一种方法,在两个不同的容器中重复使用尽可能多的对象注册?前者。我只处理一个集装箱,嗨,特拉维斯。非常感谢你的例子。我很难将其转化为需求。我使用的不是服务定位器,因此需要克隆对象A的对象无法访问AutoFac容器。您不会从对象图中创建生存期范围,而是在工作单元的最顶端创建它。不幸的是,我不能在这方面给你具体的指导——你必须将模式应用到你独特的需求中。