Autofac:如何在依赖于另一个对象函数输出的类上使用构造注入

本文关键字:注入 输出 函数 依赖于 一个对象 Autofac | 更新日期: 2023-09-27 17:49:48

这个问题是关于一般的IoC的,但是我使用的是Autofac,所以Autofac的解决方案会很好。

所以假设以下类:

class A
{
    IEnumerable<B> GetBs();
}
class B 
{
    // Some code
}
class C
{
    readonly IEnumerable<B> bs;
    C(IEnumerable<B> bs)
    {
        this.bs = bs;
    }
}
class Program
{
    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        builder.Register<A>();
        builder.Register<C>();
        var container = builder.Build();
        var c = container.Resolve<C>();
        // do something with c
    }
}

以上Main将失败。

我注意到我可以通过添加这行代码来解决这个问题:
builder.Register(c => c.Resolve<A>().GetBs())

然而,这感觉不对。还有别的办法吗?还是设计变化?

Autofac:如何在依赖于另一个对象函数输出的类上使用构造注入

如上所述,这个类结构看起来非常好。您正在正确地使用构造函数注入并使用类的静态结构来通信不变量和关系。在这里提供的信息级别上,我认为唯一缺少的是C构造函数中的Guard子句:)

在概念层面上,很难回答这是否是一个好的设计。这取决于这里没有提供的上下文。B是业务还是实体?b的预期来源是什么?

作为一般的经验法则,我们应该只注入服务,而用服务来处理实体(比如仓库或网关之类的),所以如果B代表一个服务,那么把它注入C是可以的。如果它代表一个实体,那么它就变得可疑了——除非C也是一个实体…

另一个注意事项,您可以询问b的规范源。如果A确实是b的容器,那么上述解决方案是正确的(并且是惯用的autofacc代码)。如果b确实有不同的起源,通过a来解决它们可能是一个hack…

给定您对已接受的答案的回复,Autofac中可能会使用另一种技术。如果插件集在注册时可用,您可以将它们注册为一个集合。