我正在开发一个项目,其中Unity框架用作IoC容器.我的问题涉及使用property-或setter注入将可选依赖项(在本例中为记录器)注入到几个类中.
我不想使用这些可选的依赖项来混乱所有类的构造函数,但是我找不到在Unity中处理它的好方法.根据MSDN文档,您可以通过向属性添加属性来实现此目的:
private ILogger logger; [Dependency] public ILogger Logger { get { return logger; } set { logger = value; } }
我觉得这很难看.在StructureMap中,可以执行以下操作来设置给定类型的所有属性:
SetAllProperties(policy => policy.OfType());
有谁知道在Unity中是否有可能做类似的事情?
编辑:
Kim Major建议使用这种方法,也可以通过代码实现.
我会对如何自动为所有匹配属性执行此操作的示例感兴趣.
我也不喜欢这些属性
您可以使用unity容器的Configure方法完成所有操作:
首先注册类型
unityContainer.RegisterType( new ContainerControlledLifetimeManager());
如果你有多个构造函数,你必须这样做,所以Unity调用无参数构造函数(如果没有设置Unity将用于最胖的构造函数)
unityContainer.Configure() .ConfigureInjectionFor ( new InjectionConstructor());
设置属性依赖
unityContainer.Configure() .ConfigureInjectionFor ( new InjectionProperty( "SomePropertyName", new ResolvedParameter ()));
配置方法依赖
unityContainer.Configure() .ConfigureInjectionFor ( new InjectionMethod( "SomeMethodName", new ResolvedParameter ()));
我也不是使用属性的忠实粉丝,但我也不喜欢这个.Configure
方法,因为你绑定了特定的属性名称和特定值.我发现的方式为您提供了最大的灵活性,就是创建自己的构建器策略.
我创建了这个简单的类,它迭代正在构建的对象的属性,并在已使用unity容器注册该属性的类型时设置其属性值.
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();
希望这会有所帮助,
马修
您发布的原始示例看起来非常麻烦,但您可以使用此类自动实现的属性来帮助清理该代码:
[Dependency] public ILogger Logger { get; set; }
使用Unity 2.1,这也可以:
var container = new UnityContainer() .RegisterType() .RegisterType ( new InjectionProperty("Logger", new ResolvedParameter ()));
SomeImplementaion类的注入属性正好
public ILogger Logger { get; set; }