Reputation:
I have (for instance) a Func<int, int>
which I want to call as usual, except that the parameter is of type object
rater than int
. I only know the exact type of the Func and the argument at runtime, because the Func was created using Expression trees and is now accessed from a dynamic
variable. (Simplified) code example:
using System.Linq.Expressions;
namespace FuncExample
{
class Program
{
static void Main(string[] args)
{
object myFunc = CreateFunc(); // Could return something like
// Func<int, int>, but may return a
// completely different Func<> depending on
// arguments etc.
object result = getFromFunc(5, myFunc);
}
public static object CreateFunc()
{
LambdaExpression expr = Expression.Lambda(
/*
* Create an expression
*/
);
return expr.Compile();
}
public static object getFromFunc(object arg, object func)
{
dynamic dynFunc = func;
return dynFunc(arg); // <------- Throws exception
}
}
}
How can I make the code convert arg
into an integer or whatever Type the argument is? I tried making a generic method that casts the object to a certain type and then invoking it through reflection like this:
public static T asT<T>(object n)
{
return (T)n;
}
for getFromFunc
:
MethodInfo con = typeof(Program).GetMethod("asT").MakeGenericMethod(func.GetType().GetGenericArguments()[0]);
return dfunc(con.Invoke(null, new[] { value }));
But MethodInfo.Invoke
also returns object
.
Any ideas on how to make sure the argument has the correct type?
Upvotes: 1
Views: 3722
Reputation: 59
All delegates derive from System.Delegate. You can use the System.Delegate.DynamicInvoke method to call a delegate whose type you don't know at compile time, similar to calling a method using MethodInfo.Invoke(). For example:
class Program
{
public static Delegate CreateFunc()
{
return new Func<int, int>(x => x + 1);
}
public static void Main(string[] args)
{
var func = CreateFunc();
object inArg = 42;
object result = func.DynamicInvoke(inArg);
Console.WriteLine(result);
}
}
Upvotes: 5
Reputation: 624
What about something like this?
public static int Main(string[] args)
{
// this could be any other lambda expression
Func<object, object> unknownFunc = (a) => { return 13; };
int result = (int) unknownFunc(13);
Console.WriteLine(result);
return 0;
}
Upvotes: 0
Reputation:
You're already using dynamic
, so why not use dynamic
?
return dynFunc((dynamic)arg);
This makes sure arg
's runtime type gets used for determining whether it's an appropriate argument.
Upvotes: 3