Search code examples
c#dynamicasync-awaitcastinginvoke

Cast object to awaitable type unknown at compile time


I have a concrete instance of IHandler<T> registered in the Microsoft IServiceProvider:

public interface IHandler<T>
{
    Task<T> HandleAsync();
}

The type T is only known at runtime, and I resolve the handler like this:

var myObject = new MyObject();
var handlerType = typeof(IHandler<>).MakeGenericType(myObject.GetType());
var handler = _serviceProvider.GetService(handlerType);

The problem is that the returned handler is of the type object (but when debugging I can verify that it in fact is the concrete type registered).

How can I convert the object handler into a variable that I can do await handler.HandleAsync() on?


Edit:

The question was originally a bit unclear as, ironically, I tried to make it simpler. The handlerType was like this before:

var handlerType = typeof(IHandler<>).MakeGenericType(typeof(T));

indicating that T is a generic type, which it is not. The question has been updated to reflect that the T is an object instance.


Solution

  • Use dynamic.

    public interface IHandler<T> 
    {
        Task<T> HandleAsync();
    }
    
    public class StringHandler : IHandler<string>
    {
        public async Task<string> HandleAsync()
        {
            return "Hello world!";
        }
    }
    
    public class Program
    {
        public static object GetHandler() => new StringHandler();
    
        public static void Main()
        {
            MainAsync().GetAwaiter().GetResult();
        }
    
        public static async Task MainAsync()
        {
            dynamic handler = GetHandler();                //<--- Here is the magic
            object result = await handler.HandleAsync();   //<---
            Console.WriteLine("Result is '{0}'", result);
        }
    }
    

    Results:

    Hello world!
    

    Link to fiddle