如何使用条件装饰器通过委托工厂解析服务?
问题描述:
我有一个类hirerachy,看起来像这样:如何使用条件装饰器通过委托工厂解析服务?
public class Foo : IFoo
{
private readonly IBar _bar;
public Foo(IBar bar)
=> _bar = bar;
}
public class Bar : IBar
{
private readonly Func<IFoo> _fooFunc;
private readonly IBaz _baz;
public Bar(Func<IFoo> fooFunc, IBaz baz)
{
_fooFunc = fooFunc;
_baz = baz;
}
}
public class Baz : IBaz
{
}
public class BazDecorator : IBaz
{
private readonly IBaz _decoratee;
public BarDecorator(IBaz decoratee)
=> _decoratee = decoratee;
}
注意Bar
解决了IFoo
时需要Func<IFoo>
,而不是直接IFoo
由于循环依赖的。
我目前的注册看起来喜欢这样的:
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Foo>().As<IFoo>();
builder.RegisterType<Bar>().As<IBar>();
// Func<IFoo> is automatically resolved in AutoFac
builder.RegisterType<Baz>().Named<IBaz>("baz");
builder.RegisterDecorator<IBaz>((c, inner) =>
new BazDecorator(inner),
fromKey: "baz");
}
}
我想只有有条件注册BazDecorator
通过Foo
但不Func<IFoo>
像解决时:
Foo------Bar-----BazDecorator----Baz
\
\
\____Foo----Bar----Baz
我如何注册我的服务在AutoFac中?
答
您需要手动注册Func<IFoo>
,明确地传递正确的参数到Foo
和Bar
组件
builder.Register<Func<IFoo>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return() => new Foo(new Bar(() => ctx.Resolve<IFoo>(), ctx.ResolveNamed<IBaz>("baz")));
});
如果你不想“新” Foo
和Bar
内Register
功能,它也可以通过解决它们从容器中实现,但代码看起来相当讨厌:
builder.Register<Func<IFoo>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return() => ctx.Resolve<IFoo>(
new ResolvedParameter(
(p, cx) => p.Name == "bar",
(p, cx) => cx.Resolve<IBar>(new ResolvedParameter(
(p1, c1) => p1.Name == "baz",
(p1, c1) => c1.ResolveNamed<IBaz>("baz")))));
});
这可以避免吗?因为在我的实际代码中,'Baz'和'BazDecorator'实际上在对象图中非常深,所以我想尽可能避免显式注册我的对象图的大部分。 – rexcfnghk
对不起,我不能想到任何其他解决方案将需要更少的代码或更改您的原始代码... – tdragon
没关系,感谢您的输入无论如何! – rexcfnghk