5

关于循环引用的 autofac wiki 页面说要使用:

cb.Register<DependsByProp>().OnActivated(ActivatedHandler.InjectUnsetProperties);

但看起来ActivatedHandler在 2.4.5 中不再存在。在源代码中挖掘,我找到了该类的实现,因此我将方法实现放在了 OnActivated 中。不幸的是,这仍然不起作用。

我在这里整理了一个最小的复制品,看起来就像 Wiki 页面上的内容。

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

4

2 回答 2

7

循环依赖的 Autofac 文档指出:

请注意,如果两个类都注册到 Factory 范围,则设置此方案没有意义。

MVM注册都是InstancePerDependency(以前称为FactoryScope),因此此声明适用于您的方案。结果,您陷入了创建 M 和 VM 实例的无限循环。

如果您希望注入的属性VM采用您解析的相同实例M您应该将生命周期更改为(例如)M以外的其他内容。如下所示:InstancePerDependencySingleInstance

builder.RegisterType<M>().PropertiesAutowired(true).SingleInstance();

注意:我也在使用更新的 PropertiesAutowired(true) 扩展方法。您可以使用它来代替您的 repro 中的 OnActivated 代码。

如果您不想要M每个应用程序的单个实例,您可以设置 aLifetimeScope并使用InstancePerLifetimeScope.

于 2011-05-31T13:19:01.560 回答
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);

属性/属性依赖项

于 2014-05-03T15:01:54.303 回答