Ho (per esempio) un Func<int, int>
che voglio chiamare come al solito, tranne che il parametro è di tipo object
rater che int
. Conosco solo il tipo esatto di Func e l'argomento in fase di esecuzione, poiché Func è stato creato utilizzando gli alberi di espressione e ora è accessibile da una variabile dynamic
. Esempio di codice (semplificato):
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
}
}
}
Come posso fare il codice convertito arg
in un numero intero o qualunque tipo l'argomento è? Ho provato a creare un metodo generico che proietta l'oggetto su un determinato tipo e quindi lo invoca tramite il reflection in questo modo:
public static T asT<T>(object n)
{
return (T)n;
}
per getFromFunc
:
MethodInfo con = typeof(Program).GetMethod("asT").MakeGenericMethod(func.GetType().GetGenericArguments()[0]);
return dfunc(con.Invoke(null, new[] { value }));
Ma MethodInfo.Invoke
restituisce anche object
. Qualche idea su come assicurarsi che l'argomento abbia il tipo corretto?
Stai già utilizzando la dynamic
, quindi perché non utilizzare la dynamic
?
return dynFunc((dynamic)arg);
Questo assicura che il tipo di runtime di arg
venga usato per determinare se si tratta di un argomento appropriato.
Tutti i delegati derivano da System.Delegate. È possibile utilizzare il metodo System.Delegate.DynamicInvoke per chiamare un delegato di cui non si conosce il tipo al momento della compilazione, in modo simile a chiamare un metodo utilizzando MethodInfo.Invoke (). Per esempio:
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);
}
}