等待Task< TDerived>的结果.在非泛型方法中使用反射 [英] Await the result of Task<TDerived> using reflection in a non-generic method

查看:63
本文介绍了等待Task< TDerived>的结果.在非泛型方法中使用反射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下情况:

class A
{
    public int Id;
}

class B : A
{

}

class Main
{
    public async Task<int> Create(Type type)
    {
        MethodInfo method = this.GetType().GetMethod("Create", new Type[] { typeof(string) }).MakeGenericMethod(new Type[] { type });
        A a = await (Task<A>)method.Invoke(this, new object[] { "humpf" });
        return a.Id;
    }

    public async Task<T> Create<T>(string name) where T : A
    {
        T t = await Foo.Bar<T>(name);
        return t;
    }
}

呼叫new Main().Create(typeof(B))将失败,并显示

无法将类型为"System.Threading.Tasks.Task[B]"的对象强制转换为 输入"System.Threading.Tasks.Task[A]"

Unable to cast object of type 'System.Threading.Tasks.Task[B]' to type 'System.Threading.Tasks.Task[A]'

我不太了解,因为在这种情况下,通用Create<T>方法只能返回Task<T>,其中T始终是从'A'派生的,但也许我缺少了边缘情况这里. 除此之外,我该如何进行这项工作?谢谢!

I don't quite understand because in this case, the Generic Create<T> method can only return a Task<T> where T is always derived from 'A', but maybe I'm missing an edge case here. Besides that, how can I make this work? Thanks!

推荐答案

根据我的评论:

与接口不同,Task<TResult>之类的具体类型不能协变.请参阅为什么Task不是协变的?.因此无法将Task<B>分配给Task<A>.

Unlike interfaces, concrete types such as Task<TResult> cannot be covariant. See Why is Task not co-variant?. So Task<B> cannot be assigned to a Task<A>.

我能想到的最好的解决方案是使用基础类型Task来执行await,如下所示:

The best solution I can think of is to use the underlying type Task to perform the await like so:

var task = (Task)method.Invoke(this, new object[] { "humpf" });
await task;

然后您可以使用反射来获取Result的值:

Then you can use reflection to get the value of the Result:

var resultProperty = typeof(Task<>).MakeGenericType(type).GetProperty("Result");
A a = (A)resultProperty.GetValue(task);
return a.Id;

这篇关于等待Task&lt; TDerived&gt;的结果.在非泛型方法中使用反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆