2012-11-26 99 views
47

我有一個應用程序。此應用程序使用一個接口來訪問數據庫。這個接口可以通過很多類來實現。例如,使用EF 4.4,但其他類可以使用效率更高的EF5。在未來,也許我會使用EF6,因爲它使用異步方法。在這個例子中,所有的方法都使用EF,但也可以使用其他方法。接口和異步方法

該應用程序編碼一次,使用接口,並根據配置文件,使用一個實現或其他,所以我只需要修改代碼在一個地方,構造函數,以添加新的選項實例化分配給接口的類。

目前所有的類的方法都不是async,但將來如果我使用EF6我想使用異步方法,所以我不知道是否有可能使用EF6的類並實現該接口可以使用async的方法。

對於EF6的異步方法,我會使用async/awiat模式,所以在我的類的方法中我需要使用async屬性。當我調用EF6的異步方法時,這使我可以使用await關鍵字。

但是這個類可以實現第一次使用同步方法的接口嗎?

有沒有一些方法可以在主應用程序中使用許多實現而不需要修改代碼?一些實現將使用異步方法,而其他實現將同步。

+2

請記住'async'不是簽名的一部分;異步和非異步方法都可以實現相同的接口方法。 – Servy

+1

這不是可以等待的方法,而是(返回)類型。 – rism

+1

對一個簡單問題的解釋太多。恕我直言。 – Mahmoodvcs

回答

55

async不是簽名的一部分,所以您實際上不需要關心實現接口的方法是否爲async,您只需要關心屬性的類型,即返回類型,方法的名稱和可訪問性。

真正不同的是,你的async方法需要返回一個TaskTask<T>,而非異步方法最有可能返回當前void或某些類型的,T直接。

如果您想「面向未來」,您的應用程序的一個選擇是確保您的所有接口返回TaskTask<T>,並且對於EF4/EF5實現,您將結果包裝爲完成的任務,即使它們已執行同步。

Task.FromResult加入在.NET 4.5,但如果你沒有它,你可以寫你自己很輕鬆地:

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

你也可以寫一個CompletedTask方法簡單地返回早已任務完成:(它緩存出於效率的考慮單個任務。)

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; 
} 

這兩種方法將簡化其所有的方法返回某種類型的Task的過程中,雖然這樣做會讓你的代碼雙向t messier,直到您能夠使用C#5.0才能夠得到結果await

+0

所以唯一的解決辦法是迫使所有的類返回一個任務? –

+1

好吧,它不是* only *解決方案。這是我能想出的最好的一個。如果你有C#5.0,但不是EF 6.0,那麼你仍然可以「等待」方法調用的結果(即使它們已經完成),這將使它不會太糟糕。 – Servy

+6

在這種情況下(您的操作自然是異步的),您可以使所有方法都返回Task,或者同時創建同步和異步方法。 –