public interface IBar { } public class Bar : IBar { } public class Bar2 : IBar { } public interface IFoo { Task<T> Get<T>(T o) where T : IBar; } public class Foo : IFoo { public async Task<T> Get<T>(T o) where T : IBar { ... } }
I can then call this method using reflection:
var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar2.GetType()); var task = generic.Invoke(foo, new [] { bar2 });
How do I await on this Task
? and How do I cast it to Task<bar2.GetType()>
?
The simplest way to execute a method asynchronously is to start executing the method by calling the delegate's BeginInvoke method, do some work on the main thread, and then call the delegate's EndInvoke method. EndInvoke might block the calling thread because it does not return until the asynchronous call completes.
STEP 01 Create new MVC Application project, named as "Async". In the File menu, click New Project. In the "New Project" dialog box, under Project types, expand Visual C#, and then click "Web". In the Name box, type "Async", then click on Ok.
Solution A If you have a simple asynchronous method that doesn't need to synchronize back to its context, then you can use Task. WaitAndUnwrapException : var task = MyAsyncMethod(); var result = task. WaitAndUnwrapException();
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
Because Task<T>
derives from Task
you can await on just that, once the task is awaited you can use reflection to safely access the .Result
property via reflection.
Once you have the result you will either need to store it in a IBar
and use the methods and properties on that or cast to the specific type after testing to use the type specific methods.
Here is a full MCVE of it
using System; using System.Reflection; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Test().Wait(); Console.ReadLine(); } static async Task Test() { var foo = new Foo(); var bar2 = new Bar2(); object resultObject = await CallGetByReflection(foo, bar2); IBar result = (IBar)resultObject; result.WriteOut(); //or if (resultObject is Bar) { ((Bar)resultObject).Something(); } else if (resultObject is Bar2) { ((Bar2)resultObject).SomethingElse(); } } private static async Task<object> CallGetByReflection(IFoo foo, IBar bar) { var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar.GetType()); var task = (Task) generic.Invoke(foo, new[] {bar}); await task.ConfigureAwait(false); var resultProperty = task.GetType().GetProperty("Result"); return resultProperty.GetValue(task); } public interface IBar { void WriteOut(); } public class Bar : IBar { public void Something() { Console.WriteLine("Something"); } public void WriteOut() { Console.WriteLine(nameof(Bar)); } } public class Bar2 : IBar { public void SomethingElse() { Console.WriteLine("SomethingElse"); } public void WriteOut() { Console.WriteLine(nameof(Bar2)); } } public interface IFoo { Task<T> Get<T>(T o) where T : IBar; } public class Foo : IFoo { public async Task<T> Get<T>(T o) where T : IBar { await Task.Delay(100); return o; } } } }
UPDATE: Here is a extension method to simplify the process
public static class ExtensionMethods { public static async Task<object> InvokeAsync(this MethodInfo @this, object obj, params object[] parameters) { var task = (Task)@this.Invoke(obj, parameters); await task.ConfigureAwait(false); var resultProperty = task.GetType().GetProperty("Result"); return resultProperty.GetValue(task); } }
This turns CallGetByReflection
in to
private static Task<object> CallGetByReflection(IFoo foo, IBar bar) { var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar.GetType()); return generic.InvokeAsync(foo, new[] {bar}); }
UPDATE 2: Here is a new extension method that works with any awaitable type instead of only tasks by using dynamic
and GetAwaiter()
public static class ExtensionMethods { public static async Task<object> InvokeAsync(this MethodInfo @this, object obj, params object[] parameters) { dynamic awaitable = @this.Invoke(obj, parameters); await awaitable; return awaitable.GetAwaiter().GetResult(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With