Reputation: 1324
I have created a function that returns an object using async
/await
. I would like to make the function generic so that it can return whatever object that I pass in. The code is boilerplate except for the objects being returned. I would like to be able to call GetAsync and have it return the correct object
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;
}
Upvotes: 2
Views: 6004
Reputation: 53958
What about a generic method?
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;
}
Normally, you should place this method into another class and make it public
, in order it can be used by methods in different classes.
Regarding the way you call this method, you could try the following:
// 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;
}
Note: In the above snippet I assumed that you haven't moved the GetAsync
into another class. If you move it, then you have to make a slight change.
Update
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?
I mean something like this:
// 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;
}
Upvotes: 6
Reputation: 149538
Generic can be easily done with:
private async Task<T> GetAsync(string uri)
{
var client = GetHttpClient(uri);
var content = await client.GetStringAsync(uri);
return JsonConvert.DeserializeObject<T>(content);
}
Things to note:
JavaScriptSerializer has been deprecated for ages, avoid using it. Try out Json.NET instead.
This:
Patron Patron = GetAsync(uri).Result;
is dangerous and can cause potential deadlocks, especially in Web API. You need to go "async all the way":
public Task<Patron> GetPatronByIdAsync(string barcode)
{
string uri = $"patrons/find?barcode={barcode}";
return GetAsync<Patron>(uri);
}
And only your top most level invoker need await
on the Task
. Possibly some controller action:
public async Task SomeAction()
{
await GetPatronByIdAsync("hello");
}
Upvotes: 2