2016-08-30 101 views
2

我已經創建了一個函數,該函數使用async/await返回一個對象。我想使該函數具有通用性,以便它可以返回我傳入的任何對象。除了返回的對象外,代碼是樣板文件。我希望能夠打電話給GetAsync並讓它返回正確的對象創建通用異步任務功能

public Patron getPatronById(string barcode) 
{ 
    string uri = "patrons/find?barcode=" + barcode; 
    Patron Patron = GetAsync(uri).Result; 
    return Patron; 
} 

private async Task<Patron> GetAsync(string uri) 
{ 
    var client = GetHttpClient(uri); 
    var content = await client.GetStringAsync(uri); 
    JavaScriptSerializer ser = new JavaScriptSerializer(); 
    Patron Patron = ser.Deserialize<Patron>(content); 
    return Patron; 
} 
+0

對象是根對象嗎? https://msdn.microsoft.com/zh-cn/library/system.object(v=vs.110).aspx –

+0

您不應該對'GetAsync'的結果使用'.Result'。如果你在UI線程上調用它,你會遇到死鎖。 –

+2

爲什麼getPatronById不是異步?它應該是異步的,並且你不使用'.Result'或'GetAsync'不應該是異步的,你應該使用'WebClient'而不是'HttpClient'並且使用同步方法。使用'.Result'可能會導致程序鎖定。 –

回答

4

一般方法怎麼樣?

private async Task<T> GetAsync<T>(string uri) 
{ 
    var client = GetHttpClient(uri); 
    var content = await client.GetStringAsync(uri); 
    var serializer = new JavaScriptSerializer(); 
    var t = serializer.Deserialize<T>(content); 
    return t; 
} 

通常情況下,你應該把這個方法到另一個類,並使其public,以便它可以在不同的類中的方法可以使用。

關於調用此方法的方式,你可以嘗試以下方法:

// I capitalized the first letter of the method, 
// since this is a very common convention in .NET 
public Patron GetPatronById(string barcode) 
{ 
    string uri = "patrons/find?barcode=" + barcode; 
    var Patron = GetAsync<Patron>(uri).Result; 
    return Patron; 
} 

:在上面的代碼中我認爲你沒有移動GetAsync到另一個類。如果你移動它,那麼你必須稍作改動。

更新

我不跟着你用你的音符的意思。我是否也需要讓GetPatronById成爲一項任務功能 - 就像Yuval在下面做的那樣?

我的意思是這樣的:

// The name of the class may be not the most suitable in this case. 
public class Repo 
{ 
    public static async Task<T> GetAsync<T>(string uri) 
    { 
     var client = GetHttpClient(uri); 
     var content = await client.GetStringAsync(uri); 
     var serializer = new JavaScriptSerializer(); 
     var t = serializer.Deserialize<T>(content); 
     return t; 
    } 
} 

public Patron GetPatronById(string barcode) 
{ 
    string uri = "patrons/find?barcode=" + barcode; 
    var Patron = Repo.GetAsync<Patron>(uri).Result; 
    return Patron; 
} 
+0

我不是按照你的意思所說的。我是否也需要讓GetPatronById成爲一項任務功能 - 就像Yuval在下面做的那樣? – jriggs

+0

@jriggs請看看更新。 TY – Christos

2

一般可以輕鬆完成:

private async Task<T> GetAsync(string uri) 
{ 
    var client = GetHttpClient(uri); 
    var content = await client.GetStringAsync(uri); 
    return JsonConvert.DeserializeObject<T>(content); 
} 

注意事項:

  1. JavaScriptSerializer已被否決的年齡,避免使用它。改爲嘗試使用Json.NET

  2. 此:

    Patron Patron = GetAsync(uri).Result; 
    

    是危險的,可能會導致潛在的死鎖,尤其是在網絡API。你需要去「異步一路」:

    public Task<Patron> GetPatronByIdAsync(string barcode) 
    { 
        string uri = $"patrons/find?barcode={barcode}"; 
        return GetAsync<Patron>(uri); 
    } 
    

而且只有你的最頂層調用需要awaitTask。可能有些控制器動作:

public async Task SomeAction() 
{ 
    await GetPatronByIdAsync("hello"); 
}