Tenho um projeto em C# que chama algumas APIs. Essas APIs são bem diferentes, e a resposta é diferente para quase todas as chamadas.
Eu escrevi um serviço de cliente genérico:
public class HttpClientHelper
{
private readonly IHttpClientFactory _httpClientFactory;
public HttpClientHelper(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<TResponse> MakeHttpRequestAsync<TRequest, TResponse>(
string clientName,
string url,
HttpMethod httpMethod,
TRequest requestBody = default,
bool handleErrors = false)
{
// Get a named HttpClient instance
var client = _httpClientFactory.CreateClient(clientName);
var request = new HttpRequestMessage
{
Method = httpMethod,
RequestUri = new Uri(url)
};
// Serialize the request body to JSON (if it exists)
if (requestBody != null)
{
var json = JsonSerializer.Serialize(requestBody);
request.Content = new StringContent(json,
Encoding.UTF8, "application/json");
}
// Send the HTTP request
var response = await client.SendAsync(request);
// Handle errors if specified
if (handleErrors && !response.IsSuccessStatusCode)
{
throw new HttpRequestException($"Failed: {response.StatusCode}");
}
// Deserialize the response JSON into the specified type
var responseJson = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<TResponse>(responseJson,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
}
Agora, quero ter um retorno mais estruturado desta função. Por exemplo, gosto de usar para todas as respostas algo como
public class ApiResponse<T> where T : class
{
public T? Data { get; set; }
public string? ErrorMessage { get; set; }
public int HttpErrorCode { get; set; } = 200;
public bool Success { get; set; } = false;
}
Não preciso lidar com os erros no código principal, e tudo é gerenciado perfeitamente no cliente da API genérica. Se houver um erro na chamada, no ApiResponse
, posso definir Success
como false
.
Se eu escrever este código:
public async Task<ApiResponse<TResponse>>
MakeHttpRequestAsync<TRequest, ApiResponse<TResponse>>(
...
)
{
// code
}
Recebo um erro
O tipo ou nome do namespace
TResponse
não pôde ser encontrado (está faltando uma diretiva using ou uma referência de assembly?)
O que não quero é derivar uma classe do ApiResponse
porque uso os modelos em outras partes do código.
Existe uma maneira de implementar isso?