public class A
{
public X x { get; set; }
}
public class B
{
public X x { get; set; }
}
public class X
{
public X(object owner) { /* ... */ }
}
基本上,如果在温莎中注册了类A
和B
,我希望能够以这样的方式解析X
依赖关系,以便获取所需的类的实例。
在普通代码中,它看起来像是:
var a = new A();
var x = new X(a);
a.X = x;
有可能通过一些可扩展性机制在温莎这样做吗?
对我来说,这看起来像是一个疯狂的问题,所以这背后有一些动机:
上面示例中的X
是ITracer
,它是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
的开发人员的任何,并且在不需要时不会出现性能下降,而不是一点点。因此,我正在努力使这更方便:)
答案 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>();