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;
}
}
}
输出:
我想将 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;
}
}
}
输出: