如何使用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
? 以及如何将其Task
为Task
?
因为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
更新 :这是一个简化过程的扩展方法
public static class ExtensionMethods { public static async Task
这会将CallGetByReflection
为
private static Task
更新2 :这是一个新的扩展方法,可以使用dynamic
和GetAwaiter()
处理任何等待类型而不是任务
public static class ExtensionMethods { public static async Task
基于您的示例,您知道在编译时返回对象的类型 – > 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());