我有一个充满扩展方法的静态类,其中的每个方法都是异步的,并返回一些值-像这样:
public static class MyContextExtensions{
public static async Task<bool> SomeFunction(this DbContext myContext){
bool output = false;
//...doing stuff with myContext
return output;
}
public static async Task<List<string>> SomeOtherFunction(this DbContext myContext){
List<string> output = new List<string>();
//...doing stuff with myContext
return output;
}
}
我的目标是能够从另一个类的单个方法中调用任何这些方法,并将其结果作为对象返回。它看起来像这样:
public class MyHub: Hub{
public async Task<object> InvokeContextExtension(string methodName){
using(var context = new DbContext()){
//This fails because of invalid cast
return await (Task<object>)typeof(MyContextExtensions).GetMethod(methodName).Invoke(null, context);
}
}
}
问题是强制转换失败。我的困境是我无法将任何类型参数传递给“InvokeContextExtension”方法,因为它是SignalR集线器的一部分,并由javascript调用。在某种程度上,我不在乎扩展方法的返回类型,因为它只会序列化为JSON并发送回javascript客户端。但是,我必须将Invoke返回的值强制转换为Task才能使用await运算符。而且我必须为该“任务”提供一个通用参数,否则它将把返回类型视为无效。因此,一切都取决于我如何将具有通用参数T的Task成功地转换为具有对象通用参数的Task,其中T表示扩展方法的输出。
最佳答案
您可以分两个步骤进行操作-使用基类对任务执行await
,然后使用反射或dynamic
收获结果:
using(var context = new DbContext()) {
// Get the task
Task task = (Task)typeof(MyContextExtensions).GetMethod(methodName).Invoke(null, context);
// Make sure it runs to completion
await task.ConfigureAwait(false);
// Harvest the result
return (object)((dynamic)task).Result;
}
这是一个完整的运行示例,将通过反射调用
Task
的上述技术置于上下文中:class MainClass {
public static void Main(string[] args) {
var t1 = Task.Run(async () => Console.WriteLine(await Bar("Foo1")));
var t2 = Task.Run(async () => Console.WriteLine(await Bar("Foo2")));
Task.WaitAll(t1, t2);
}
public static async Task<object> Bar(string name) {
Task t = (Task)typeof(MainClass).GetMethod(name).Invoke(null, new object[] { "bar" });
await t.ConfigureAwait(false);
return (object)((dynamic)t).Result;
}
public static Task<string> Foo1(string s) {
return Task.FromResult("hello");
}
public static Task<bool> Foo2(string s) {
return Task.FromResult(true);
}
}