Unity framework DependencyAttribute only works for public properties?

前端 未结 8 1205
小鲜肉
小鲜肉 2021-02-14 17:31

I was trying to clean up some accessability stuff in my code, and inadvertently broke Unity dependency injection. After a while I realized that I marked some public properties t

8条回答
  •  暖寄归人
    2021-02-14 18:01

    UPDATE FOR Enterprise Library 5.0

    As rally52rs warned might happen, the upgrade to EntLib5.0 breaks his implementation. Using the same approach as Rally did, I reflected on the new code base and worked up the following 5.0 compatible version of the InternalConstructorSelectorPolicy.

    Note that my version specifically limits itself to internal constructors in the FindLongestConstructor method. On this point my code is functionally different from Rally's.

    public class InternalConstructorSelectorPolicy : IConstructorSelectorPolicy, IBuilderPolicy 
    {
        private IDependencyResolverPolicy CreateResolver(ParameterInfo parameter)
        {
            List attrs = parameter.GetCustomAttributes(false).OfType().ToList();
            if (attrs.Count > 0)
            {
                return attrs[0].CreateResolver(parameter.ParameterType);
            }
            return new NamedTypeDependencyResolverPolicy(parameter.ParameterType, null);
        }
    
        private SelectedConstructor CreateSelectedConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination, ConstructorInfo ctor)
        {
            SelectedConstructor result = new SelectedConstructor(ctor);
            foreach (ParameterInfo param in ctor.GetParameters())
            {
                string key = Guid.NewGuid().ToString();
                IDependencyResolverPolicy policy = this.CreateResolver(param);
                resolverPolicyDestination.Set(policy, key);
                DependencyResolverTrackerPolicy.TrackKey(resolverPolicyDestination, context.BuildKey, key);
                result.AddParameterKey(key);
            }
            return result;
        }
    
        private static ConstructorInfo FindInjectionConstructor(Type typeToConstruct)
        {
            ConstructorInfo[] injectionConstructors = typeToConstruct
                .GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                .Where(delegate(ConstructorInfo ctor)
            {
                return ctor.IsDefined(typeof(InjectionConstructorAttribute), true);
            }).ToArray();
            switch (injectionConstructors.Length)
            {
                case 0:
                    return null;
    
                case 1:
                    return injectionConstructors[0];
            }
            throw new InvalidOperationException(string.Format("Multiple constructors found for {0}" , typeToConstruct.Name ));
        }
    
        private static ConstructorInfo FindLongestConstructor(Type typeToConstruct)
        {
            var constructors =
                Array.FindAll(
                    typeToConstruct.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
                    ctor => !ctor.IsFamily && !ctor.IsPrivate);  //Filter out protected and private constructors
    
            Array.Sort(constructors, new ConstructorLengthComparer());
            switch (constructors.Length)
            {
                case 0:
                    return null;
    
                case 1:
                    return constructors[0];
            }
            int paramLength = constructors[0].GetParameters().Length;
            if (constructors[1].GetParameters().Length == paramLength)
            {
                throw new InvalidOperationException(string.Format("Ambiguous constructor found for {0}", typeToConstruct.Name));
            }
            return constructors[0];
        }
    
        public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
        {
            Type typeToConstruct = context.BuildKey.Type;
            ConstructorInfo ctor = FindInjectionConstructor(typeToConstruct) ?? FindLongestConstructor(typeToConstruct);
            if (ctor != null)
            {
                return this.CreateSelectedConstructor(context, resolverPolicyDestination, ctor);
            }
            return null;
        }
    
        // Nested Types
        private class ConstructorLengthComparer : IComparer
        {
            // Methods
            public int Compare(ConstructorInfo x, ConstructorInfo y)
            {
                return (y.GetParameters().Length - x.GetParameters().Length);
            }
        }
    }
    

提交回复
热议问题