У меня простой вопрос об асинхронных операциях. У меня есть класс композиции, используемый для инкапсуляции экземпляра HttpClient
. Этот класс имеет абстрактный базовый класс, чтобы избежать избыточности кода.
Моя проблема возникает, когда я пытаюсь переопределить базовый метод, выполняющий часть работы в производном методе, который выполняет дополнительные операции.
Чтобы было понятнее, у меня есть:
Базовый метод:
/// <summary>
/// Execute a Typed GET Request and returning <typeparamref name = "TResponse"/> result.
/// </summary>
/// <typeparam name = "TResponse">Response specified type.</typeparam>
/// <param name = "route">Uri string to request.</param>
/// <param name = "path">Path parameters to provide to the <paramref name = "route"/>.</param>
/// <param name = "query">Query parameters to provide to the <paramref name = "route"/>.</param>
/// <returns>The <see cref = "Task"/> that represents the asynchronous operation containing <typeparamref name = "TResponse"/> response object.</returns>
/// <exception cref = "HttpRequestException">Raised if the Http request failed.</exception>
public virtual async Task<TResponse?> GetAsync<TResponse>(string route, Dictionary<string, string>? path = null, Dictionary<string, string>? query = null)
{
using HttpResponseMessage response = await _httpClient.GetAsync(BuildUri(route, path, query));
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<TResponse>(new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
}
Производный метод:
/// <inheritdoc/>
public override async Task<TResponse?> GetAsync<TResponse>(string route, Dictionary<string, string>? path = null, Dictionary<string, string>? query = null)
{
var token = await GetBearerToken();
base._httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return base.GetAsync<TResponse>(route, path, query);
}
Таким образом, метод базового класса несет ответственность за http-запрос, а производный метод добавляет дополнительные предварительные обработки для настройки httpClient
с необходимыми заголовками и другими.
Ошибка возникает при возврате, я пробовал оба:
return base.GetAsync<TResponse>(route, path, query);
с ошибкой: Невозможно преобразовать тип Task<TResponse?>
в TResponse?
и
return await base.GetAsync<TResponse>(route, path, query);
с ошибкой: Невозможно преобразовать тип TResponse
в TResponse
?
Я не понимаю, почему, когда я жду результата, выполняется приведение Nullable<TResponse>
к TResponse
в производном методе, зная тот факт, что базовый метод возвращает Task<TResponse?>
.
Заранее спасибо.
Редактировать:
@Selvin и @Enigmativity получили здесь правильный ответ, добавив ограничение класса к общему TResponse
типу в определении метода как базового, так и производного метода, чтобы решить проблему, спасибо за вашу помощь!
или просто используйте Task<TResponse> GetAsync<TResponse>()
и пусть пользователь решит использовать GetAsync<Type>()
или GetAsync<Type?>()
Ваш метод должен ограничить TResponse
значением class
:
public virtual async Task<TResponse?> GetAsync<TResponse>(
string route,
Dictionary<string, string>? path = null,
Dictionary<string, string>? query = null)
where TResponse : class
Возможно, вам нужно добавить ограничение к общему параметру, которое заставит аргумент быть ссылочным типом.