2016-11-10 25 views
0

我为Castle.Windsor创建了自定义工具。 总之。我用我的自定义属性MyComponent标记了组件类的一些属性。在这个设施中我订阅了Kernel.ComponentRegistered。在组件注册时,我检查是否有组件的属性标有属性。如果是,我也使用该属性的值进行组件注册。 的问题是如何让元件本身的对象时,我有IHandler和对象的字符串键:Castle.Windsor如何从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

@AndyLamb我试图解决以下的事情。我有一些课程可能被认为是工厂。它通过属性提供多种服务。所以我想要注册这些服务的组件,将它们的值作为实例。 –

回答

0

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