我可以将子容器用作具有复杂依赖关系的组件的工厂吗?
Can I use child container as factory for component with complex dependencies?
我有一个具有多个依赖项的组件:
class Service
{
public Service(IDependencyA a, IDependencyB b, ...) { ... }
}
其中某些依赖项具有单一实现:
class CommonDependencyA : IDependencyA
{
...
}
有些有多个实现:
class FooDependencyB : IDependencyB
{
public FooDependencyB(IDependencyC c, ...) { ... }
}
class BarDependencyB : IDependencyB
{
public BarDependencyB(IDependencyC c, ...) { ... }
}
class FooDependencyC : IDependencyC
{
...
}
class BarDependencyC : IDependencyC
{
...
}
有时我想使用 "Bar" 实现来解析 Service
class,而其他时候我想要 "Foo" 实现。
我正在考虑使用子容器进行注册。这样我可以做类似的事情:
public Service CreateService(IWindsorContainer parent, FooBarType type)
{
using(IWindsorContainer child = SetupChildContainer(parent))
{
if (type == FooBarType.Foo)
{
child.Register(Component.For<IDependencyC>.ImplementedBy<FooDependencyC>().LifeStyle.Transient);
child.Register(Component.For<IDependencyB>.ImplementedBy<FooDependencyB>().LifeStyle.Transient);
...
}
else
{
//register "Bar" implementations
}
child.Register(Component.For<Service>.LifeStyle.Transient);
return child.Resolve<Service>();
}
}
然后我可以将这个方法重构为一个工厂,并在父容器中注册这个工厂。
我不喜欢这种方法的地方是每次我需要解析服务时,我都必须进行注册。我还读过一个声明,使用子容器几乎总是错误的解决方案。那么,我做错了吗?有更好的方法吗?我宁愿只注册所有组件一次,然后调用类似:
var fooService = container.Resolve<Service>(new []{FooBarType.Foo});
并让 Widsor 找出正确的依赖关系。但我不知道如何进行注册才能使其正常工作。
我最终使用了命名依赖项:
container.Register(Component.For<IDependencyA>().ImplementedBy<CommonDependencyA>());
container.Register(Component.For<IDependencyC>().ImplementedBy<FooDependencyC>()
.Named("FooDependencyC"));
container.Register(Component.For<IDependencyB>().ImplementedBy<FooDependencyB>()
.Named("FooDependencyB")
.DependsOn(Dependency.OnComponent(typeof(IDependencyC), "FooDependencyC"));
container.Register(Component.For<Service>().
.Named("FooService")
.DependsOn(Dependency.OnComponent(typeof(IDependencyB), "FooDependencyB"));
不是我所希望的(我讨厌使用名字),但对我来说已经足够好了。
我有一个具有多个依赖项的组件:
class Service
{
public Service(IDependencyA a, IDependencyB b, ...) { ... }
}
其中某些依赖项具有单一实现:
class CommonDependencyA : IDependencyA
{
...
}
有些有多个实现:
class FooDependencyB : IDependencyB
{
public FooDependencyB(IDependencyC c, ...) { ... }
}
class BarDependencyB : IDependencyB
{
public BarDependencyB(IDependencyC c, ...) { ... }
}
class FooDependencyC : IDependencyC
{
...
}
class BarDependencyC : IDependencyC
{
...
}
有时我想使用 "Bar" 实现来解析 Service
class,而其他时候我想要 "Foo" 实现。
我正在考虑使用子容器进行注册。这样我可以做类似的事情:
public Service CreateService(IWindsorContainer parent, FooBarType type)
{
using(IWindsorContainer child = SetupChildContainer(parent))
{
if (type == FooBarType.Foo)
{
child.Register(Component.For<IDependencyC>.ImplementedBy<FooDependencyC>().LifeStyle.Transient);
child.Register(Component.For<IDependencyB>.ImplementedBy<FooDependencyB>().LifeStyle.Transient);
...
}
else
{
//register "Bar" implementations
}
child.Register(Component.For<Service>.LifeStyle.Transient);
return child.Resolve<Service>();
}
}
然后我可以将这个方法重构为一个工厂,并在父容器中注册这个工厂。
我不喜欢这种方法的地方是每次我需要解析服务时,我都必须进行注册。我还读过一个声明,使用子容器几乎总是错误的解决方案。那么,我做错了吗?有更好的方法吗?我宁愿只注册所有组件一次,然后调用类似:
var fooService = container.Resolve<Service>(new []{FooBarType.Foo});
并让 Widsor 找出正确的依赖关系。但我不知道如何进行注册才能使其正常工作。
我最终使用了命名依赖项:
container.Register(Component.For<IDependencyA>().ImplementedBy<CommonDependencyA>());
container.Register(Component.For<IDependencyC>().ImplementedBy<FooDependencyC>()
.Named("FooDependencyC"));
container.Register(Component.For<IDependencyB>().ImplementedBy<FooDependencyB>()
.Named("FooDependencyB")
.DependsOn(Dependency.OnComponent(typeof(IDependencyC), "FooDependencyC"));
container.Register(Component.For<Service>().
.Named("FooService")
.DependsOn(Dependency.OnComponent(typeof(IDependencyB), "FooDependencyB"));
不是我所希望的(我讨厌使用名字),但对我来说已经足够好了。