.net Unity中没有属性的Setter /属性注入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/515028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setter / property injection in Unity without attributes
提问by LittleBoyLost
I am working on a project where the Unity framework is used as the IoC container. My question relates to injecting an optional dependency (in this case a logger) into several classes using property- or setter injection.
我正在开发一个使用 Unity 框架作为 IoC 容器的项目。我的问题涉及使用属性或 setter 注入将可选依赖项(在本例中为记录器)注入多个类。
I do not want to clutter the constructors of all my classes with these optional dependencies, but I cannot find a good way to handle this in Unity. The way you would do this is, according to the MSDN documentation, by adding an attribute to the property:
我不想用这些可选的依赖项来混淆我所有类的构造函数,但我找不到在 Unity 中处理这个问题的好方法。根据MSDN 文档,您可以通过向属性添加属性来执行此操作:
private ILogger logger;
[Dependency]
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
I find this very ugly. In StructureMapone could do the following to set all properties of a given type:
我觉得这非常丑陋。在StructureMap 中,可以执行以下操作来设置给定类型的所有属性:
SetAllProperties(policy => policy.OfType<ILog>());
Does anyone know if it is possible to do something similar in Unity?
有谁知道是否可以在 Unity 中做类似的事情?
Edit:
编辑:
Kim Major suggests using this approachwhich can also be achieved through code.
I would be interested in examples of how to do this automatically for all matching properties.
我会对如何为所有匹配的属性自动执行此操作的示例感兴趣。
回答by t3mujin
I don't like those attributes also
我也不喜欢这些属性
You can do all using the Configuremethod of the unity container:
您可以使用统一容器的Configure方法完成所有操作:
First register the type
首先注册类型
unityContainer.RegisterType<MyInterface,MyImpl>(
new ContainerControlledLifetimeManager());
If you have multiple constructors you'll have to do this so Unity invokes the parameterless constructor (if none set Unity will go for the fattest one)
如果您有多个构造函数,则必须执行此操作,以便 Unity 调用无参数构造函数(如果未设置,则 Unity 将使用最胖的构造函数)
unityContainer.Configure<InjectedMembers>()
.ConfigureInjectionFor<MyImpl>(
new InjectionConstructor());
Setting property dependency
设置属性依赖
unityContainer.Configure<InjectedMembers>()
.ConfigureInjectionFor<MyImpl>(
new InjectionProperty(
"SomePropertyName",
new ResolvedParameter<MyOtherInterface>()));
Configuring method dependency
配置方法依赖
unityContainer.Configure<InjectedMembers>()
.ConfigureInjectionFor<MyImpl>(
new InjectionMethod(
"SomeMethodName",
new ResolvedParameter<YetAnotherInterface>()));
回答by Matthew
I am also not a big fan of using attributes but I also don't like the .Configure<InjectedMembers>()method because you're bound to a specific property name and specific value. The way I've found that gives you the most flexibility is to create your own builder strategy.
我也不喜欢使用属性,但我也不喜欢该.Configure<InjectedMembers>()方法,因为您绑定到特定的属性名称和特定值。我发现为您提供最大灵活性的方法是创建您自己的构建器策略。
I created this simple class that iterates the properties of an object being built up and sets its property values if the type of that property has been registered with the unity container.
我创建了这个简单的类,它迭代正在构建的对象的属性,并在该属性的类型已注册到统一容器时设置其属性值。
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));
}
}
}
}
}
You register your BuilderStrategyby creating a UnityContainerExtension. Here is an example:
您BuilderStrategy通过创建一个UnityContainerExtension. 下面是一个例子:
public class TestAppUnityContainerExtension:UnityContainerExtension
{
protected override void Initialize()
{
Context.Strategies.Add(new PropertyInjectionBuilderStrategy(Container), UnityBuildStage.Initialization);
}
}
That gets registered with the Unity container as such:
这会在 Unity 容器中注册,如下所示:
IUnityContainer container = new UnityContainer();
container.AddNewExtension<TestAppUnityContainerExtension>();
Hope this helps,
Matthew
希望这会有所帮助,
马修
回答by RamonH
The original example you posted does look very cumbersome, but you can use auto-implemented properties like this to help clean that code up:
您发布的原始示例确实看起来很麻烦,但是您可以使用这样的自动实现的属性来帮助清理该代码:
[Dependency]
public ILogger Logger { get; set; }
回答by Oleksandr Lytvyn
With Unity 2.1 this would work as well:
使用 Unity 2.1 这也可以:
var container = new UnityContainer()
.RegisterType<ILogger, Logger>()
.RegisterType<ISomeInterface, SomeImplementaion>(
new InjectionProperty("Logger", new ResolvedParameter<ILogger>()));
The injected property of SomeImplementaion class is just
SomeImplementaion 类的注入属性只是
public ILogger Logger { get; set; }
回答by Johan Leino
You could try this:
你可以试试这个:
this code in MyClass
MyClass 中的这段代码
[InjectionMethod]
public void Initialize(
[Dependency] ILogger logger
and then calling it by:
然后通过以下方式调用它:
unitycontainer.BuildUp<MyClass>(new MyClass());
unity will then call Initialize method with the dependency from the container and then u can save it in a private variable in MyClass or something...
unity 然后将使用来自容器的依赖项调用 Initialize 方法,然后您可以将其保存在 MyClass 或其他东西的私有变量中...
回答by Kim Major
The following walkthrough shows one way of doing it through configuration. You can of course wire it through code as well. http://aardvarkblogs.wordpress.com/unity-container-tutorials/10-setter-injection/
以下演练展示了通过配置执行此操作的一种方法。您当然也可以通过代码连接它。 http://aardvarkblogs.wordpress.com/unity-container-tutorials/10-setter-injection/
回答by NooBody
Have a look at the UnityConfigurationproject for convention-based configuration. It works pretty well, though i have an issue while looking up multiple implementations using ResolveAll<IType>(). See this Question.
查看基于约定的配置的UnityConfiguration项目。它工作得很好,尽管我在使用ResolveAll<IType>(). 看到这个问题。
container.RegisterInstance(typeof (ILogger), LoggerService.GetLogger());
container.Configure(c => c.Scan(scan =>
{
scan.AssembliesInBaseDirectory(a => a.FullName.StartsWith("My.Company")); // Filter out everthing that are not from my assemblies
scan.InternalTypes();
scan.With<SetAllPropertiesConvention>().OfType<ILogger>();
}));
回答by Manish Kumawat
You can inject your class with unity container.
您可以使用统一容器注入您的课程。
for example if you have a class "MyClass" and you have dependency on two interface "IExample1" and "IExample2" and you don't want to define parameter for them in constructor , then follow below steps
例如,如果您有一个类“MyClass”并且您依赖于两个接口“IExample1”和“IExample2”,并且您不想在构造函数中为它们定义参数,那么请按照以下步骤操作
Step 1.Register both the interfaces in unity container
步骤 1.在统一容器中注册两个接口
IUnityContainer container = new UnityContainer();
container.RegisterType<IExample1,Impl1>();
container.RegisterType<IExample2,Impl2>();
//resolve class MyClass
var myClass = container.Resolve<MyClass>();
Step 2.Your class should look like this
第 2 步。你的类应该是这样的
public class MyClass
{
IExample1 ex1;
IExample2 ex2
public MyClass(IUnityContainer container)
{
/* This unity container is same unity container that we used in step
1 to register and resolve classes. So you can use this container to resolve
all the dependencies. */
ex1= container.Resolve<IExample1>(); // will give you object of Impl1
ex2= container.Resolve<IExample2>(); // will give you object of Impl2
}
}
Step 3. In this way you can resolve any number of dependencies without defining them in constructor.
第 3 步。通过这种方式,您可以解析任意数量的依赖项,而无需在构造函数中定义它们。

