如何在Castle.Windsor中从IHandler获取组件的对象?

时间:2016-11-10 15:29:11

标签: c# .net castle-windsor

我为Castle.Windsor创建了自定义工具。 简而言之。我用自定义属性MyComponent标记了组件类的一些属性。在这个工具中,我订阅了Kernel.ComponentRegistered。在组件注册时,我会检查是否有任何组件属性标记了该属性。如果是,我也使用此属性的值进行组件注册。 问题是当我有IHandler和对象的字符串键时,如何获取组件的对象:

public class ComponentsSearcherFacility : AbstractFacility
{
    protected override void Init()
    {
      Kernel.ComponentRegistered += OnComponentRegistered;
    }

    private void OnComponentRegistered(string key, IHandler handler)
    {
      var serviceProperties = handler.ComponentModel.Implementation
                                                    .GetProperties()
                                                    .Where(p => Attribute.IsDefined(p, typeof(MyComponentAttribute)))
                                                    .ToArray();

      if (!serviceProperties.Any())
        return;

      var componentObject = ?????;

      foreach (var serviceProperty in serviceProperties)
      {
        var interfaces = FindInterfacesRepresentedByProperty(serviceProperty.PropertyType);
        var instance = serviceProperty.GetValue(componentObject, null);
        Kernel.Register(Component.For(interfaces)
                                 .Instance(instance)
                                 .LifestyleSingleton());
      }
    }
  }

暂时我使用这样的黑客:

var componentObject = Kernel.Resolve(handler.ComponentModel.Services.First());

但是虽然它一般都有效但只有在类声明中遵循一些严格的规则才能正确地完成它的工作。无论如何,这很糟糕。

1 个答案:

答案 0 :(得分:0)

正如你所说,这种方法有点限制,看起来工厂组件必须是单身?我认为更好的方法是在注册顶级组件的代码中处理这个问题。您可以将其封装在扩展方法中,以维护注册的流畅样式并允许重用。在您注册顶级组件时,您可以访问该实例,并且可以使用反射来一般性地访问这些属性。