Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic method with HttpMethod as a parameter

Tags:

c#

I am trying to create a method that will invoke other methods based on the HttpMethod. My method looks like this:

public async Task<string> CreateAsync<T>(HttpClient client, string url, HttpMethod method, T data, Dictionary<string, string> parameters = null)
{
    switch(method)
    {
        case HttpMethod.Post:
            return await PostAsync(client, url, data);
        case HttpMethod.Put:
            return await PutAsync(client, url, data);
        case HttpMethod.Delete:
            return await DeleteAsync(client, url, parameters);
        default:
            return await GetAsync(client, url, parameters);
    }
}

The problem is, the switch is moaning about this:

A constant value is expected

And each case is underlined in red. Does anyone know what I am doing wrong?

like image 469
r3plica Avatar asked Jun 22 '17 15:06

r3plica


3 Answers

As it was already pointed out the problem is that the HttpMethod Delete, Post, ...etc. properties are instances and not constants or enums. It was also pointed out that they are equatable.

The only thing I would like to add is that if this is C# 7 you can use pattern matching instead of the if..else if....else if... chain:

public async Task<string> CreateAsync<T>(HttpClient client, string url, HttpMethod method, T data, Dictionary<string, string> parameters = null)
{
    switch (method)
    {
        case HttpMethod m when m == HttpMethod.Post:
            return await PostAsync(client, url, data);
        case HttpMethod m when m == HttpMethod.Put:
            return await PutAsync(client, url, data);
        case HttpMethod m when m == HttpMethod.Delete:
            return await DeleteAsync(client, url, parameters);
        default:
            return await GetAsync(client, url, parameters);
    }
}
like image 175
gregkalapos Avatar answered Oct 06 '22 00:10

gregkalapos


You could not do that like dasblinkenlight and Nkosi said. The easiest work around is to use HttpMethod.Method and hard-coded string for case statement.

public async Task<string> CreateAsync<T>(HttpClient client, string url, HttpMethod method, T data, Dictionary<string, string> parameters = null)
{
    switch (method.Method)
    {
        case "POST":
            return await PostAsync(client, url, data);
        case "PUT":
            return await PutAsync(client, url, data);
        case "DELETE":
            return await DeleteAsync(client, url, parameters);
        default:
            return await GetAsync(client, url, parameters);
    }
}
like image 32
Win Avatar answered Oct 06 '22 01:10

Win


Since static properties of HttpMethod, such as HttpMethod.Put and HttpMethod.Post, are instances of HttpMethod class, you cannot use them as case expressions in a switch statement, as if they were members of an enum.

These objects are equatable, though, so you can use them in a chain of if-then-else, or in a Dictionary<HttpMethod,SomeDelegate> where SomeDelegate is an action type representing the task that you would like to run:

if (method == HttpMethod.Post) {
    return await PostAsync(client, url, data);
} else if (method == HttpMethod.Put) {
    return await PutAsync(client, url, data);
} else if (method == HttpMethod.Delete) {
    return await DeleteAsync(client, url, parameters);
} else {
    return await GetAsync(client, url, parameters);
}
like image 34
Sergey Kalinichenko Avatar answered Oct 06 '22 01:10

Sergey Kalinichenko