Я также не большой поклонник использования атрибутов, но мне также не нравится метод .Configure<InjectedMembers>()
, потому что вы привязаны к определенному имени свойства и определенному значению. Способ, который я нашел и который дает вам наибольшую гибкость, заключается в создании собственной стратегии строителя.
Я создал этот простой класс, который выполняет итерацию свойств создаваемого объекта и устанавливает значения его свойств, если тип этого свойства зарегистрирован в контейнере единицы.
public class PropertyInjectionBuilderStrategy:BuilderStrategy
{
private readonly IUnityContainer _unityContainer;
public PropertyInjectionBuilderStrategy(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public override void PreBuildUp(IBuilderContext context)
{
if(!context.BuildKey.Type.FullName.StartsWith("Microsoft.Practices"))
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(context.BuildKey.Type);
foreach (PropertyDescriptor property in properties)
{
if(_unityContainer.IsRegistered(property.PropertyType)
&& property.GetValue(context.Existing) == null)
{
property.SetValue(context.Existing,_unityContainer.Resolve(property.PropertyType));
}
}
}
}
}
Вы регистрируете BuilderStrategy
, создавая UnityContainerExtension
. Вот пример:
public class TestAppUnityContainerExtension:UnityContainerExtension
{
protected override void Initialize()
{
Context.Strategies.Add(new PropertyInjectionBuilderStrategy(Container), UnityBuildStage.Initialization);
}
}
Это регистрируется в контейнере Unity как таковое:
IUnityContainer container = new UnityContainer();
container.AddNewExtension<TestAppUnityContainerExtension>();
Надеюсь, это поможет,
Мэтью