Search code examples
c#genericsasp.net-web-apisystem.net.httpwebrequest

Create generic async task function


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

Solution

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