2

我有类似这样的代码:

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 实例生命周期功能应该处理这个问题,但发布的示例只有一层,而不是两层。

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

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

4

2 回答 2

4

DryIoc(这是我的)中,可以使用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需要在图中识别/查找范围。例如,如果C1并且C2将实现相同的接口IC,则不需要服务密钥。你只是说Reuse.InResolutionScopeOf<IC>(),它对于图IA中的每个IC对象都是一个。

于 2015-05-15T13:35:49.147 回答
2

您正在寻找称为“每个图的实例”生命周期范围的东西。autofac 本身不支持它。如果您不使用 autofac,则可以按照相关/重复问题中的说明使用 Castle Windsor

如果您正在寻找 autofac 本身的解决方案,您可以使用InstancePerMatchingLifetimeScopeor来实现它InstancePerLifetimeScope

这是您配置容器的方式

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;
    }
}
于 2015-05-12T21:57:34.173 回答