繁体   English   中英

如何在温莎城堡的解决方案管道中传递参数?

[英]How can I pass an argument down the resolution pipeline in Castle Windsor?

我有一个抽象工厂(由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工厂创建注入到MyComponentIDependency实例,其参数与传递给IAbstractFactory 参数相同 我想温莎自动解决的IDependency使用IDependencyFactory并将其提供给MyComponent ,因为我不希望有参数传递到MyComponent时候我把它。 选择的IDependency的特定实现需要基于传递给IAbstractFactory.Create(argument)的相同参数来完成。 该过程可能需要在整个解决方案流程中继续进行,并使用相同的argument选择更多的组件。

选择实现的特定逻辑将查找特定类属性的存在并尝试匹配其上的值,如果找不到该属性,则默认为Windsor的默认选择行为。

我怀疑有一种方法可以使用自定义处理程序或ISubDependencyResolver的实现来实现,但是我很难将各个部分组合在一起。

仅使用一些更高级的注册和组件选择功能,是否有合理的方法来解决此问题?

您能否对大局有更多的解释? 如何使用IComponent或IDependency?谁使用?

我要求这样做的原因如下:

  1. 如果int参数和所需的IDependency之间的映射是您高级已知的,并且它映射一个IDependency,那么我将不添加工厂,而直接在安装程序中声明此依赖关系:

      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从容器中解析。

基本上,如果您已经使用了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>()),

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM