2016-08-30 62 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"); 
}