Register<IA, A>();
class B { public IA A {get;set;}}
//container inject this property because IA was registered
在autofac中你可以做到
builder.RegisterType<A>().InjectProperties();
为此。
有没有任何扩展团结来做到这一点?或者可以作为我自己实施此功能的样本的扩展名吗?
答案 0 :(得分:2)
这不是一项简单的任务。要解决它,您应该更改Unity的属性选择器策略的默认行为。你可以改变它。这就是我可以提出的建议
namespace Microsoft.Practices.Unity.ObjectBuilder
{
public class ResolveBecouseWeCanPropertySelectorPolicy : PropertySelectorBase<DependencyResolutionAttribute>
{
private readonly IUnityContainer container;
public ResolveBecouseWeCanPropertySelectorPolicy(IUnityContainer container) {
this.container = container;
}
public override IEnumerable<SelectedProperty> SelectProperties(IBuilderContext context, IPolicyList resolverPolicyDestination) {
Type t = context.BuildKey.Type;
foreach (
PropertyInfo prop in
t.GetProperties(BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance)) {
if (prop.GetIndexParameters().Length == 0 &&
prop.CanWrite
&& prop.IsDefined(typeof (DependencyResolutionAttribute), false)
) //Default behaviour
{
yield return CreateSelectedProperty(context, resolverPolicyDestination, prop);
}
//Alternate behaviour
else if (prop.GetIndexParameters().Length == 0 &&
prop.CanWrite &&
container.IsRegistered(prop.PropertyType)//don't mind about Dependency attribute if we can resolve it - we would
) {
{
yield return CreateSelectedPropertyForResolveBecouseWeCan(context, resolverPolicyDestination, prop);
}
}
}
}
private SelectedProperty CreateSelectedProperty(IBuilderContext context, IPolicyList resolverPolicyDestination, PropertyInfo property) {
return DoCreateSelectedProperty(property, resolverPolicyDestination, CreateResolver(property), context);
}
private static SelectedProperty CreateSelectedPropertyForResolveBecouseWeCan(IBuilderContext context, IPolicyList resolverPolicyDestination, PropertyInfo property) {
IDependencyResolverPolicy dependencyResolverPolicy = new DependencyAttribute().CreateResolver(property.PropertyType);
return DoCreateSelectedProperty(property, resolverPolicyDestination, dependencyResolverPolicy, context);
}
private static SelectedProperty DoCreateSelectedProperty(PropertyInfo property, IPolicyList resolverPolicyDestination, IDependencyResolverPolicy dependencyResolverPolicy, IBuilderContext context) {
string key = Guid.NewGuid().ToString();
var result = new SelectedProperty(property, key);
resolverPolicyDestination.Set( dependencyResolverPolicy, key);
DependencyResolverTrackerPolicy.TrackKey(context.PersistentPolicies,
context.BuildKey,
key);
return result;
}
protected override IDependencyResolverPolicy CreateResolver(PropertyInfo property)
{
var attributes =
property.GetCustomAttributes(typeof (DependencyResolutionAttribute), false)
.OfType<DependencyResolutionAttribute>()
.ToList();
Debug.Assert(attributes.Count == 1);
return attributes[0].CreateResolver(property.PropertyType);
}
}
}
这是修改后的DefaultUnityPropertySelectorPolicy,你可以在团结的源代码中找到它。
之后,您需要使用UnityContainerExtension
机制重新定义默认行为。
public class ResolveBecouseWeCanUnityContainerExtension : UnityContainerExtension {
protected override void Initialize() {
Context.Policies.SetDefault<IPropertySelectorPolicy>(
new ResolveBecouseWeCanPropertySelectorPolicy(Container));
}
}
现在让我们假设您有以下课程
public interface IConcreteService {
int Val { get; set; }
}
public class ConcreteService : IConcreteService {
public int Val { get; set; }
public ConcreteService() {
}
}
public class B {
//no attribute
public IConcreteService ConcreteService { get; set; }
public int SomeVal { get; set; }
}
所以现在这个测试应该通过
[TestMethod]
public void TestMethod1() {
var container = new UnityContainer();
container.AddExtension(new ResolveBecouseWeCanUnityContainerExtension());
container.RegisterType<IConcreteService, ConcreteService>();
var b = new B();
container.BuildUp(b);
Assert.IsNotNull(b.ConcreteService);
}
但你应该明白这个不会
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
var container = new UnityContainer();
container.RegisterType<IConcreteService, ConcreteService>();
var b0 = new B();
container.BuildUp(b0);
Assert.IsNull(b0.ConcreteService);
container.AddExtension(new ResolveBecouseWeCanUnityContainerExtension());
var b = new B();
container.BuildUp(b);
Assert.IsNotNull(b.ConcreteService); //dies becouse plan cashed
}
}
<强>更新强>
我玩了一点,发现了如何让这个测试工作
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
var container = new UnityContainer();
container.RegisterType<IConcreteService, ConcreteService>();
var b0 = new B();
container.BuildUp(b0);
Assert.IsNull(b0.ConcreteService);
var b = new B();
container.BuildUpAndResolveAllWeCan(b);
Assert.IsNotNull(b.ConcreteService);
//check if we have no broken something and that it will work second time
var b1 = new B();
container.BuildUp(b1);
Assert.IsNull(b1.ConcreteService);
var b2 = new B();
container.BuildUpAndResolveAllWeCan(b2);
Assert.IsNotNull(b2.ConcreteService);
}
}
这可以通过以下方式完成
public static class UnityExtensions {
public static T BuildUpAndResolveAllWeCan<T>(this IUnityContainer container, T existing) {
return BuildUpAndResolveAllWeCan(container, existing, null) ;
}
public static T BuildUpAndResolveAllWeCan<T>(this IUnityContainer container, T existing, string name) {
container.AddExtension(new ResolveBecouseWeCanUnityContainerExtension());
//we are adding __BuildUpResolveAllWeCan__ to create new IBuildPlanPolicy for type T
//and IPropertySelectorPolicy is ResolveBecouseWeCanPropertySelectorPolicy
//this will be cached so it will not hurt the performance
var buildedUp = container.BuildUp(existing, (name ?? string.Empty) + "__BuildUpResolveAllWeCan__");
container.AddExtension(new CleanUnityContainerExtension());
return buildedUp;
}
}
并添加清理扩展程序
public class CleanUnityContainerExtension : UnityContainerExtension {
protected override void Initialize() {
Context.Policies.SetDefault<IPropertySelectorPolicy>(
new DefaultUnityPropertySelectorPolicy());
}
}
下载源文件