Написал я тут в коде одну конструкцию, которая пугает меня своей сложностью.
Это — кусок кода класса RestServiceClient, предназначенного для отправки запросов HTTP-серверам. Эта функция создаёт HttpClient и вызывает коллбэк, указанный в качестве параметра.
public async Task InvokeHttpCall(Func<HttpClient, Task<HttpResponseMessage>> callback)
{
using (var httpClient = new HttpClient())
{
HttpResponseMessage response = null;
var http = httpClient;
await this.retryPolicy.ExecuteAndCaptureAsync(
async () =>
await Task.Run(
async () => response = await callback.Invoke(http)));
}
}
Сделано это для того чтоб не повторять один и тот же код для обёртки каждого типа HTTP-запроса. Здесь я привожу упрощённый код, реально там ещё установка разных заголовков аутентификации, замеры времени обработки запроса и т.д. Результат выполнения запроса (переменная response) используется потом для возврата HttpStatusCode. Там несколько похожих методов, с десериализацией результата и без него, я привожу здесь простейший вариант. Используется этот метод так:
public async Task DeleteAsync(Uri uri)
{
await this.httpCallsInvoker.InvokeHttpCall((httpClient) => httpClient.DeleteAsync(uri));
}
Здесь идёт обёртка для DELETE-запоса, остальные типы запросов реализованы аналогично, но с дополнительными параметрами.
Вот эта строчка:
await this.retryPolicy.ExecuteAndCaptureAsync
Использует библиотеку Polly для применения разных политик обработки ошибок соединения (retry, circuit breaker, и т.д.). Оно тоже всё асинхронное и принимает коллбэки в качестве параметров.
Так вот.. это всё работает, но результат мне самому кажется излишне сложным. Особенно меня смущает вот эта лестница из async/await:
await this.retryPolicy.ExecuteAndCaptureAsync(
async () =>
await Task.Run(
async () => response = await callback.Invoke(http)));
Хочется всё это переписать к более понятному виду, потому как сейчас, кроме меня, этот код врятли кто-нибудь разберёт в моей команде. Коллеги, подскажите, как и с какой стороны к этому лучше подходить? Нет ли тут каких-то явных косяков, которые я не замечаю? Мне кажется, что что-то в этой последовательности async/await можно упростить, но я пока не смог.