关于Circular References的autofac wiki页面说要使用:
cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties);
但看起来2.4.5中不再存在 ActivatedHandler 。在源代码中挖掘,我找到了该类的实现,因此我在OnActivated中添加了方法实现。不幸的是,它仍然不起作用。
我在这里整理了一个最小的复制品,看起来就像维基页面上的那样。
class M
{
public VM VM { get; set; }
public M()
{
}
}
class VM
{
public VM(M m)
{
}
}
[Fact]
void CanResolveCircular()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<VM>();
builder.RegisterType<M>().OnActivated(e => e.Context.InjectUnsetProperties(e.Instance));
using (var container = builder.Build())
{
var m = container.Resolve<M>();
Assert.NotNull(m);
}
}
此代码仍会在尝试Resolve时抛出堆栈溢出异常。我错过了什么?让Autofac处理循环依赖的正确方法是什么?
答案 0 :(得分:7)
circular dependencies州的Autofac文档:
注意,设置没有意义 如果两个类都是这种情况 在工厂范围内注册。
您的M
和VM
注册均为InstancePerDependency
(以前称为FactoryScope
),因此此声明适用于您的方案。因此,您将无休止地创建M和VM实例。
如果您希望注入VM
的属性获取您解析的M
的相同实例,则应将M
的生命周期更改为其他内容比InstancePerDependency
(例如SingleInstance
)。如下所示:
builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance();
注意:我也在使用更新的PropertiesAutowired(true)扩展方法。您可以在repro中使用它来代替OnActivated代码。
如果您不想为每个应用设置一个M
个实例,则可以设置LifetimeScope
并使用InstancePerLifetimeScope
。
答案 1 :(得分:5)
对于任何有兴趣的人来说,这是一种新的方式:
class DependsByProp1
{
public DependsByProp2 Dependency { get; set; }
}
class DependsByProp2
{
public DependsByProp1 Dependency { get; set; }
}
// ...
var cb = new ContainerBuilder();
cb.RegisterType<DependsByProp1>()
.InstancePerLifetimeScope()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
cb.RegisterType<DependsByProp2>()
.InstancePerLifetimeScope()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);