Castle Windsor使用组件ID /名称作为参数

时间:2017-05-17 13:42:44

标签: c# castle-windsor castle-windsor-3

我有一个项目,我使用Castle Windsor进行依赖注入,更具体地说,我正在使用XML配置,因此可以根据参数以不同方式运行公共服务。

例如(非常简化):

<component id="Processors" service="System.Collections.Generic.IEnumerable`1[[Services.Interfaces.IProcessor, Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" type="System.Collections.Generic.List`1[[Services.Interfaces.IProcessor, Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]">
  <parameters>
    <collection>
      <list>
        <item>${Processor1}</item>
        <item>${Processor2}</item>
      </list>
    </collection>
   <parameters>
</component>

<component id="Processor1" service="Services.Interfaces.IProcessor" type="Services.TestProcessor, Services">
  <parameters>
        <example>LIVE</example>
        <id>Processor1</id>
  </parameters>
</component>

<component id="Processor2" service="Services.Interfaces.IProcessor" type="Services.TestProcessor, Services">
  <parameters>
        <example>TEST</example>
        <id>Processor2</id>
  </parameters>
</component>

在运行时,我们解析名为Processors的组件,并遍历调用每个项目的所有项目。

正如您在上面的示例中所看到的,我们在每个处理器上都有一个名为id的参数,这主要用于日志记录,并且非常有用于跟踪哪个处理器存在问题(以及通过代理配置)。理想情况下,如果我可以重用组件配置中的id(减少配置),那将是很好的。

关于如何做到这一点的任何想法?

1 个答案:

答案 0 :(得分:1)

使用&#34;组件ID /名称作为参数&#34;另外,您可以定义自定义Castle.MicroKernel.ISubDependencyResolver,例如:

public class InjectIdSubDependencyResolver : ISubDependencyResolver
{
    private const string SpecialName = "id";

    public bool CanResolve(
        CreationContext context, ISubDependencyResolver contextHandlerResolver, 
        ComponentModel model, DependencyModel dependency) 
        => 
        dependency.TargetType == typeof(string)
        &&
        dependency.DependencyKey == SpecialName
        &&
        dependency.Parameter?.ConfigValue == null;

    public object Resolve(
        CreationContext context, ISubDependencyResolver contextHandlerResolver, 
        ComponentModel model, DependencyModel dependency) 
        => model.Name;
}

你这样设置:

        IWindsorContainer wc = ...;
        wc.Kernel.Resolver.AddSubResolver(new InjectIdSubDependencyResolver());

然后XML配置得到简化......

<component id="Processor1" service="Services.Interfaces.IProcessor" type="Services.TestProcessor, Services">
  <parameters>
        <example>LIVE</example>
  </parameters>
</component>

<component id="Processor2" service="Services.Interfaces.IProcessor" type="Services.TestProcessor, Services">
  <parameters>
        <example>TEST</example>
  </parameters>
</component>

注意

此外,不是在容器中注册通用列表,而是使用一些第二类以及Collection Sub Dependency resolver,即

public class Processors {
    public Processors(IEnumerable<IProcessor> collection) { /**/ }
}

...甚至尝试使用Typed Factories

希望它有所帮助。