将任务<T>转换为任务<DerivedT>

Chr*_*sCa 6 c# asynchronous task

我有一个看起来像这样的同步通用方法

public TResponse Execute<TResponse>(Request request) where TResponse : Response
{
   return (TResponse) proxy.ExecuteRequest(request);
Run Code Online (Sandbox Code Playgroud)

代理是WCF服务引用

它只有一个接收请求并返回响应的方法.但它通过传递派生请求和返回派生响应来使用.如上所示,包装器方法将响应转换为泛型参数(TResponse)指定的派生类型.

您使用派生的请求和响应调用该方法

例如

Execute<GetSomeDataResponse>(new GetSomeDataRequest());
Run Code Online (Sandbox Code Playgroud)

我现在正在生成异步服务引用,因此可以使用任务

所以我想要一个看起来像这样的方法

public Task<TResponse> ExecuteAsync<TResponse>(Request request) where TResponse : Response
{
    // need to cast to a Task<TResponse>
    return proxy.ExecuteRequestAsync(request
Run Code Online (Sandbox Code Playgroud)

可以像这样调用

Task<GetSomeDataResponse> res = ExecuteAsync<GetSomeDataResponse>(new GetSomeDataRequest());
Run Code Online (Sandbox Code Playgroud)

所以我需要一种方法来投射Task<Response>Task<TResponse>

我一直在阅读这个看起来与我需要的相反,但是无法弄清楚如何将它弯曲到我的用例

如何将Task <TDerived>转换为Task <TBase>?

有任何想法吗?

Evk*_*Evk 3

简单的方法是使用 async\await 模式:

 public static async Task<TResponse> ExecuteAsync<TResponse>(Request request) where TResponse : Response {
    var response = await proxy.ExecuteRequestAsync(request);
    return (TResponse) response;
 }
Run Code Online (Sandbox Code Playgroud)

稍微复杂一点(取自您的链接问题)是使用TaskCompletionSource

public static Task<TResponse> ExecuteAsync2<TResponse>(Request request) where TResponse : Response {
    var tcs = new TaskCompletionSource<TResponse>();
    proxy.ExecuteRequestAsync(request).ContinueWith(t => {
        if (t.IsFaulted)
            tcs.TrySetException(t.Exception.InnerExceptions);
        else if (t.IsCanceled)
            tcs.TrySetCanceled();
        else
            tcs.TrySetResult((TResponse) t.Result);
        }, TaskContinuationOptions.ExecuteSynchronously);
    return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)