MarkPflug
MarkPflug

Reputation: 29548

Is it possible to invoke a dynamic object in C#?

I have a situation where I have an object of type "dynamic" that is invokable. I'm trying to implement a function that will invoke the object dynamically at runtime with a set of arguments. It is easy enough to invoke it if I know the number of arguments at compile time:

Object StaticInvoke(dynamic func, Object[] args) {
    // arguments are explicitly unwrapped and bound to the invokation
    // requiring that we know the number at compile time
    return func(args[0], args[1], ...); 
}

But, this doesn't accomplish what I want because the args array could be of variable length. I can't figure out a way to support an arbitrary number of arguments. The closest I've come up with is something like:

static Object Invoke(dynamic func, Object[] args)
{

    // not sure what to put here
    switch(args.Length)
    {
        case 0:
            return func();
        case 1:
            return func(args[0]);
        case 2:
            return func(args[0], args[1]);
        ...
        default:
            throw new NotSupportedException();
    }
}

Which would limit the number of arguments I could possibly pass. I guess I could live with this limitation, but it feels like what I'm trying to do should be possible.

I'm basically trying to implement the javascript "apply" function in C#. Is there an easier way to accomplish what I'm trying to do? I feel like I'm missing something obvious.

Upvotes: 1

Views: 360

Answers (2)

jbtule
jbtule

Reputation: 31809

The opensource apache licensed ImpromptuInterface (on nuget) has a static method Impromptu.Invoke that does this. You can look at the implementation, while it handles an arbitrary number of arguments, it also does work that you probably don't need such as providing a mechanism to dynamically described named arguments and invoke them.

Your switch case idea might actually be the way to go depending on your usage as it should be both simple and fast.

With your switch case, with N being the largest number of arguments you support, the C# compiler will create N+1 callsites that it just statically knows where they are. Impromptu will being calling the dlr apis, just like the compiler, but it will be storing the callsite in a hashtable which will add look up time (not bad though).

The dlr api's also require a delegate the has a signature that matches the number or arguments your are calling, again the compiler will make sure you statically have N+1 delegates, while Impromptu will use the 17 built-in Func<> in a switch case and then start emiting new delegates as needed, it's a one time heavy cost to generate and then adds more hashtable look ups for subsequent calls.

Upvotes: 1

Alexei Levenkov
Alexei Levenkov

Reputation: 100610

EDIT: This is not an answer - keeping it here to let others know that it is unlikely what @Mark looking for.

For regular objects you would use MethodBase.InvokeMethod:

 MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
 object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});

Upvotes: 0

Related Questions