Castle-Windsor 是否通过 XML 配置支持 ForwardedTypes

发布于 2024-07-07 21:51:49 字数 100 浏览 13 评论 0原文

我有一个实现多个接口的类。 我想通过 XML 注册这些接口。 我找到的只是新 Fluent Interface 的文档。 此选项是否通过 XML 支持? 添加此功能会涉及什么?

I have a class that implements multiple interfaces.
I would like to register these interfaces via XML.
All I've found is documentation for the new Fluent Interface.
Is this option supported via XML?
What would be involved in adding this feature?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断念 2024-07-14 21:51:49

[更新] 现在在 Windsor 2.1 或更高版本中可以实现这一点。 请参阅此处的语法文档。


到目前为止,此功能尚未在 XML 解释器中实现。但是,通过工具添加对其的支持并不困难(显然,当想要添加现有配置解析器中缺少的其他功能时,此技术也很有用)。

因此,首先我们添加一个工具,它将检测何时为某种类型创建处理程序,同时将注册任何转发的服务,以便它们指向现有的处理程序:

public class HandlerForwardingFacility : AbstractFacility
{
  IConversionManager conversionManager;

  protected override void Init()
  {
    conversionManager = (IConversionManager)Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
    Kernel.HandlerRegistered += new HandlerDelegate(Kernel_HandlerRegistered);      
  }

  void Kernel_HandlerRegistered(IHandler handler, ref bool stateChanged)
  {
    if (handler is ForwardingHandler) return;

    var model = handler.ComponentModel;

    if (model.Configuration == null) return;

    var forward = model.Configuration.Children["forward"];
    if (forward == null) return;

    foreach (var service in forward.Children)
    {
      Type forwardedType = (Type)conversionManager.PerformConversion(service, typeof (Type));
      Kernel.RegisterHandlerForwarding(forwardedType, model.Name);
    }
  }
}

当然,我们需要利用它在代码中,对于这个例子,我将有一个突变的鸭子/狗组件,它支持两个单独的服务 - IDuck 和 IDog:

public interface IDog
{
  void Bark();
}

public interface IDuck
{
  void Quack();
}

public class Mutant : IDog, IDuck
{
  public void Bark()
  {
    Console.WriteLine("Bark");
  }

  public void Quack()
  {
    Console.WriteLine("Quack");
  }
}

现在实际配置容器:

 <castle>
  <facilities>
    <facility id="facility.handlerForwarding" type="Example.Facilities.HandlerForwardingFacility, Example" />
  </facilities>
  <components>
    <component id="mutant" service="Example.IDog, Example" type="Example.Mutant, Example">
      <forward>
        <service>Example.IDuck, Example</service>
      </forward>
    </component>
  </components>
</castle>

现在我们可以愉快地执行这样的测试:

  WindsorContainer container = new WindsorContainer(new XmlInterpreter());

  var dog = container.Resolve<IDog>();
  var duck = container.Resolve<IDuck>();

  Assert.AreSame(dog, duck);

希望这会有所帮助。

[Update] This is now possible in Windsor 2.1 or newer. See the documentation for syntax here.


This feature has not been implemented in the XML interpreter as of yet.. however it is not difficult to add support for it via a facility (obviously this technique is also useful when wanting to add other features absent from the existing configuration parser).

So first off we add a facility which will detect when a handler is created for a type, and at the same time will register any of the forwarded services so they point to the existing handler:

public class HandlerForwardingFacility : AbstractFacility
{
  IConversionManager conversionManager;

  protected override void Init()
  {
    conversionManager = (IConversionManager)Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
    Kernel.HandlerRegistered += new HandlerDelegate(Kernel_HandlerRegistered);      
  }

  void Kernel_HandlerRegistered(IHandler handler, ref bool stateChanged)
  {
    if (handler is ForwardingHandler) return;

    var model = handler.ComponentModel;

    if (model.Configuration == null) return;

    var forward = model.Configuration.Children["forward"];
    if (forward == null) return;

    foreach (var service in forward.Children)
    {
      Type forwardedType = (Type)conversionManager.PerformConversion(service, typeof (Type));
      Kernel.RegisterHandlerForwarding(forwardedType, model.Name);
    }
  }
}

And then of course we need to make use of this in code, for this example I'm going to have a mutant duck/dog component that supports two separate services - IDuck and IDog:

public interface IDog
{
  void Bark();
}

public interface IDuck
{
  void Quack();
}

public class Mutant : IDog, IDuck
{
  public void Bark()
  {
    Console.WriteLine("Bark");
  }

  public void Quack()
  {
    Console.WriteLine("Quack");
  }
}

Now to actually configure the container:

 <castle>
  <facilities>
    <facility id="facility.handlerForwarding" type="Example.Facilities.HandlerForwardingFacility, Example" />
  </facilities>
  <components>
    <component id="mutant" service="Example.IDog, Example" type="Example.Mutant, Example">
      <forward>
        <service>Example.IDuck, Example</service>
      </forward>
    </component>
  </components>
</castle>

And now we can happily execute a test like this:

  WindsorContainer container = new WindsorContainer(new XmlInterpreter());

  var dog = container.Resolve<IDog>();
  var duck = container.Resolve<IDuck>();

  Assert.AreSame(dog, duck);

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文