根据触发解析的父树解析参数?
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 本身的解决方案,您可以使用 InstancePerMatchingLifetimeScope
或 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;
}
}
在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 图中范围所必需的。例如,如果 C1
和 C2
将实现相同的接口 IC
,则不需要服务密钥。您只需说 Reuse.InResolutionScopeOf<IC>()
,图中每个 IC
对象将是一个 IA
。
我有类似的代码:
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 本身的解决方案,您可以使用 InstancePerMatchingLifetimeScope
或 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;
}
}
在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 图中范围所必需的。例如,如果 C1
和 C2
将实现相同的接口 IC
,则不需要服务密钥。您只需说 Reuse.InResolutionScopeOf<IC>()
,图中每个 IC
对象将是一个 IA
。