Happy Go Lucky
Happy Go Lucky

Reputation: 617

Asynchronous runtime method invocation

I am loading some assemblies at run time and invoking methods on them using Reflections (MethodInfo.Invoke).

Now I want to make these calls asynchronous. So I am thinking of using Delegate.BeginInvoke(). But I am not sure how to create delegate instance by providing function name at run-time. (All examples I see have delegate instance target resolved at compile time itself.) I have a MethodInfo object containing the method to be invoked. Is there a way to do this?

   public void Invocation(Object[] inputObjs)
    {
        public delegate string DelegateMethodInfo(int num);

        Assembly assm = Assembly.Load(assemblyName);
        Type type = assm.GetType(className);
        Type[] ctorParams = new Type[0];
        Object[] objs = new Object[0];

        ConstructorInfo ctorInf = type.GetConstructor(ctorParams);
        Object classObj = ctorInf.Invoke(objs);
        MethodInfo methodInf = type.GetMethod(methodName);

        // Need asynchronous invocation.
        //Object retObj = methodInf.Invoke(classObj, inputObjs);

        DelegateMethodInfo del = new DelegateMethodInfo(???); // How to instantiate the delegate???
        del.BeginInvoke((int)inputObjs[0], null, null);
    }

Upvotes: 2

Views: 3560

Answers (4)

Orion Edwards
Orion Edwards

Reputation: 123642

This is similar to the other answers, but you can create a new Func and assign the methodInf.Invoke method to it. Here's an example

class Other
{
    public void Stuff()
    { Console.WriteLine("stuff"); }
}

static void Main(string[] args)
{
    var constructor = typeof(Other).GetConstructor(new Type[0]);
    var obj = constructor.Invoke(null);

    var method = typeof(Other).GetMethods().First();
    Func<object, object[], object> delegate = method.Invoke;
    delegate.BeginInvoke(obj, null, null, null);

    Console.ReadLine();
}

What it's doing is creating a new variable of type Func<object, object[], object>, which matches the signature of MethodInfo.Invoke. It then gets a reference to the actual invoke method on your object, and sticks that reference in the variable.

Because Func<> is a delegate type, you can then use BeginInvoke

Upvotes: 1

Jim L
Jim L

Reputation: 2327

Have you looked at using MethodInvoker (The delegate, not the class) and not trying to create an additional delegate? By using an anonymous method with this, you may be able to pull off what you need. Or I may be smoking crack. But, basically, MethodInvoker acts as a standard parameterless delegate then in the anon method, you pass your parameters to MethodInvoker's anonmous code. I've used it in WinForms to do Form.BeginInvoke without needing to create delegates left and right. If need to and you can wait, respond to me and I'll get you sample code tonight (I'm on US West Coast... GMT -8).

Upvotes: 0

Dario
Dario

Reputation: 49218

Just use a lambda expression that wraps the call to methodInf.Invoke. The resulting delegate is of type DelegateMethodInfo.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500385

You can use Delegate.CreateDelegate - but you'll need to know the signature so that you've got an appropriate type of delegate to create. That's slightly tricky when you've basically just got the MethodInfo :( Even worse, there's no equivalent of Delegate.DynamicInvoke for asynchronous execution.

To be honest, the simplest thing would be to start a new thread pool job which invoked the method:

ThreadPool.QueueUserWorkItem(delegate { methodInf.Invoke(classObj, inputObjs);});

Upvotes: 4

Related Questions