Is it possible to obtain instance of component being resolved before satisfying property dependency?
public class A
{
public X x { get; set; }
}
public class B
{
public X x { get; set; }
}
public class X
{
public X(object owner) { /* ... */ }
}
Basically if classes A
а также B
are registered in Windsor I want to be able to resolve X
dependency in such a way that it gets instance of the class it was required for.
In plain code it would look like that:
var a = new A();
var x = new X(a);
a.X = x;
Is there a way to do this in Windsor, maybe through some extensibility mechanism?
It looks like some crazy question even for me, so here is some motivation behind it:
X
in the example above is ITracer
который является прокси для TraceSource
это добавляет некоторые биты информации к каждому отслеживаемому сообщению, а именно, уникальный идентификатор владельца и его тип (теперь это только идентификатор - вот почему вопрос - я не могу добраться до экземпляра и вызвать GetType()
в теме).
Краткий пример, чтобы сделать его более понятным. Предположим, у вас есть какой-то сервис IService
и хочу добавить следы к нему самым ненавязчивым способом. Но в приложении может быть несколько десятков экземпляров этого сервиса, поэтому в следах вы хотите различить их по идентификатору / типу. Было бы хорошо, если бы класс получил трассировщик из контейнера и просто писал туда сообщения, когда это было необходимо, не думая об идентификаторах, о конкретных TraceSource
и т.п.
У меня уже есть некоторая инфраструктура, которая позволяет мне писать так:
[TracedTo("NameOfTheTraceSource")]
public class Service : IService
{
public ITracer Tracer { get; set; }
}
И Виндзор правильно разрешает Tracer
быть своим собственным (не совместно используемым с другими объектами) экземпляром ITracer
указывая на TraceSource
с именем NameOfTheTraceSource
, Более того, если я добавлю traceAllMethods = true
к атрибуту - Виндзор автоматически добавит перехватчик, который будет записывать каждый вызов метода в этом экземпляре через тот же Tracer
(и делает это только если соответствует TraceSource
настроены некоторые слушатели - нам не нужно добавлять их на лету). Это просто здорово, потому что ничего от разработчика Service
и это не терпит снижения производительности, когда это не нужно, ни капли. И поэтому я работаю, чтобы сделать это еще более удобным:)
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>();