简体   繁体   中英

Creating Reusable Method using generics

I am not sure about the title of the question, but here it is:-

I have my code as :-

HttpClient client = new HttpClient();// Create a HttpClient
client.BaseAddress = new Uri("http://localhost:8081/api/Animals");//Set the Base Address

//eg:- methodToInvoke='GetAmimals'
//e.g:- input='Animal' class
HttpResponseMessage response = client.GetAsync('GetAllAnimals').Result;  // Blocking call!

if (response.IsSuccessStatusCode)
{
    XmlSerializer serializer = new XmlSerializer(typeof(Animal));//Animal is my Class (e.g)
    string data = response.Content.ReadAsStringAsync().Result;
    using (MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)))
    {
        var _response = (Animal)serializer.Deserialize(ms);
        return _response;
    }

}

This works perfectly well, now if I need to do the same for another class say Dog or Cat

What I am doing is:-

HttpClient client = new HttpClient();// Create a HttpClient
    client.BaseAddress = new Uri("http://localhost:8081/api/Animals");//Set the Base Address

    //eg:- methodToInvoke='GetAmimals'
    //e.g:- input='Animal' class
    HttpResponseMessage response = client.GetAsync('GetAllDogs').Result;  // Blocking call!

    if (response.IsSuccessStatusCode)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Dog));//Animal is my Class (e.g)
        string data = response.Content.ReadAsStringAsync().Result;
        using (MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)))
        {
            var _response = (Dog)serializer.Deserialize(ms);
            return _response;
        }

    }

Now, I want it to change it to a Generic class , something like this below:-

private T GetAPIData(T input,string parameters, string methodToInvoke)
        {
            try
            {

                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri("http://localhost:8081/api/Animals");

                //eg:- methodToInvoke='GetAmimals'
                //e.g:- input='Animal' class
                HttpResponseMessage response = client.GetAsync(methodToInvoke).Result;  // Blocking call!

                if (response.IsSuccessStatusCode)
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(input));
                    string data = response.Content.ReadAsStringAsync().Result;
                    using (MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)))
                    {
                        var _response = (input)serializer.Deserialize(ms);
                        return _response;
                    }

                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return (T)input;
        }

But, I am not able to do it. Puzzled even how will I call this method?

var testData = GetAPIData(new Aminal(),null,'GetAmimals');

Will this work... This is the first time I am working with generics.

The definition of your method is missing the generic type parameter. Additionally, you don't need the first parameter ( input ), because you don't use it. The signature of your method should look like this:

private T GetAPIData<T>(string parameters, string methodToInvoke)

Usage would be like this:

var testData = GetAPIData<Animal>(null, "GetAllAnimals");

The implementation would use T everywhere the original method used Dog or Animal .

Furthermore:
Your catch block doesn't add any value. In fact, it removes it by throwing the base exception class that you should never throw and by discarding the original stack trace. Just remove it.

The final method would look like this:

private T GetAPIData<T>(string parameters, string methodToInvoke)
{
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:8081/api/Animals");

    //eg:- methodToInvoke='GetAmimals'
    //e.g:- input='Animal' class
    HttpResponseMessage response = client.GetAsync(methodToInvoke).Result;

    if (!response.IsSuccessStatusCode)
        throw new InvalidOperationException("Request was not successful");

    XmlSerializer serializer = new XmlSerializer(typeof(T));
    string data = response.Content.ReadAsStringAsync().Result;
    using (MemoryStream ms = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data)))
    {
        return (T)serializer.Deserialize(ms);
    }
}

You missed the generic definition

private T GetAPIData<T>(string parameters, string methodToInvoke)

and

var testData = GetAPIData<Animal>(null,'GetAmimals');

your parameter input is useless so you can remove it.

You can also add a type costraint :

private T GetAPIData<T>(string parameters, string methodToInvoke) where T:IAnimal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM