如何使用reflection调用通用异步方法

public interface IBar { } public class Bar : IBar { } public class Bar2 : IBar { } public interface IFoo { Task Get(T o) where T : IBar; } public class Foo : IFoo { public async Task Get(T o) where T : IBar { ... } } 

然后我可以使用reflection调用此方法:

 var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar2.GetType()); var task = generic.Invoke(foo, new [] { bar2 }); 

我如何等待这个Task ? 以及如何将其TaskTask

因为Task派生自Task您可以等待,只要等待任务,您就可以使用reflection通过reflection安全地访问.Result属性。

获得结果后,您需要将其存储在IBar并使用其上的方法和属性,或者在测试后转换为特定类型以使用特定于类型的方法。

这是一个完整的MCVE

 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 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 Get(T o) where T : IBar; } public class Foo : IFoo { public async Task Get(T o) where T : IBar { await Task.Delay(100); return o; } } } } 

更新 :这是一个简化过程的扩展方法

 public static class ExtensionMethods { public static async Task 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); } } 

这会将CallGetByReflection

 private static Task 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}); } 

更新2 :这是一个新的扩展方法,可以使用dynamicGetAwaiter()处理任何等待类型而不是任务

 public static class ExtensionMethods { public static async Task InvokeAsync(this MethodInfo @this, object obj, params object[] parameters) { dynamic awaitable = @this.Invoke(obj, parameters); await awaitable; return awaitable.GetAwaiter().GetResult(); } } 

基于您的示例,您知道在编译时返回对象的类型 – > IFoo ,因此您可以使用普通转换(IFoo)

 var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(typeof(IBar)); var task = (Task)generic.Invoke(foo, new [] { bar2 }); IBar result = await task; 

如果您在编译时不知道类型,那么只需使用dynamic关键字

 var method = typeof(IFoo).GetMethod(nameof(IFoo.Get)); var generic = method.MakeGenericMethod(bar2.GetType()); dynamic task = generic.Invoke(foo, new [] { bar2 }); IBar result = await task; 

但是如果任务的类型不是运行时的Task – 将抛出exception
如果你需要具体类型的IBar那么

 var concreteResult = Convert.ChangeType(result, bar2.GetType());