2016-05-13 40 views
6

Ho un, metodo generico sincrono che assomiglia a questoCasting un'attività <T> a un'attività <DerivedT>

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

il proxy è un riferimento al servizio WCF

'solo un metodo che accetta una richiesta e restituisce una risposta. Ma è usato passando richieste derivate e restituendo risposte derivate. Come puoi vedere sopra, il metodo wrapper lancia la risposta al tipo derivato specificato dal parametro generico (TResponse).

Si chiama il metodo con le richieste e le risposte

esempio derivati

Execute<GetSomeDataResponse>(new GetSomeDataRequest()); 

ora sto generando un riferimento al servizio asincrono in modo da può fare uso di task

Quindi vorrei un metodo che assomiglia a questo

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

che può essere chiamato in questo modo

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

Quindi ho bisogno di un modo per trasmettere il Task<Response> a un Task<TResponse>

ho letto questo, che sembra tipo di l'opposto di quello che mi serve, ma non posso a capire come piegare al mio caso d'uso

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

tutte le idee?

+0

Beh, si può sempre e solo 'ritorno (TDerived) (attende ExecuteRequestAsync (richiesta)); '. – Luaan

+0

@Luaan sfortunatamente ExecuteRequestAsync non è un metodo asincrono nel senso di .net 4.5 - restituisce solo un'attività . non ha una parola chiave asincrona nella sua firma (generata da svcutil quindi non posso cambiarlo) – ChrisCa

+1

@ChrisCa ExecuteRequestAsync non ha bisogno di alcuna parola chiave asincrona, come fa il tuo ExecuteAsync. – Evk

risposta

2

modo semplice è utilizzare asincrono \ await modello:

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

Un po 'più complicato (preso dalla tua domanda linked) è quello di utilizzare 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; 
} 
+0

ah - ovviamente. Non posso credere che non ho potuto vedere il tuo primo esempio - grazie! – ChrisCa