Una opción alternativa utilizando la reflexión y siguiendo el Strategy Pattern.
1) Crear una clase base para los argumentos de los constructores
public abstract class ConstructorArgs
{
}
2) Crear una secuencia de diferentes clases de argumentos concretos:
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) En su clase GradeType crear los métodos requerido para la Reflexión. ParseArguments escanea los argumentos para las propiedades y para cada uno que encuentra, copia su valor a la propiedad respectiva de GradeType usando SetProperty.Dado que se usa el nombre de la propiedad para el juego, es importante mantener el mismo nombre de propiedad a través tanto de la GradeType y los ConstructorArgs concretas:
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) En la clase GradeType crear las respectivas propiedades (cuenta que debe utilizar exactamente los mismos nombres y tipos que utilizó en los ConstructorArgs concretas pero se puede usar cualquier modificador de acceso se quiere)
public string _gradeTypeStringFromXmlFile { get; set; }
public Enum.GradeType _gradeType { get; set; }
5) Crear un constructor para la clase GradeType con un parámetro de ConstructorArgs tipo:
public GradeType(ConstructorArgs args)
{
this.ParseArguments(args);
}
6) Ahora puede registrar el GradeType en la Unidad utilizando un único constructor pero se pueden pasar en diferentes tipos como argumentos al resolver que:
_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)});
Si usted está planeando para resolver en repetidas ocasiones su tipo en una iteración ese enfoque podría no ser ideal, ya que Reflection viene con una penalización de rendimiento.
¿por qué no utilizar 'Enum.Parse' en la cadena gradeType antes de crear la clase? – jgauffin
, se siente como un diseño intuitivo que la clase GradeType convierte la cadena. – FatAlbert
Parece ser una solución frágil para mí, ya que cualquier valor no existente arrojará una excepción u ocultará un error. – jgauffin