我怎样才能在温莎城堡的分辨率管道中传递一个参数?

时间:2016-06-08 05:46:22

标签: c# dependency-injection castle-windsor typed-factory-facility

我有一个抽象工厂(由Windsor使用.AsFactory()管理),其解析的其中一个组件需要特定的依赖项。通常情况下,这不会成为问题,因为Windsor可以查看为该抽象注册的实现并提供它。但是,该依赖项有多个实现,我想使用与传递给顶级工厂的相同的参数来选择一个。

例如:

public interface IAbstractFactory
{
    IComponent Create(int argument);
}

public class MyComponent : IComponent
{
    public MyComponent(IDependency dependency) { }
}

public interface IDependencyFactory
{
    IDependency Create(int argument); // same argument as above
}

我想使用Windsor工厂创建IDependency注入MyComponent的实例,其中相同的参数已传入IAbstractFactory 。我希望Windsor使用IDependency自动解析IDependencyFactory并将其提供给MyComponent,因为我不想将参数传递给{{1}我称之为。所选择的MyComponent的具体实现需要基于传递给IDependency的相同参数来完成。此过程可能需要在整个解决方案管道中继续,使用相同的IAbstractFactory.Create(argument)选择更多组件。

选择实现的具体逻辑将查找特定类属性的存在并尝试匹配其上的值,如果无法找到,则默认为Windsor的默认选择行为。< / p>

我怀疑使用自定义处理程序或argument的实现方法可以实现此目的,但我无法将各个部分组合在一起。

使用一些更高级的注册和组件选择功能是否有合理的方法来处理这个问题?

1 个答案:

答案 0 :(得分:1)

你能解释一下大局吗?如何使用IComponents或IDependency以及由谁使用?

我要求的原因如下:

  1. 如果你在高级中知道int参数和所需的IDependency之间的映射,并且它映射了单个IDependency,那么我就不会添加工厂而只是在安装程序中直接声明这个依赖: / p>

        container.Register(
            Component.For<IDependency>()
                .ImplementedBy<SomeDependency>()
                .Named("SomeDependency"),
            Component.For<IComponent>()
                .ImplementedBy<MyComponent>()
                .DependsOn(Dependency.OnComponent("dependency","SomeDependency")));
    
  2. 如果特定组件可能需要多个IDependency来使用,那么我将更改MyComponent以依赖于IDependencyFactory本身和IDependency来声明它应答的int参数。这些方面的东西:

    public interface IDependency
    {
        int Argument { get; set; }
    }
    public abstract class DependencyBase : IDependency
    {
        public DependencyBase(int argument) { Argument = argument; }
        public int Argument { get; set; }
    }
    
    public class DependencyA : DependencyBase { public DependencyA() : base(1) {} }
    public class DependencyB : DependencyBase { public DependencyB() : base(2) {} }
    public interface IDependencyFactory
    {
        IDependency Create(int argument);
    }
    
    public interface IComponent { }
    public class MyComponent : IComponent
    {
        public MyComponent(IDependencyFactory dependencyFactory)
        {
            DependencyFactory = dependencyFactory;
        }
    
        public IDependencyFactory DependencyFactory { get; set; }
    }
    public class Installer : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<IDependency>().ImplementedBy<DependencyA>(),
                Component.For<IDependency>().ImplementedBy<DependencyB>(),
                Component.For<IDependencyFactory>().AsFactory(),
                Component.For<IComponent>().ImplementedBy<MyComponent>());
        }
    }
    

    并实现一个ITypedFactoryComoponentSelector,它将通过参数intager从容器中解析。

  3. 基本上,如果您已经使用了AsFactory,我会说“我为什么需要实现工厂”(或ITypedFactoryComoponentSelector),但是TypedFactoryFacility是用于映射的开箱即用形式不同对象类型之间到不同的返回对象而不是不同的对象实例。也许可以阅读更多关于它的城堡文档。

    希望这有帮助

    我已经将IComponent和IDependency类更改为具有DoSomething()函数,因此我可以实际执行某些操作。

        public interface IDependency
    {
        void DoSomething();
        int Argument { get; set; }
    }
    public abstract class DependencyBase : IDependency
    {
        public DependencyBase(int argument) { Argument = argument; }
        public void DoSomething() { }
        public int Argument { get; set; }
    }
    

    现在,MyComponent实现如下所示:

        public class MyComponent : IComponent
    {
        public MyComponent(IDependencyFactory dependencyFactory)
        {
            DependencyFactory = dependencyFactory;
        }
    
        public void DoSomething(int argument)
        {
            var selectedDependency = DependencyFactory.Create(argument);
            selectedDependency.DoSomething();
        }
    
        public IDependencyFactory DependencyFactory { get; set; }
    }
    

    我已经实现了一个ITypedFactoryComponentSelector:

        public class DependencyComponentSelector : ITypedFactoryComponentSelector
    {
        public DependencyComponentSelector(IKernel kernel)
        {
            Kernel = kernel;
        }
        public Func<IKernelInternal, IReleasePolicy, object> SelectComponent(MethodInfo method, Type type, object[] arguments)
        {
            return (k, r) =>
            {
                return from dependency in k.ResolveAll<IDependency>()
                       where dependency.Argument == int.Parse(arguments[0].ToString())
                       select dependency;
            };
        }
        public IKernel Kernel { get; set; }
    }
    

    (显然应该添加输入验证以检查是否已经为正确的工厂方法调用了它)

    然后在安装程序中将工厂的注册更改为:

    Component.For<DependencyComponentSelector>(),
    Component.For<IDependencyFactory>().AsFactory(c=> c.SelectedWith<DependencyComponentSelector>()),