我可以将子容器用作具有复杂依赖关系的组件的工厂吗?

时间:2016-07-14 08:06:14

标签: c# dependency-injection castle-windsor

我有一个包含多个依赖项的组件:

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类,而有时我想要“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找出正确的依赖关系。但我不知道如何进行注册以使其正常工作。

1 个答案:

答案 0 :(得分:0)

我最终使用了命名依赖项:

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"));

不是我所希望的(我讨厌使用名字),但在我的情况下还不错。