user2037593
user2037593

Reputation:

Call Func<> with argument of type object

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

Answers (3)

Adam Jenkins
Adam Jenkins

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

dinony
dinony

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

user743382
user743382

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

Related Questions