【问题标题】:Postponing registration of property using Autofac使用 Autofac 推迟财产登记
【发布时间】:2016-10-13 16:01:35
【问题描述】:

我正在尝试使用 Autofac 实现以下依赖注入场景。

假设我有三个类,A、B 和 P。A 类拥有一个 P 类型的属性,并且还有一个对 B 的引用,需要在运行时注入。

class A
{
    private B _b;

    public P Prop { get; set; }

    InitializeProp()
    { ... }
}

同时,B类依赖于P的一个实例:

class B
{
    private P _p;
}

现在,最重要的细节是:我需要以某种方式将 P 的实例注入 B。但是,该实例必须是类 A 中的 Prop,它仅在 A 中的 InitializeProp() 被调用后才被初始化。假设 InitializeProp() 可以在对象的生命周期中调用,比 A 的构造函数晚。

Autofac 可以实现这种情况吗?

我尝试做这样的事情,但我得到一个循环引用异常,大概是当 B 被进一步解决时:

containerBuilder.RegisterType<A>().SingleInstance();

containerBuilder.Register<Func<P>>(c =>
{
    var a = c.Resolve<A>();
    return () => a.Prop;
});

【问题讨论】:

    标签: c# .net dependency-injection autofac


    【解决方案1】:

    为了能够掌握注册问题,我经常发现在代码中手动构建所需的对象图很有用。在不使用 DI 容器的情况下,这就是您希望实现的目标:

    var p = new P();
    var a = new A(new B(p)) { P = p };
    

    您可以看到P 的实例在整个图中被重用来实现这一点。有了这些知识,我们现在可以确定您需要做什么才能实现您想要的。

    所以解决方案是配置 Autofac 以重用 P 的相同实例。由于您将A 注册为SingleInstance,因此除了将P 注册为SingleInstance 之外别无选择,否则您将处理Captive Dependency

    但如果我们退后一步,我认为P 没有理由成为A 的属性。其实有hardly ever a good reason使用属性注入。

    您应该始终使用构造函数注入。所以你的类应该如下所示:

    class A { public A(B b, P p) { } }
    class B { public B(P p) { } }
    

    这完全消除了配置问题,因为您可以简单地执行以下操作:

    containerBuilder.RegisterType<A>().SingleInstance();
    containerBuilder.RegisterType<B>().SingleInstance();
    containerBuilder.RegisterType<P>().SingleInstance();
    

    【讨论】:

    • 理想情况下,我会按照您的建议设计我的类,通过 A 和 B 中的构造函数注入 P。但是,我的真实场景受到其他依赖项的限制,长话短说,没有办法规避类 A 中的属性 P,它在 A 生命周期的某个时间点初始化。 A 实现了一个接口,其中声明了属性 P。
    【解决方案2】:

    所以最终我想通了,事实证明 Autofac 比我想象的要聪明。

    没有必要显式注册 P 的 Func,而是使用这个简化的注册:

    builder.RegisterType<A>().SingleInstance();
    
    builder.Register(c =>
    {
      var a = c.Resolve<A>();
      return a.Property;
    });
    
    builder.RegisterType<B>();
    

    现在在主程序中我可以执行以下操作:

    var a = container.Resolve<A>();
    a.InitializeProperty();
    a.Execute(); // calls B
    

    【讨论】:

      猜你喜欢
      • 2015-05-11
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多