Platform: .NET framework 4.5.1, C#
I am attempting to call the constructor for a class, not knowing the generic type at run-time and wondering how I could do this. Based on other answers I have read, it’s clear that I need to rely on Reflection.
I have tried a method that includes me getting the MethodInfo array of the constructors and use that, however I am still struggling to put everything together. Below my classes.
I have a parent abstract class, defined like below.
public abstract class ParentClass {
public string name {get;}
public CustomEnum type {get;}
public object value {get;}
public ParentClass(string name, CustomEnum type, object value = null){
this.name = name;
this.type = type;
this.value = value;
}
}
One of the many implementations of the abstract class depends on a GenericType, defined like below.
public class ChildClass<GenericType> : ParentClass {
public delegate GenericType FunctionPointer(ExternalObject object);
public override string name {get;}
public override CustomEnum type {get;}
public FunctionPointer mappingFunction = null;
private ExternalObject _value {get;}
private List<GenericType> mappedValues = null;
private override object value {get => getValue(); set => setValue(value); }
public ChildClass(string name, CustomEnum type, ExternalObject value = null, FunctionPointer mappingFunction = null){
this.name = name;
this.type = type;
this._value = value;
this.mappingFunction = mappingFunction;
populateList(value);
}
private void populateList(ExternalObject value){
if(this.mappingFunction != null){
if(value != null){
this.mappedValues = new List<GenericType>();
foreach(var item in value){
GenericType valueToAdd = mappingFunction.Invoke(value);
this.mappedValues.Add(valueToAdd);
}
}
}
}
private object getValue(){
if(this.mappingFunction == null){
return this._value;
}
else {
return this.mappedValues;
}
}
private void setValue(object value){
this._value = value;
if(this.mappingFunction != null){
populateList(this._value);
}
}
}
This is how I have the process code set up:
public ParentClass[] getValues(ParentClass[] inputParameters){
ParentClass[] outputParameters = null;
if(inputParameters != null){
List<ParentClass> outputList = new List<ParentClass>();
foreach(ParentClass inputParameter in inputParameters){
object value = obtainValue(inputParameter);
ParentClass populatedParameter = populateParameter(inputParameter, value);
outputList.Add(populatedParameter);
}
outputParameters = outputList.ToArray<ParentClass>();
}
return outputParameters;
}
The method I am specifically trying to code for, is as follows:
private ParentClass populateParameter(ParentClass inputParameter, object value){
ParentClass populatedParameter = null;
if(inputParameter != null){
switch(inputParameter.type){
case CustomEnum.WITHOUT_GENERIC_TYPE:
[...]
break;
case CustomEnum.WITH_GENERIC_TYPE:
populatedParameter = populateGenericParameter(inputParameter, (ExternalObject) value);
break;
}
}
return populatedParameter;
}
I am stuck trying to understand how to craft the below method:
private ParentClass populateGenericParameter(ParentClass inputParameter, ExternalObject value) {
ParentClass populatedParameter = null;
FieldInfo functionPointer = null;
Type genericType = typeof(ChildClass<>).MakeGenericType(new object[] { inputParameter.getType() });
FieldInfo[] parameterFields = genericType.GetConstructors();
if(parameterFields != null){
const string functionPointerString = "FunctionPointer";
foreach(FieldInfo parameterField in parameterFields){
if(parameterField.ToString().ToUpper().Contains(functionPointerString.ToUpper()) == true){
functionPointer = parameterField;
}
}
}
ConstructorInfo[] allConstructors = genericType.GetConstructors();
if(allConstructors != null && allConstructor.Length > 0){
ConstructorInfo constructor = allConstructor[0];
object[] constructorParameters = new object[] {parameter.name, parameter.type, value, functionPointer.GetValue(null) };
populatedParameter = (ChildClass<>) constructor.Invoke(constructorParameters);
}
return populatedParameter;
}
So, the problem is with the constructorParameters object and the Invoke method.
The "functionPointer.GetValue(null)" throws an exception.
The casting of ChildClass when invoking the constructor is a compile-time error, and so far the only way to get around it has been to replace it with the ParentClass.
I am new to reflection, so looking forward to read how to get around this problem. I have visited other topics as well, and that has led me to try to use the ConstructorInfo and FieldInfo arrays. I seem stuck here though. I hope what I am trying to achieve is possible.
Aucun commentaire:
Enregistrer un commentaire