如何使用Autofac 2.4.5处理循环引用?

时间:2011-05-31 10:27:23

标签: dependency-injection autofac circular-dependency property-injection

关于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处理循环依赖的正确方法是什么?

2 个答案:

答案 0 :(得分:7)

circular dependencies州的Autofac文档:

  

注意,设置没有意义   如果两个类都是这种情况   在工厂范围内注册。

您的MVM注册均为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);

Property/Property Dependencies