【问题标题】:Use component id in Castle Windsor generic object configuration在 Castle Windsor 通用对象配置中使用组件 ID
【发布时间】:2010-06-08 16:16:16
【问题描述】:

两个问题合二为一,但非常相关。

Castle Windsor 是否可以解析配置条目,例如 -

Assembly.Namespace.Object1`2[[${ComponentId1}],[${ComponentId2}]],Assembly

其中 ComponentId1 和 ComponentId2 被定义为组件。 Castle Windsor 似乎没有解析 ComponentId,它只是在 Castle.Windsor 程序集中寻找 ComponentId1。

如果你不能做第一个问题,第二个问题就会发挥作用。如果您必须使用完整的程序集引用而不是 ComponentId,您如何将任何参数传递给正在创建的对象?例如设置 ComponentId1.Field1 = "blah",或者传递一些东西给 ComponentId1 的构造函数

希望这是有道理的

更新-

在请求代码之后,我拼凑了以下 -

对象

public class Wrapper<T, T1> where T : ICollector where T1:IProcessor
{
    private T _collector;
    private T1 _processor;

    public Wrapper(T collector, T1 processor)
    {
        _collector = collector;
        _processor = processor;
    }

    public void GetData()
    {
        _collector.CollectData();
        _processor.ProcessData();
    }

}

public class Collector1 : ICollector
{
    public void CollectData()
    {
        Console.WriteLine("Collecting data from Collector1 ...");
    }
}

public class Processor1 : IProcessor
{
    public void ProcessData()
    {
        Console.WriteLine("Processing data from Processor1  ...");
    }
}

在示例中对每种类型的对象重复了 3 次

配置

<components>
<component id="Collector1"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector1, CastleWindsorPlay"/>
<component id="Collector2"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector2, CastleWindsorPlay"/>
<component id="Collector3"
           service="CastleWindsorPlay.ICollector, CastleWindsorPlay"
           type="CastleWindsorPlay.Collector3, CastleWindsorPlay"/>
<component id="Processor1"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor1, CastleWindsorPlay"/>
<component id="Processor2"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor2, CastleWindsorPlay"/>
<component id="Processor3"
           service="CastleWindsorPlay.IProcessor, CastleWindsorPlay"
           type="CastleWindsorPlay.Processor3, CastleWindsorPlay"/>
<component id="Wrapper1"
           type="CastleWindsorPlay.Wrapper`2[[CastleWindsorPlay.Collector1, CastleWindsorPlay],[CastleWindsorPlay.Processor3, CastleWindsorPlay]], CastleWindsorPlay" />
  </components>

实例化

        var wrapper = (Wrapper<ICollector, IProcessor>) container.Resolve("Wrapper1");
        wrapper.GetData();

虽然这个错误消息的简短示例错误 -

无法创建组件“Wrapper1”,因为它需要满足依赖关系。 Wrapper1 正在等待以下依赖项:

服务: - 未注册的 CastleWindsorPlay.Collector1。 - 未注册的 CastleWindsorPlay.Processor3。

有趣的是,我可以在调用包装器之前单独解析 Collector1 和 Processor3,但包装器仍然看不到它们。

这是一个基本示例,接下来我想做的是在实例化 Wrapper 时,在收集器和/或处理器上设置一个属性。所以它可能类似于 Collector.Id = 10,但在定义包装器的配置中设置。根据收集器组件定义进行设置将不起作用,因为我希望能够使用不同的 Id 实例化每个收集器的多个副本

更新 2

我真正想做的是拥有 -

<components>
<component id="Wrapper1"
           type="CastleWindsorPlay.Wrapper`2[${Collector1}(id=1)],[${Processor3}]], CastleWindsorPlay" />
<component id="Wrapper2"
           type="CastleWindsorPlay.Wrapper`2[${Collector1}(id=3)],[${Processor3}]], CastleWindsorPlay" />
  </components>

然后将另一个对象定义为

<component id="Manager"
           type="CastleWindsorPlay.Manager,CastleWindsorPlay">
  <parameters>
    <wrappers>
      <array>
        <item>${Wrapper1}</item>
        <item>${Wrapper2}</item>
      </array>
    </wrappers>
  </parameters>

那么最后在代码中就可以调用了-

var manager = (Manager)container.Resolve("Manager");

这应该返回管理器对象,其中填充了一个包装器数组,并且包装器配置了正确的收集器和转换器。

我知道 Castle 配置中有错误,这就是我问这个问题的原因,我不知道如何设置配置来做我想要的,或者即使可以做到在温莎城堡

【问题讨论】:

  • 导致您出现这种情况的根本问题是什么?另外,一旦解决了这个对象,你将如何使用它?你会在哪里注射?请发布一些代码来说明您要实现的目标。
  • ComponentId1 和 ComponentId2 并被注入到 Object1 以改变它的行为。不知道混乱在哪里。在 Object1 中,我可以定义诸如私有 T ComponentOne 之类的属性,这些属性将具有注入对象的行为
  • 可能是我误用了温莎城堡。我正在尝试基本上使用 Castle Windsor 通过 config 设置一系列对象。所以我可以有一个对象数组,例如 { Object1, Object2, Object3。可以通过 Castle 配置更改此数组以及随后的系统行为,而无需重新构建程序集。
  • 再次,请发布代码,一个简单的测试用例之类的。否则,试图回答你问题的人(比如我)必须猜测和/或更加努力地工作。
  • AFAIK 你不能用 Windsor OOTB 做到这一点,但它可以通过一些扩展来实现。但请发布代码。

标签: c# generics castle-windsor


【解决方案1】:

更新2

好的,现在开始有意义了 :) 就像我从一开始就说的那样,看起来您正在寻找服务覆盖:

<components>
<component id="Wrapper1" type="CastleWindsorPlay.Wrapper`2[<<closing types go here>>]/>
   <parameters>
      <collector>${collector1WithId1}</collector>
      <collector>${processor3WithId3}</collector>
   </parameters>
</component>

<component id="Wrapper2" type="CastleWindsorPlay.Wrapper`2[<<closing types go here>>]/>
   <parameters>
      <collector>${collector1WithId5}</collector>
      <collector>${processor3WithId8}</collector>
   </parameters>
</component>
</components>

更新

好的,谢谢你的例子。您收到错误的原因是您将 component Collector1component Processor3 注册为 service @987654326 @ 和 IProcessor 分别。 您没有Collector1Processor3服务,因此当 Windsor 尝试提供它们时,它找不到它们,因此出现异常消息。

您需要将它们注册为适当的服务才能使其正常工作。


我不知道你想在这里做什么,但我假设你正在寻找 service overridesinline parameters

【讨论】:

  • 抱歉,服务覆盖和内联参数没有回答如何在使用泛型的组件定义中使用组件 ID,或者如何将参数传递给通过泛型传递的对象。
  • 嗯,很有趣。不知道如何做我想做的事,或者即使我可以和温莎城堡一起做。这个想法是,在配置中,我可以使用刚刚在配置中定义的收集器和处理器声明新的包装器。我可以让它工作的唯一方法是在配置和解析中定义收集器(例如 Wrapper = resolve 等)。这打败了对象。第二个要求是我可以将不同的参数传递给为 Wrapper 定义的每个收集器。所以说 Wrapper1 使用 Collector1,将 Id=1 传递给 Collector,Wrapper2 使用 Collector1,传递 Id=2,等等
  • 我不明白的是 - 如果你想解析 classes Collector1, Processor3 为什么要将它们注册为 interfaces ?
  • 我刚刚说过我删除了那些,这是一个错误。我添加了第二个更新,以再次尝试清除我真正想要询问的内容
  • K,你可能有我要找的东西,我只是从错误的角度来看它。让我快速玩一下你的建议
猜你喜欢
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
相关资源
最近更新 更多