创建通用异步任务函数
Create generic async task function
我使用 async
/await
创建了一个 return 对象的函数。我想使该函数通用,以便它可以 return 我传入的任何对象。代码是样板,除了被 returned 的对象。我希望能够调用 GetAsync 并使其 return 成为正确的对象
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;
}
泛型方法怎么样?
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;
}
一般情况下,您应该将此方法放入另一个class中,并使其成为public
,以便不同class中的方法可以使用它。
关于您调用此方法的方式,您可以尝试以下方法:
// 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
移动到另一个 class。如果你移动它,那你就得稍微改变一下。
更新
I'm not following what you mean by your note. Do I need to make GetPatronById a task function as well - like Yuval has done below?
我的意思是这样的:
// 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;
}
通用可以很容易地完成:
private async Task<T> GetAsync(string uri)
{
var client = GetHttpClient(uri);
var content = await client.GetStringAsync(uri);
return JsonConvert.DeserializeObject<T>(content);
}
注意事项:
JavaScriptSerializer 已被弃用多年,请避免使用它。请尝试 Json.NET。
这个:
Patron Patron = GetAsync(uri).Result;
很危险,可能会导致潜在的死锁,尤其是在 Web API 中。你需要去 "async all the way":
public Task<Patron> GetPatronByIdAsync(string barcode)
{
string uri = $"patrons/find?barcode={barcode}";
return GetAsync<Patron>(uri);
}
并且只有最顶层的调用者才需要 await
Task
。可能有一些控制器动作:
public async Task SomeAction()
{
await GetPatronByIdAsync("hello");
}
我使用 async
/await
创建了一个 return 对象的函数。我想使该函数通用,以便它可以 return 我传入的任何对象。代码是样板,除了被 returned 的对象。我希望能够调用 GetAsync 并使其 return 成为正确的对象
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;
}
泛型方法怎么样?
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;
}
一般情况下,您应该将此方法放入另一个class中,并使其成为public
,以便不同class中的方法可以使用它。
关于您调用此方法的方式,您可以尝试以下方法:
// 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
移动到另一个 class。如果你移动它,那你就得稍微改变一下。
更新
I'm not following what you mean by your note. Do I need to make GetPatronById a task function as well - like Yuval has done below?
我的意思是这样的:
// 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;
}
通用可以很容易地完成:
private async Task<T> GetAsync(string uri)
{
var client = GetHttpClient(uri);
var content = await client.GetStringAsync(uri);
return JsonConvert.DeserializeObject<T>(content);
}
注意事项:
JavaScriptSerializer 已被弃用多年,请避免使用它。请尝试 Json.NET。
这个:
Patron Patron = GetAsync(uri).Result;
很危险,可能会导致潜在的死锁,尤其是在 Web API 中。你需要去 "async all the way":
public Task<Patron> GetPatronByIdAsync(string barcode) { string uri = $"patrons/find?barcode={barcode}"; return GetAsync<Patron>(uri); }
并且只有最顶层的调用者才需要 await
Task
。可能有一些控制器动作:
public async Task SomeAction()
{
await GetPatronByIdAsync("hello");
}