ChrisCa
ChrisCa

Reputation: 11006

Casting a Task<T> to a Task<DerivedT>

I have a synchronous, generic method that looks like this

public TResponse Execute<TResponse>(Request request) where TResponse : Response
{
   return (TResponse) proxy.ExecuteRequest(request);

the proxy is a WCF service reference

It just has one method that takes a request and returns a response. But it is used by passing derived requests and returning derived responses. As you can see above the wrapper method is casting the response to the derived type specified by the generic parameter (TResponse).

You call the method with derived requests and responses

e.g.

Execute<GetSomeDataResponse>(new GetSomeDataRequest());

I am now generating an async service reference so can make use of Tasks

So I would like a method that looks like this

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

that can be called like this

Task<GetSomeDataResponse> res = ExecuteAsync<GetSomeDataResponse>(new GetSomeDataRequest());

So I need a way to cast the Task<Response> to a Task<TResponse>

I've been reading this which seems kind of the opposite of what I need, but cant quite figure out how to bend it to my use case

How to convert a Task<TDerived> to a Task<TBase>?

any ideas?

Upvotes: 7

Views: 1519

Answers (1)

Evk
Evk

Reputation: 101473

Easy way is use async\await pattern:

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

A bit more complicated (taken from your linked question) is to use 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;
}

Upvotes: 3

Related Questions