I am looking for a way to assign different delegates in a list to MethodInfo
's without having information about the return types beforehand. Below is the code code I am using. The comments give additional information on what is happening. It is a lengthy bit of code but I have reduced it as much as I can.
Main Snippet
private const string methodName = "Execute";
public static void Main()
{
ExampleClass1 e1 = new ExampleClass1();
ExampleClass2 e2 = new ExampleClass2();
ExampleClass3 e3 = new ExampleClass3();
/* Code below Simulates: "e3.GetString = e2.Execute;" */
var method = e2.GetType().GetMethod(methodName);
for (int i = 0; i < e3.DelegateList.Count; i++)
{
// First check the type of e2 return
Type methodType = method.ReturnType;
// Check that its the same return type as delegate
if (methodType != e3.DelegateList[i].ReturnType)
continue;
// Assign delegate to method
var returnType = e3.DelegateList[i].DelegateType;
e3.DelegateList[i].Delegate = Delegate.CreateDelegate(returnType, e2, method);
/* Code below only for debugging */
Console.WriteLine("The delegate in the list: " + e3.DelegateList[i].Delegate);// Returns Type of StringHandler
Console.WriteLine("The delegate in the object: " + e3.GetString);// Returns null
e3.GetString = e3.DelegateList[i].Delegate;// This throws Error Cannot convert Delegate to StringHandler
}
/* Code above Simulates: "e3.GetString = e2.Execute;" */
e2.GetNumber = e1.Execute;
e3.Execute();// Throws Null References Exception on
// Read the key
Console.ReadKey();
}
Supporting Classes/Code
If you need more information about supporting classes, please see the code below. In addition, this is a self-contained program and should be runnable as is.
public class ExampleClass3
{
public delegate string StringHandler();
public delegate int IntHandler();
public StringHandler GetString { get; set; }
public IntHandler GetInt { get; set; }
public List<DelegateInfo<Type, Type, Delegate>> DelegateList { get; set; }
public ExampleClass3()
{
DelegateList = new List<DelegateInfo<Type, Type, Delegate>>();
DelegateList.Add(new DelegateInfo<Type, Type, Delegate>(typeof(StringHandler), typeof(string), GetString));
DelegateList.Add(new DelegateInfo<Type, Type, Delegate>(typeof(IntHandler), typeof(int), GetInt));
}
public object Execute()
{
Console.WriteLine(GetString());
return null;
}
}
public class ExampleClass2
{
public delegate int NumberHandler();
public NumberHandler GetNumber { get; set; }
public string Execute() => $"Your Number Is {GetNumber()}";
}
public class ExampleClass1
{
public int number = 5;
public int Execute() => number;
}
public class DelegateInfo<T1, T2, T3>
{
public DelegateInfo(T1 delegateType, T2 returnType, T3 @delegate)
{
DelegateType = delegateType;
ReturnType = returnType;
Delegate = @delegate;
}
public T1 DelegateType { get; set; }
public T2 ReturnType { get; set; }
public T3 Delegate { get; set; }
}
I simplified your code a bit to demonstrate how I would go about this. First off, don't create a special DelegateInfo class - stick with the standard .NET reflection library as much as possible. They did a really good job on it - but it does take a while to learn.
Here is the code:
First off, note how I got rid of the custom delegate definitions in favor of Func. This will prove much easier to work with in a generic fashion. Note how ExampleClass3 is defined now:
I can use the fact that all these functions are of type Func to develop a generic solution to assigning them a value. Based upon the return type of the target method, I can construct a Func delegate of the appropriate type (and link it to the specific e2 instance in question):
Now I can directly assign this delegate as the value of any properties with a matching delegate type:
Hope that helps :)