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

发布于 2024-11-10 18:54:47 字数 964 浏览 2 评论 0原文

关于循环引用的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);
    }
}

当尝试解决时,此代码仍然会引发堆栈溢出异常。我缺少什么?让 Autofac 处理循环依赖的正确方法是什么?

The autofac wiki page about Circular References says to use:

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

But it looks like ActivatedHandler does not exist anymore in 2.4.5. Digging around in the source, I found the implementation of that class, and so I put in the method implementation in the OnActivated instead. Unfortunately, it this still doesn't work.

I've put together a minimal repro here that looks like what was on the Wiki page.

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);
    }
}

This code still throws a stack overflow exception as a Resolve is attempted. What am I missing? What is the correct way to get Autofac to handle circular dependencies?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

執念 2024-11-17 18:54:47

循环依赖项的 Autofac 文档指出:

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

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

如果您希望注入的 VM 属性采用您解析的 M相同实例,则应该更改 M< 的生命周期/code> 为 InstancePerDependency 之外的其他内容(例如 SingleInstance)。如下所示:

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

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

如果您不希望每个应用有一个 M 实例,您可以设置一个 LifetimeScope 并使用 InstancePerLifetimeScope

The Autofac documentation for circular dependencies states:

Note, it doesn't make sense to set up
this scenario if both classes are
registered with Factory scope.

Both your M and VM registrations are InstancePerDependency (previously known as FactoryScope) so this statement applies to your scenario. As a result, you get in an endless loop of creating M and VM instances.

If you want the property injected VM to take the same instance of M that you resolve, you should change the lifetime of M to something other than InstancePerDependency (e.g. SingleInstance). This is shown below:

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

Note: I'm also using the more recent PropertiesAutowired(true) extension method. You can use this in place of the OnActivated code in your repro.

If you don't want a single instance of M per app, you could setup a LifetimeScope and use InstancePerLifetimeScope.

倾其所爱 2024-11-17 18:54:47

对于任何对此感兴趣的人来说,这是执行此操作的新方法:

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);

属性/属性依赖项

For anyone interested here is the new way of doing this:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文