代码之家  ›  专栏  ›  技术社区  ›  Peter Morris

Unity.Buildup无法消除歧义

  •  1
  • Peter Morris  · 技术社区  · 14 年前

    我有一个有两个构造函数的类,两个构造函数都有一个参数。由于不值得解释的限制,我不能更改构造函数或使用子类。

    我不能使用Unity来创建这个类的实例,因为Unity看到两个具有相同数量参数的构造函数,并抱怨它不知道使用哪一个,这是足够公平的。因此,我自己创建实例,然后尝试使用UnityContainer.Buildup()。

    var result = constructorInfo.Invoke(new object[] { content });
    UnitContainer.BuildUp(result);
    

    上面的代码没有设置任何[Dependency]属性,如果我使用它,它也不会调用[InjectionMethod]。

    var result = constructorInfo.Invoke(new object[] { content });
    UnitContainer.BuildUp(typeOfObject, result);
    

    对于不明确的构造函数,这会引发另一个异常,即使我没有要求它构造实例。

    有人有什么想法吗?

    这是一个示例应用程序

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.Unity;
    using System.Reflection;
    
    namespace ConsoleApplication7
    {
        public interface IConstructorType1 { }
        public interface IConstructorType2 { }
        public interface INeedThisDependency { }
        public class NeedThisDependency : INeedThisDependency { }
    
        public class MyDomainObject
        {
            public MyDomainObject(IConstructorType1 constructorType1) { }
            public MyDomainObject(IConstructorType2 constructorType2) { }
    
            [Dependency]
            public INeedThisDependency Needed { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                IUnityContainer unityContainer = new UnityContainer();
                unityContainer.RegisterType<INeedThisDependency, NeedThisDependency>();
                //Try with type 1 constructor
                ConstructorInfo constructorInfo1 = typeof(MyDomainObject).GetConstructor(new Type[] { typeof(IConstructorType1) });
                MyDomainObject instance1 = CreateTheInstance(unityContainer, typeof(MyDomainObject), constructorInfo1, null);
                //Try with type 2 constructor
                ConstructorInfo constructorInfo2 = typeof(MyDomainObject).GetConstructor(new Type[] { typeof(IConstructorType2) });
                MyDomainObject instance2 = CreateTheInstance(unityContainer, typeof(MyDomainObject), constructorInfo2, null);
            }
    
            //This is the only point I have any influence over what happens
            //So this is the only place I get to change the code.
            static MyDomainObject CreateTheInstance(IUnityContainer unityContainer, Type type, ConstructorInfo constructorInfo, object parameters)
            {
                var result = (MyDomainObject)constructorInfo.Invoke(new object[] { parameters });
                //This will throw an ambiguous constructor exception,
                //even though I am not asking it to construct anything
                unityContainer.BuildUp(type, result);
                //This will not build up dependencies
                unityContainer.BuildUp(result); 
                if (result.Needed == null)
                    throw new NullReferenceException("Needed");
                return result;
            }
        }
    }
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   Chris Tavares    14 年前

    不幸的是,这是一个积累中的错误。

        2
  •  0
  •   Peter Morris    14 年前

    不要调用Buildup,而是调用此CallinjuctionMethod帮助程序。

    public static class UnityContainerHelper
    {
        public static void CallInjectionMethod(this IUnityContainer unityContainer, object instance, params ResolverOverride[] overrides)
        {
            if (instance == null)
                throw new ArgumentNullException("Instance");
    
            var injectionMethodInfo = instance.GetType().GetMethods().Where(x => x.GetCustomAttributes(typeof(InjectionMethodAttribute), true).Any()).SingleOrDefault();
            if (injectionMethodInfo == null)
                return;
            var parameters = injectionMethodInfo.GetParameters();
            if (parameters.Length == 0)
                return;
    
            var dependencies = new object[parameters.Length];
            int index = 0;
            foreach (Type parameterType in parameters.Select(x => x.ParameterType))
            {
                dependencies[index] = unityContainer.Resolve(parameterType, overrides);
                index++;
            }
            injectionMethodInfo.Invoke(instance, dependencies);
        }
    }