Monday 27 August 2018

Generics and Reflection and Async :)

Sometimes, using Reflection based code can lead you into true wilderness. Especially when your classes and methods make use of generics. Throw in async/await pattern implementation too. You suddenly start to ask why are you writing code using reflection in the first place :).

I ran into a similar situation recently.

I had a generic method like following:

public class Test
{      public async Task < T[] > Method(arguments);
{
////....
}
}

Now let us say you have to invoke this method on-demand for any type defined in your object models. What are your options?

1. Write a huge switch case where each case belongs to a type and makes a call for each type. That works but requires a lot of maintenance. Whenever you add a new type, you have to add to that switch case.

2. Change signature of the method to start return JSON and deserialize it in the calling method.

3. Call this method through reflection :).

var method = typeof(Test).GetMethod("Method"); 

var methodReference = method?.MakeGenericMethod("type that needs to be used"); 

var response = methodReference.Invoke(instance of Test, arguments);

But wait, this is an async method. You will be getting a Task, not the actual result.

So what do we do?

Hmm... We can not cast it to Task because T is dynamic. What else can we do?

Change the method signature to return generic Array instead of T[].

public async Task < Array > Method(arguments);

and change the calling method to following:

var response = (await) ((Task < Array >)methodReference.Invoke(instance of Test, arguments);

Solved :).