使用unity解析具有多个构造函数的实例

我想使用unity创建一个类的实例,其中类有两个具有相同参数数量的构造函数。

这是实例化:

_unityContainer.Resolve(new ParameterOverride("gradeTypeStringFromXmlFile", gradeTypeStringFromXmlFile)); 

以下是构造函数:

  public GradeType(string gradeTypeStringFromXmlFile) { _gradeTypeStringFromXmlFile = gradeTypeStringFromXmlFile; } public GradeType(Enum.GradeType gradeType) { _gradeType = gradeType; } 

如果我尝试这样做,我得到一个例外,说明类型GradeType有多个长度为1的构造函数。无法消除歧义

我可以在一个构造函数上设置属性[InjectionConstructor]以使其与一个一起工作,但是我不能使用另一个构造函数创建一个具有unity的实例。

是否有一些方法让多个构造函数具有相同数量的参数并仍然使用unity来创建实例?

是的,可以告诉Unity应该使用哪个构造函数,但只有在使用InjectionConstructor注册类型时才能执行此操作。 如果你想使用两个构造函数,它甚至会很复杂,因为你必须在注册时命名注册并使用该名称。

使用Unity版本2.1.505构建的示例:

 var continer = new UnityContainer(); continer.RegisterType("stringConstructor", new InjectionConstructor(typeof(string))); continer.RegisterType("enumConstructor", new InjectionConstructor(typeof(EnumGradeType))); IGradeType stringGradeType = continer.Resolve("stringContructor" , new DependencyOverride(typeof(string), "some string")); IGradeType enumGradeType = continer.Resolve("enumConstructor", new DependencyOverride(typeof(EnumGradeType), EnumGradeType.Value)); 

使用Reflection并遵循策略模式的替代选项。

1)为构造函数的参数创建一个基类

 public abstract class ConstructorArgs { } 

2)创建一系列不同的具体参数类:

 public class StringArg : ConstructorArgs { public string _gradeTypeStringFromXmlFile { get; set; } public StringArg (string gradeTypeStringFromXmlFile) { this._gradeTypeStringFromXmlFile = gradeTypeStringFromXmlFile ; } } public class EnumArg : ConstructorArgs { public Enum.GradeType _gradeType { get; set; } public EnumArg (Enum.GradeType gradeType) { this._gradeType = gradeType ; } } 

3)现在在GradeType类中创建Reflection所需的方法。 ParseArguments扫描args中的属性,找到它找到的每个属性,它使用SetProperty将其值复制到GradeType的相应属性。 由于它使用属性名称进行匹配,因此在GradeType和具体ConstructorArgs中保持相同的属性名称非常重要:

  private void SetProperty(String propertyName, object value) { var property = this.GetType().GetProperty(propertyName); if (property != null) property.SetValue(this, value); } private void ParseArguments(ConstructorArgs args) { var properties = args.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in properties) { this.SetProperty(propertyInfo.Name, args.GetType().GetProperty(propertyInfo.Name).GetValue(args)); } } 

4)在GradeType类中创建相应的属性(请注意,您必须使用与具体ConstructorArgs中使用的完全相同的名称和类型,但您可以使用您喜欢的任何访问修饰符)

  public string _gradeTypeStringFromXmlFile { get; set; } public Enum.GradeType _gradeType { get; set; } 

5)使用类型为ConstructorArgs的参数为GradeType类创建构造函数:

  public GradeType(ConstructorArgs args) { this.ParseArguments(args); } 

6)现在您可以使用单个构造函数在Unity中注册GradeType,但在解析它时可以传入不同类型的参数:

  _unityContainer.RegisterType( new InjectionConstructor( typeof(ConstructorArgs) )); var args1 = new StringArg(gradeTypeStringFromXmlFile); // string IGradeType gradeType1 = _unityContainer.Resolve( new ResolverOverride[]{new ParameterOverride("args", args1)}); var args2 = new EnumArg(gradeType); // enum IGradeType gradeType2 = _unityContainer.Resolve( new ResolverOverride[]{new ParameterOverride("args", args2)}); 

如果您计划在迭代中重复解析您的类型,那么这种方法可能并不理想,因为Reflection会带来性能损失。

删除一个构造函数,并将字符串转换为枚举,反之亦然,然后使用容器解析。