Search code examples
c#httphttp-get

Is there an elegant way to combine multiple methods that have the same signature and the same method call?


I am writing a class that is sending quite a few GET requests and I am looking for the right way to consolidate them. I have extracted the common logic into a method called GetRequest. Here is what it looks like at the moment:

private async Task<HttpResponseMessage> GetRequest(string message)
{
    _uriBuilder.Path = _commonApiPath + message;
    return await _client.GetAsync(_uriBuilder.Uri.AbsoluteUri);
}

public async Task<HttpResponseMessage> GetA()
{
    return await GetRequest("sys/a");
}

public async Task<HttpResponseMessage> GetB()
{
    return await GetRequest("sys/b");
}

public async Task<HttpResponseMessage> GetC()
{
    return await GetRequest("sys/c");
}

public async Task<HttpResponseMessage> GetX()
{
    return await GetRequest("sys/x");
}

public async Task<HttpResponseMessage> GetY()
{
    return await GetRequest("sys/y");
}

This approach is straightforward and it works, but is there some language feature that I am able to use in order to combine those calls? The only real difference is the string that is passed as the message. I don't want the consumer of this class to have to include the message string since it could be potentially written incorrectly.

I was considering trying to use Func<>/Action<> or lambdas to consolidate, but each one seems to have a limitation which makes me think it's not the correct approach.


Solution

  • If this is just to constrain the allowed values, expose an enum to the callers, then use a dictionary behind the scenes:

    public enum RequestType {
      A,
      B,
      ...
    }
    
    private static readonly Dictionary<RequestType, string> RequestPaths = new Dictionary<RequestType, string> {
      { RequestType.A, "sys/a"},
      { RequestType.B, "sys/b"}
    };
    
    public async Task<HttpResponseMessage> GetRequest(RequestType request)
    {
        _uriBuilder.Path = _commonApiPath + RequestPaths[request];
        return await _client.GetAsync(_uriBuilder.Uri.AbsoluteUri);
    }
    

    This will throw at runtime if they cast an unknown value to RequestType but it usually suffices in keeping the honest callers honest.