Un'opzione alternativa utilizzando la riflessione e seguendo la Strategy Pattern.
1) Creare una classe base per gli argomenti dei costruttori
public abstract class ConstructorArgs
{
}
2) creare una sequenza di diverse classi di argomenti concreti:
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) Ora, nella tua classe GradeType creare i metodi richiesto per la riflessione. ParseArguments analizza gli argomenti per le proprietà e per ognuno che trova, ne copia il valore nella rispettiva proprietà di GradeType utilizzando SetProperty.Dal momento che utilizza il nome della proprietà per l'abbinamento, è importante mantenere lo stesso nome di proprietà attraverso sia il GradeType ei ConstructorArgs concreti:
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) Nella classe GradeType creare le rispettive proprietà (la mente che si deve utilizzare esattamente gli stessi nomi e tipi che si è utilizzato nella ConstructorArgs concreti, ma è possibile utilizzare qualsiasi modificatori di accesso che ti piace)
public string _gradeTypeStringFromXmlFile { get; set; }
public Enum.GradeType _gradeType { get; set; }
5) Creare un costruttore per la classe GradeType con un parametro di tipo ConstructorArgs:
public GradeType(ConstructorArgs args)
{
this.ParseArguments(args);
}
6) Ora è possibile registrare il GradeType in Unity utilizzando un unico costruttore, ma è possibile passare in diversi tipi come argomenti quando risolverlo:
_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)});
Se avete intenzione di volte risolvere il tipo in un'iterazione questo approccio potrebbe non essere l'ideale, dal momento che Reflection prevede una penalizzazione delle prestazioni.
perché non utilizzare 'Enum.Parse' nella stringa gradeType prima di creare la classe? – jgauffin
sembra proprio un design intuitivo che la classe GradeType converta la stringa. – FatAlbert
Mi sembra una soluzione fragile dal momento che qualsiasi valore inesistente può generare un'eccezione o nascondere un errore. – jgauffin