2012-11-26 19 views
47

Ho un'applicazione. Questa applicazione utilizza un'interfaccia per accedere al database. Questa interfaccia può essere implementata da molte classi. Ad esempio, si utilizza EF 4.4, ma altre classi possono utilizzare EF5 che è più efficiente. In futuro forse userò EF6 perché usa metodi asincroni. In questo esempio tutti i metodi utilizzano EF, ma forse altre opzioni possono essere utilizzate in altri modi.Interfacce e metodi asincroni

L'applicazione è codificata una volta, utilizzando l'interfaccia e, in base al file di configurazione, utilizzare un'implementazione o l'altra, quindi ho solo bisogno di modificare il codice in un unico posto, il costruttore, per aggiungere la nuova opzione nel istanziazione della classe che è assegnata all'interfaccia.

Al momento tutti i metodi delle classi non sono async, ma in futuro, se utilizzo EF6, vorrei utilizzare i metodi asincroni, quindi non so se è possibile che la classe che usa EF6 e implementa l'interfaccia può utilizzare i metodi async.

Per i metodi asincroni di EF6, vorrei utilizzare il modello async/awiat, quindi nel metodo della mia classe ho bisogno di usare l'attributo async. Questo mi permette di usare la parola chiave await quando chiamo al metodo asincrono di EF6.

Ma questa classe può implementare l'interfaccia che per la prima volta è per i metodi sincroni?

C'è un modo in cui nell'applicazione principale posso utilizzare molte implementazioni senza la necessità di modificare il codice? Alcune implementazioni useranno metodi asincroni mentre altre saranno sincrone.

+2

Ricordare che 'async' non fa parte della firma; un metodo asincrono e un metodo non asincrono possono entrambi implementare lo stesso metodo di interfaccia. – Servy

+1

Non è il metodo che è attendibile, è il tipo (di ritorno). – rism

+1

Troppe spiegazioni per una semplice domanda. A PARER MIO. – Mahmoodvcs

risposta

55

async non è una parte della firma, quindi non è necessario preoccuparsi del fatto che il metodo di implementazione dell'interfaccia sia async oppure no, è sufficiente preoccuparsi dei tipi di proprietà, tipo di ritorno, il nome del metodo e l'accessibilità.

Il vera differenza è che i vostri metodi async dovranno restituire un Task o un Task<T>, mentre i metodi non asincroni sono molto probabilmente al momento tornando void o qualche tipo, T direttamente.

Se si desidera "prova di futuro", l'applicazione una possibilità è quella di garantire che tutte le interfacce di ritorno Task o Task<T> e che per i vostri EF4/implementazioni EF5 si avvolgono i risultati in un'attività completata anche se sono eseguiti sincrono.

Task.FromResult è stato aggiunto in .NET 4.5, ma se non si dispone di esso è possibile scrivere il proprio abbastanza facilmente:

public static Task<T> FromResult<T>(T result) 
{ 
    var tcs = new TaskCompletionSource<T>(); 
    tcs.SetResult(result); 
    return tcs.Task; 
} 

è anche possibile scrivere un metodo CompletedTask che restituisce semplicemente un compito che ha già completato: (Si memorizza nella cache una singola attività per ragioni di efficienza.)

private static Task _completedTask; 
public static Task CompletedTask() 
{ 
    return _completedTask ?? initCompletedTask(); 
} 

private static Task initCompletedTask() 
{ 
    var tcs = new TaskCompletionSource<object>(); 
    tcs.SetResult(null); 
    _completedTask = tcs.Task; 
    return _completedTask; 
} 

Questi due metodi saranno semplificare il processo di avere tutti i metodi che ritornano un certo tipo di Task, anche se facendo questo renderà il vostro codice di un bi t messier fino a quando non sarai in grado di utilizzare C# 5.0 per essere in grado di ottenere il risultato da await.

+0

quindi l'unica soluzione è forzare tutte le classi a restituire un'attività? –

+1

Bene, non è la * sola * soluzione. È il migliore che potrei inventare. Se si dispone di C# 5.0 ma non di EF 6.0, è comunque possibile "attendere" i risultati della chiamata al metodo (anche se sono già stati completati), il che non lo rende troppo terribile. – Servy

+6

In una situazione come questa (in cui le operazioni sono naturalmente asincrone), è possibile rendere tutti i metodi restituiti 'Task' o creare metodi sincroni e asincroni affiancati. –

Problemi correlati