Альтернативный вариант с использованием отражения и следования шаблону стратегии .
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 сканирует аргументы на предмет свойств и для каждого обнаруженного им значения копирует свое значение в соответствующее свойство GradeType с помощью SetProperty. Поскольку для сопоставления используется имя свойства, важно сохранить одинаковое имя свойства как для 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) Создайте конструктор для вашего класса GradeType с параметром типа ConstructorArgs:
public GradeType(ConstructorArgs args)
{
this.ParseArguments(args);
}
6) Теперь вы можете зарегистрировать GradeType в Unity, используя один конструктор, но вы можете передавать различные типы в качестве аргументов при его разрешении:
_unityContainer.RegisterType<IGradeType, GradeType>(
new InjectionConstructor( typeof(ConstructorArgs) ));
var args1 = new StringArg(gradeTypeStringFromXmlFile); // string
IGradeType gradeType1 = _unityContainer.Resolve<IGradeType>(
new ResolverOverride[]{new ParameterOverride("args", args1)});
var args2 = new EnumArg(gradeType); // enum
IGradeType gradeType2 = _unityContainer.Resolve<IGradeType>(
new ResolverOverride[]{new ParameterOverride("args", args2)});
Если вы планируете многократно разрешать ваш тип в итерации, такой подход может быть не идеальным, поскольку Reflection сопровождается снижением производительности.