Baked Inhalf
Baked Inhalf

Reputation: 3735

Invoke async Task in abstract class via Reflection

I'm trying to run tasks async by using reflection. The problem is that the class is abstract. I got this to work with InvokeMember in a synchronous context. With async the method is not found for some reason.. So this is what I came up with instead. It's not working because I can't pass an object of an abstract class to the Invoke method.. dead end?

public MyClass
{
  public async Task<string> MyMethod()
  { 
    var tasks = new List<Task>();

    for (int i = 0; i < 3; i++)
    {
       string taskType = "Banana"; // should be an array[i] 
       Type type = Type.GetType("MyService." + taskType);
       var method = type.GetMethod("Test");

       var result = (Task<string>)method.Invoke(null, null);

       tasks.Add(result);
    }    
    await Task.WhenAll(tasks);
  }
}

And for example the 'taskType' above is a class which looks like this:

public abstract class Banana
{
    public async Task<string> Test(string input)
    {
        await Task.Delay(5000);
        return "foo";
    }
}

Upvotes: 1

Views: 543

Answers (1)

mu88
mu88

Reputation: 5384

We've discussed this in the comments, but maybe the following code gives you a better idea.

public class MyClass
{
  public async Task<string> MyMethod()
  { 
    var tasks = new List<Task>();

    for (int i = 0; i < 3; i++)
    {
       string taskType = "Banana"; // should be an array[i] 
       Type type = Type.GetType("MyService." + taskType);
       var method = type.GetMethod("Test");

       var result = (Task)method.Invoke(null, null);

       tasks.Add(result);
    }
    await Task.WhenAll(tasks);

    var theResult = string.Empty;
    foreach(var task in tasks)
    {
      theResult += (string)task.GetType().GetProperty("Result").GetValue(task);
    }

    return theResult;
  }
}

I've written it completely blind and couldn't test it - bear with me!

But the general idea is the following: the concrete async method is of Task<string>, but I couldn't find a way to invoke an async generic method. But since every Task<T> is a non-generic Task, we can cast to it and await it. The additional knowledge that each element within tasks is a Task<string> allows us to retrieve its property Result via reflection.

Upvotes: 2

Related Questions