Reputation: 541
What I am trying to do is the following (which I necessarily don't know if it's even possible); I know a run time type. I know which method I want to invoke in run time. However, I don't know this in compile time.
The GetFunction method won't be able to create a delegate of the given methodInfo since the inparam isn't of type object.
Is there a way to create a delegate of a function where I only know a Type and a MethodInfo of the method I wish to delegate?
public sealed class Functions {
public static int SetStrValue(string s) {
// set a string
}
public static int SetIntValue(int i) {
// set an int
}
}
public sealed class GetFunctions {
public Func<object, int> GetFunction(Type type, MethodInfo methodInfo) {
// what I would like to do.
Func<object, int> func = Delegate.CreateDelegate(typeof(Func<object, int>), methodInfo);
return t => func(t);
}
}
public class InvokeFunctions {
public void invokeFunction() {
Type t = typeof(String);
MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
int i = GetFunctions.GetFunction(t, methodInfo).Invoke("hello");
}
}
Upvotes: 3
Views: 3086
Reputation: 73452
You can use expression trees to create a delegate. As the compile time type is not known you could try to cast the parameter to the appropriate type at runtime.
public sealed class GetFunctions
{
public static Func<object, int> GetFunction(MethodInfo methodInfo)
{
var obj = Expression.Parameter(typeof (object), "obj");
var convert = Expression.Convert(obj, methodInfo.GetParameters().First().ParameterType);
var call = Expression.Call(methodInfo, convert);
var lambda = Expression.Lambda<Func<object, int>>(call, obj);
return lambda.Compile();
}
}
public class InvokeFunctions
{
public void invokeFunction()
{
MethodInfo methodInfo = typeof(Functions).GetMethod("SetStrValue");
int i = GetFunctions.GetFunction(methodInfo).Invoke("hello");
MethodInfo methodInfo2 = typeof(Functions).GetMethod("SetIntValue");
int i2 = GetFunctions.GetFunction(methodInfo2).Invoke(1);
}
}
I've removed the Type
parameter and taken it directly from Method's first parameter, If that's not the intended behavior you can change it.
Upvotes: 5
Reputation: 298
You can use generics to simplify this to just:
public sealed class Functions
{
public static int SetValue<T>(T input)
{
// set a value of type T
}
}
And call the function with:
Functions.SetValue<string>("hello");
Or you could use a generic delegate definition if you still want to use delegates:
public delegate int MyDelegateFunction<T>(T input);
Upvotes: 0