Advertisement
Guest User

Unity Extension

a guest
Jun 28th, 2010
448
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.31 KB | None | 0 0
  1. using Microsoft.Practices.ObjectBuilder2;
  2. using Microsoft.Practices.Unity;
  3. using Microsoft.Practices.Unity.ObjectBuilder;
  4.  
  5. namespace ConsoleApplication1
  6. {
  7.     internal class DefaultCtorExtension : UnityContainerExtension
  8.     {
  9.         protected override void Initialize()
  10.         {
  11.             Context.Policies.Set(typeof(IConstructorSelectorPolicy), new DefaultConstructorSelectorPolicy(), "DefaultCtor");
  12.         }
  13.     }
  14.    
  15.     public class DefaultConstructorSelectorPolicy : DefaultConstructorPolicyBase<InjectionConstructorAttribute>
  16.     {
  17.         protected override IDependencyResolverPolicy CreateResolver(ParameterInfo param)
  18.         {
  19.             IEnumerable<DependencyResolutionAttribute> attributes = param.GetCustomAttributes(false).Cast<DependencyResolutionAttribute>();
  20.            
  21.             // Resolve all DependencyAttributes on this parameter, if any
  22.             List<DependencyResolutionAttribute> attrs = new List<DependencyResolutionAttribute>(attributes);
  23.  
  24.             if(attrs.Count > 0)
  25.             {
  26.                 // Since this attribute is defined with MultipleUse = false, the compiler will
  27.                 // enforce at most one. So we don't need to check for more.
  28.                 return attrs[0].CreateResolver(param.ParameterType);
  29.             }
  30.  
  31.             // No attribute, just go back to the container for the default for that type.
  32.             return new NamedTypeDependencyResolverPolicy(param.ParameterType, null);
  33.         }
  34.     }
  35.    
  36.     public abstract class DefaultConstructorPolicyBase<TInjectionConstructorMarkerAttribute>
  37.         : IConstructorSelectorPolicy
  38.         where TInjectionConstructorMarkerAttribute : Attribute
  39.     {
  40.         public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
  41.         {
  42.             Type typeToConstruct = context.BuildKey.Type;
  43.             ConstructorInfo ctor = FindInjectionConstructor(typeToConstruct) ?? GetDefaultConstructor(typeToConstruct);
  44.  
  45.             SelectedConstructor result = null;
  46.  
  47.             if(ctor != null)
  48.                 result = CreateSelectedConstructor(context, ctor);
  49.  
  50.             return result;
  51.         }
  52.  
  53.         private SelectedConstructor CreateSelectedConstructor(IBuilderContext context, ConstructorInfo ctor)
  54.         {
  55.             SelectedConstructor result = new SelectedConstructor(ctor);
  56.  
  57.             foreach(ParameterInfo param in ctor.GetParameters())
  58.             {
  59.                 string key = Guid.NewGuid().ToString();
  60.                 IDependencyResolverPolicy policy = CreateResolver(param);
  61.  
  62.                 context.PersistentPolicies.Set(policy, key);
  63.  
  64.                 DependencyResolverTrackerPolicy.TrackKey(context.PersistentPolicies, context.BuildKey, key);
  65.                 result.AddParameterKey(key);
  66.             }
  67.  
  68.             return result;
  69.         }
  70.  
  71.         protected abstract IDependencyResolverPolicy CreateResolver(ParameterInfo param);
  72.  
  73.         private static ConstructorInfo FindInjectionConstructor(Type typeToConstruct)
  74.         {
  75.             ConstructorInfo[] injectionConstructors = typeToConstruct.GetConstructors()
  76.                 .Where(ctor => ctor.IsDefined(typeof(TInjectionConstructorMarkerAttribute), true))
  77.                 .ToArray();
  78.  
  79.             ConstructorInfo result = null;
  80.            
  81.             switch(injectionConstructors.Length)
  82.             {
  83.                 case 0:
  84.                     result = null;
  85.                     break;
  86.  
  87.                 case 1:
  88.                     result = injectionConstructors[0];
  89.                     break;
  90.  
  91.                 default:
  92.                     string msg = string.Format("The type {0} has multiple constructors marked with the InjectionConstructor attribute. Unable to disambiguate.", typeToConstruct.Name);
  93.                     throw new InvalidOperationException(msg);
  94.             }
  95.  
  96.             return result;
  97.         }
  98.  
  99.         private static ConstructorInfo GetDefaultConstructor(Type typeToConstruct)
  100.         {
  101.             ConstructorInfo[] constructors = typeToConstruct.GetConstructors();
  102.             Array.Sort(constructors, new ConstructorLengthComparer());
  103.  
  104.             ConstructorInfo result = null;
  105.            
  106.             switch(constructors.Length)
  107.             {
  108.                 case 0:
  109.                     result = null;
  110.                     break;
  111.  
  112.                 case 1:
  113.                     result = constructors[0];
  114.                     break;
  115.  
  116.                 default:
  117.                     int paramLength = constructors[0].GetParameters().Length;
  118.  
  119.                     if(constructors[1].GetParameters().Length == paramLength)
  120.                     {
  121.                         string msg = string.Format("The type {0} has multiple constructors of length {1}. Unable to disambiguate.", typeToConstruct.Name, paramLength);
  122.                         throw new InvalidOperationException(msg);
  123.                     }
  124.                    
  125.                     result = constructors[0];
  126.                     break;
  127.             }
  128.  
  129.             return result;
  130.         }
  131.  
  132.         private class ConstructorLengthComparer : IComparer<ConstructorInfo>
  133.         {
  134.             public int Compare(ConstructorInfo x, ConstructorInfo y)
  135.             {
  136.                 return x.GetParameters().Length - y.GetParameters().Length;
  137.             }
  138.         }
  139.     }
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement