Call Func <> con argumento de tipo objeto

c# expression-trees func

Pregunta

Tengo (por ejemplo) un Func<int, int> que quiero llamar como de costumbre, excepto que el parámetro es de tipo de evaluador de object que int . Solo conozco el tipo exacto del Func y el argumento en tiempo de ejecución, porque el Func se creó utilizando árboles de Expresión y ahora se accede desde una variable dynamic . Ejemplo de código (simplificado):

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
        }
    }
}

¿Cómo puedo hacer que el código convierta arg en un número entero o el tipo que sea el argumento? Intenté crear un método genérico que convierte el objeto en un determinado tipo y luego lo invoco a través de una reflexión como esta:

public static T asT<T>(object n)
{
    return (T)n;
}

para getFromFunc :

MethodInfo con = typeof(Program).GetMethod("asT").MakeGenericMethod(func.GetType().GetGenericArguments()[0]);
return dfunc(con.Invoke(null, new[] { value }));

Pero MethodInfo.Invoke también devuelve object . ¿Alguna idea sobre cómo asegurarse de que el argumento tiene el tipo correcto?

Respuesta aceptada

Ya estás usando dynamic , ¿por qué no usar dynamic ?

return dynFunc((dynamic)arg);

Esto asegura que el tipo de tiempo de ejecución de arg se use para determinar si es un argumento apropiado.


Respuesta popular

Todos los delegados derivan de System.Delegate. Puede usar el método System.Delegate.DynamicInvoke para llamar a un delegado cuyo tipo no conoce en el momento de la compilación, similar a llamar a un método usando MethodInfo.Invoke (). Por ejemplo:

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);
    }
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow