Unity - 为什么 Resolve(ParameterOverride[]) 不使用预期的构造函数?

Unity - Why isn't Resolve(ParameterOverride[]) using the expected constructor?

我想将 IoD 与 class 一起使用,它实现了接口并具有带参数的构造函数。

界面:

    public interface IUsefulClass
    {
        string InterestingInfo { get; set; }
        string RelevantStuff { get; set; }
    }

两个简单的属性,没什么好说的。

class:

    public class UsefulClass : IUsefulClass
    {
        public string InterestingInfo { get; set; }

        public string RelevantStuff { get; set; }

        public UsefulClass()
        {
        }

        public UsefulClass(string p_strInterestingInfo)
        {
            InterestingInfo = p_strInterestingInfo;
        }

        public UsefulClass (string p_strInterestingInfo, string p_strRelevantStuff)
        {
            InterestingInfo = p_strInterestingInfo;
            RelevantStuff = p_strRelevantStuff;
        }
    }

它有几个不同的构造函数,每个构造函数都以自己的方式设置属性。

另一个人的来电class:

        public void HereGoes()
        {
            IUnityContainer z_ucoContainer = new UnityContainer();

            z_ucoContainer.RegisterType<IUsefulClass, UsefulClass>();

            IUsefulClass z_objUsefulButEmpty = z_ucoContainer.Resolve<IUsefulClass>();
            IUsefulClass z_objUsefulAndInteresting = z_ucoContainer.Resolve<IUsefulClass>(new ParameterOverride("p_strInterestingInfo", "This is interesting information"));
            IUsefulClass z_objUsefulAndInterestingToo = z_ucoContainer.Resolve<IUsefulClass>(new ParameterOverride[] { new ParameterOverride("p_strInterestingInfo", "This is very interesting information") });
            IUsefulClass z_objUsefulInterestingAndRelevant = z_ucoContainer.Resolve<IUsefulClass>(new ParameterOverride("p_strInterestingInfo", "This is quite interesting information"), new ParameterOverride("p_strRelevantStuff", "More relevant stuff here"));
            IUsefulClass z_objUsefulInterestingAndRelevantAsWell = z_ucoContainer.Resolve<IUsefulClass>(new ParameterOverride[] { new ParameterOverride("p_strInterestingInfo", "This is possibly the most interesting information"), new ParameterOverride("p_strRelevantStuff", "Look for relevant stuff there") });
        }

在测试和调试中,我发现所有五个变量在两个属性中都有 null

又调试了一下,发现每次Resolve()调用的都是无参构造函数

我尝试删除上述构造函数(自然地设置 [=15= 的代码行):我收到 Unity.ResolutionFailedException 消息,“解决方案因错误而失败:未能 select RegMat_VM.Infrastructure.UsefulClass".

的构造函数

我看了又看(here and there 以及其他地方),但找不到我做错了什么。我怎样才能让它正常工作?

解决方法是这样调用:

IUnityContainer z_ucoContainer = new UnityContainer();
z_ucoContainer.RegisterType<IUsefulClass, UsefulClass>();
z_ucoContainer.RegisterType<IUsefulClass, UsefulClass>("stringConstructor",new InjectionConstructor (typeof(string)));
z_ucoContainer.RegisterType<IUsefulClass, UsefulClass>("string2Constructor", new InjectionConstructor (typeof(string), typeof(string)));
IUsefulClass z_objUsefulButEmpty = z_ucoContainer.Resolve<IUsefulClass>();
IUsefulClass z_objUsefulAndInteresting = z_ucoContainer.Resolve<IUsefulClass>("stringConstructor",new ParameterOverride("p_strInterestingInfo", "This is interesting information"));
IUsefulClass z_objUsefulAndInterestingToo = z_ucoContainer.Resolve<IUsefulClass>("stringConstructor",new ParameterOverride[] { new ParameterOverride("p_strInterestingInfo", "This is very interesting information") });
IUsefulClass z_objUsefulInterestingAndRelevant = z_ucoContainer.Resolve<IUsefulClass>("string2Constructor",new ParameterOverride("p_strInterestingInfo", "This is quite interesting information"), new ParameterOverride("p_strRelevantStuff", "More relevant stuff here"));
IUsefulClass z_objUsefulInterestingAndRelevantAsWell = z_ucoContainer.Resolve<IUsefulClass>("string2Constructor",new ParameterOverride[] { new ParameterOverride("p_strInterestingInfo", "This is possibly the most interesting information"), new ParameterOverride("p_strRelevantStuff", "Look for relevant stuff there") });

这里涉及到构造注入的知识

当有多个构造函数时,可以使用InjectionConstructorAttribute装饰唯一需要的构造函数。

当你需要在同时使用multiple constructors时,你需要命名他们并且解析时使用该名称

有关命名构造函数的更一般用法,请参见下文:

using System;
using System.Collections.Generic;
using Unity;
using Unity.Injection;
using Unity.Resolution;

namespace ConsoleApp1 {
    class Program {
        static void Main (string[] args) {
            IUnityContainer container = new UnityContainer();
            container.RegisterType<IPeople, Swordsman>(new InjectionConstructor());//Unnamed default registration, the following default registration will overwrite the previous one
            container.RegisterType<IPeople, Witch>("Witch");//Named registration

            IPeople people=container.Resolve<IPeople>();//Resolve default objects           
            IPeople _witch =container.Resolve<IPeople>("Witch");//Specify the name resolution object

            IEnumerable<IPeople> peoples=container.ResolveAll<IPeople>();//Get all registered named objects of IPeople in the container
            
            people.ClassName = people.GetType().ToString();
            _witch.ClassName = _witch.GetType().ToString();
            var info1= people.ShowInfo();
            var info2= _witch.ShowInfo();

            foreach (var item in peoples)
                {
                item.ClassName = item.GetType().ToString();
                Console.WriteLine(item.ShowInfo());
                }
            Console.WriteLine(info1);
            Console.WriteLine(info2);
            //Dealing with the case of multiple constructors:
            container.RegisterType<IPeople, Swordsman>("SString",new InjectionConstructor(typeof(string)));
            container.RegisterType<IPeople, Swordsman>("TString", new InjectionConstructor(typeof(string), typeof(string)));

            var people2=container.Resolve<IPeople>("SString",new ParameterOverride("o" ,"hello"));
            IPeople people3=container.Resolve<IPeople>("TString",new ParameterOverride ("o", "hello"),new ParameterOverride ("g", "world"));
            Console.WriteLine(people2.ClassName);
            Console.WriteLine(people3.ClassName + people3.ClassAge);
            
            Console.ReadLine();
            }
        }

    //People interface
    public interface IPeople {
        string ClassName {
            get; set;
            }
        string ClassAge {
            get; set;
            }
        string ShowInfo ();
        }

    //Witch
    public class Witch : IPeople {
        public string ClassName {
            get; set;
            }
        public string ClassAge {
            get; set;
            }
        public string ShowInfo () {
            return string.Format("Witch:{0}", ClassName);
            }
        }

    //Swordsman 
    public class Swordsman : IPeople {
        public string ClassName {
            get; set;
            }
        public string ClassAge {
            get;set;
            }
        public string ShowInfo () {
            return string.Format("Swordsman:{0}", ClassName);
            }
        
        public Swordsman (string o) {
            ClassName = o;
            }
        //[InjectionConstructor]
        public Swordsman () {
            }
        
        public Swordsman (string o, string g) {
            ClassName = o;
            ClassAge = g;
            }
        }
    }

输出: