是否有可能在满足属性依赖性之前获取正在解析的组件实例?

时间:2012-12-07 20:15:17

标签: castle-windsor windsor-3.0

public class A
{
    public X x { get; set; }
}

public class B
{
    public X x { get; set; }
}

public class X
{
    public X(object owner) { /* ... */ }
}

基本上,如果在温莎中注册了类AB,我希望能够以这样的方式解析X依赖关系,以便获取所需的类的实例。

在普通代码中,它看起来像是:

var a = new A();
var x = new X(a);
a.X = x;

有可能通过一些可扩展性机制在温莎这样做吗?


对我来说,这看起来像是一个疯狂的问题,所以这背后有一些动机:

上面示例中的XITracer,它是TraceSource的代理,它为每个跟踪的消息添加一些信息,即所有者的唯一ID及其类型(现在它只是ID - 这就是为什么问题 - 我无法访问实例并在其上调用GetType())。

一个简单的例子,使其更清晰。假设您有一些服务IService,并希望以最非侵入性的方式向其添加跟踪。但是在应用程序中可能有十几个此服务的实例,因此在跟踪中您希望通过ID /类型区分它们。如果类从容器中接收到它的跟踪器并且在需要时只在那里写消息而不考虑ID,具体TraceSource等,那将是很好的。

我已经有了一些允许我这样写的基础设施:

[TracedTo("NameOfTheTraceSource")]
public class Service : IService
{
    public ITracer Tracer { get; set; }
}

Windsor正确地将Tracer解析为ITracer自己的(不与其他对象共享)实例,指向名为TraceSource的{​​{1}} NameOfTheTraceSource。此外,如果我向属性添加traceAllMethods = true - Windsor将自动添加拦截器,该拦截器将通过相同的Tracer在此实例上记下每个方法调用(只有在相应的TraceSource具有此功能时才会执行此操作一些听众配置 - 我们不必支持动态添加它们。这真是太棒了,因为它不需要来自Service的开发人员的任何,并且在不需要时不会出现性能下降,而不是一点点。因此,我正在努力使这更方便:)

1 个答案:

答案 0 :(得分:1)

好的,我想你想要的是一个设施。这是一个简单的(没有错误检查),可能是你正在寻找的(或至少指向正确的方向):

public class XFacility : AbstractFacility
{
    protected override void Init()
    {
        this.Kernel.ComponentCreated += KernelOnComponentCreated;
    }

    private void KernelOnComponentCreated(ComponentModel model, object instance)
    {
        var props =
            instance.GetType().GetProperties().Where(p => p.CanWrite && p.PropertyType == typeof (X));
        if (props.Any())
        {
            var pi = props.First();
            pi.SetValue(instance, new X(instance), null);
        }
    }
}

现在确保在进行任何解析之前将设施添加到容器中:

var container = new WindsorContainer();
container.AddFacility<XFacility>();
container.Register(Component.For<A>(),
                    Component.For<B>()
    );

var a = container.Resolve<A>();