根据触发解析的父树解析参数?

Resolve parameters according to the parent tree that triggered the resolve?

我有类似的代码:

class A: IA { ... }
class B: IB {
    public B(IA a, ...) { ... }
    ...
}
class C1 {
    public C1(IA a, IB b, ...) { ... }
}
class C2 {
    public C2(IA a, IB b, ...) { ... }
}

我只需要 A 的两个实例 -- 一个与 C1 一起使用,一个与 C2 一起使用。我想要 B 的两个实例。传递给 C1 的 B 实例应该获得为 C1 创建的相同 A 实例。 C2 和他的参数应该有一个不同的 A 实例。我如何在 Autofac 中配置这个场景? 看起来 Owned instance lifetime feature 应该处理这个,但是发布的例子是只有一层深,而不是两层。

我的真实情况要复杂得多。我有十几个 IB 的继承者和六个采用 IB 继承者的各种组合的 C def。我想避免使用命名实例,因为这会使我的引导程序显着膨胀并且难以维护。

第二个问题:DryIoc 支持这个吗?我可能会被说服转换。

您正在寻找称为 "instance per graph" 生命周期范围的东西。 autofac 本身不支持它。如果你没有被 autofac 困住,你可以使用 Castle Windsor as explained in this related/duplicate question.

如果您正在寻找 autofac 本身的解决方案,您可以使用 InstancePerMatchingLifetimeScopeInstancePerLifetimeScope.

来实现它

这是您配置容器的方法

private IContainer Build()
{
    ContainerBuilder builder = new ContainerBuilder();

    builder.RegisterType<A>().As<IA>().InstancePerMatchingLifetimeScope("SomeTag");
    builder.RegisterType<B>().As<IB>().InstancePerMatchingLifetimeScope("SomeTag");
    builder.RegisterType<C1>();

    return builder.Build();
}

下面是你如何使用它

[Test]
public void PerGraphLifeStyle()
{
    var container = Build();

    C1 c1;
    C1 c2;
    using (var scope = container.BeginLifetimeScope("SomeTag"))
    {
        c1 = scope.Resolve<C1>();
        Assert.AreSame(c1.A, c1.B.A);
    }

    using (var scope = container.BeginLifetimeScope("SomeTag"))
    {
        c2 = scope.Resolve<C1>();
        Assert.AreSame(c1.A, c1.B.A);
    }

    Assert.AreNotSame(c1.A, c2.A);
}

虚拟 类 我为测试创建的如下

internal interface IA
{
}

class A : IA
{

}

internal interface IB
{
    IA A { get; set; }
}

class B : IB
{
    public B(IA a)
    {
        A = a;
    }

    public IA A { get; set; }
}
class C1
{
    public IA A { get; set; }
    public IB B { get; set; }

    public C1(IA a, IB b)
    {
        A = a;
        B = b;
    }
}

DryIoc (which is mine) it may be directly achieved using Reuse.InResolutionScopeOf中:

container.Register<C1>(setup: Setup.With(openResolutionScope: true), serviceKey: Some.Blah);
container.Register<C2>(setup: Setup.With(openResolutionScope: true), serviceKey: Some.Blah);

container.Register<IA, A>(reuse: Reuse.InResolutionScopeOf(serviceKey: Some.Blah));

就是这样。 openResolutionScope: true 在对象图中创建范围。serviceKey 是 identify/find 图中范围所必需的。例如,如果 C1C2 将实现相同的接口 IC,则不需要服务密钥。您只需说 Reuse.InResolutionScopeOf<IC>(),图中每个 IC 对象将是一个 IA