Walter Kelt
Walter Kelt

Reputation: 2279

Combining Tasks with Reflection

I have a situation where a List of strings is provided. The first entry in the list is the name of a method. The remaining strings in the list are method arguments. I'd like to use a task to run the method (for educational purposes). I am having problems figuring out the proper procedure that would allow me to feed the method name into the Task instruction.

For this example, I have two statics methods that could be run as a Task. args[1] would signify my selection.

public class Program
{
    private static ILog log = LogManager.GetLogger 
                    (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    static void Main(string[] args)
    {
        string whichPrint = args[1];

        Type type = typeof(Program);
        MethodInfo meth = type.GetMethod(whichPrint, BindingFlags.Public | 
                                                           BindingFlags.Static);

        //this is the problem area....how do I feed the the method or delegate into 
        //the lambda expression ????
        Delegate methDel = meth.CreateDelegate(type);
        Task t = Task.Factory.StartNew(() => methDel("help!!"));

    }

    static void printme1(string s)
    {
        log.Debug("Printme1 Printing: " + s);
    }

    static void printme2(string s)
    {
        log.Debug("Printme2 Printing: " + s);
    }
}

I can't compile since methDel is being viewed as variable. I need it, or something else, to be viewed as a method. I don't want to use case/switch statements since I may have a lot of methods that could be assigned to a task.

Upvotes: 2

Views: 1655

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1502716

The fact that you're going to create a new task with this is somewhat irrelevant. All you need to do is work out how to call the method, and the rest is just "start a new task which then calls the method".

So you probably want something like:

public static void CallMethod(List<string> nameAndArguments)
{
    var method = typeof(Program).GetMethod(nameAndArguments[0]);
    method.Invoke(null, nameAndArguments.Skip(1).ToArray()):
}

Then:

Task.Factory.StartNew(() => CallMethod(nameAndArguments));

I don't think it's worth building a delegate unless you're trying to get better performance out of calling that delegate lots of times.

Upvotes: 5

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236278

I think you don't need delegate here - just invoke method in Action body. Also your methods are private, not public:

MethodInfo meth = type.GetMethod(whichPrint, BindingFlags.NonPublic |
                                             BindingFlags.Static);
Task t = Task.Factory.StartNew(() => meth.Invoke(null, new object[] {"help!!"}));

Upvotes: 2

Related Questions