Этот тип T может быть любым из моих конкретный класс, который хранит возвращаемое целое число из базы данных.
Я заставил его работать, но в настоящее время он принимает только определенный IEnumerable. Как сделать так, чтобы я мог передавать любой IEnumerableлюбому из моих классов?
А также как обрабатывать результат в OnRetry? Поскольку он должен иметь доступ к параметру IEnumerable, который в каждом классе называется по-разному.
Код: Выделить всё
public static async ValueTask KeepTrying(Func func, int expectedInteger) where TResult : IEnumerable
{
var pipeline = new ResiliencePipelineBuilder()
.AddRetry( new RetryStrategyOptions(){
ShouldHandle = new PredicateBuilder().Handle()
.HandleResult(result => result.First().MyInteger != expectedInteger),
MaxRetryAttempts = 3,
Delay = TimeSpan.FromSeconds(2)
})
.Build();
return await pipeline.ExecuteAsync(token => new ValueTask(func()));
}
Код: Выделить всё
var result = await KeepTrying(() => DB.MyFunction(), expectedInteger: 100);
- Без надлежащего контекст, я не могу сказать, когда генерируется NotFoundException. Но по обоснованному предположению, он выдается тогда, когда в противном случае функция базы данных вернула бы ноль. Но пустая и пустая коллекция — это не одно и то же.
Код: Выделить всё
if (result.Count == 0)
throw new NotFoundException("Some error");
return result;
- Я не уверен на 100 %, что под этим подразумевается. Не могли бы вы перефразировать это? (Что касается обработки других типов)
Иногда мне хочется вернуть из базы данных не только целое число, но и логическое значение или строку.
И что я сделал я добавил новое свойство в IMyInteger (фактически переименовал его в IReturnedValueFromDatabase, поскольку это не только int).
Код: Выделить всё
public interface IReturnedValueFromDatabase
{
public int ReturnedInteger { get; set; } // was MyInteger
public bool ReturnedBool { get; set; }
public string ReturnedString { get; set; }
}
Добавил новые параметры, допускающие значение NULL, поэтому в HandleResult я знаю, какой из них следует проверить:
Код: Выделить всё
public static async ValueTask KeepTrying(..., int? expectedNumber = null, bool? expectedBool = null, bool handleResult = true) where TResult : IReturnedValueFromDb
{
// skipping to .HandleResult()
.HandleResult(result => {
if (!handleResult)
// Sometimes I want to only handle Exception and not to check result, so added this check, but maybe there is better way?
return false;
if (expectedNumber != null)
// I am passing int so lets check int
return result.First().ReturnedInteger != expectedNumber;
if (expectedBool != null)
// I am passing bool so lets check bool
return result.First().ReturnedBool != expectedBool;
// all else fails, throw exception
throw new InvalidOperationException("Unable to determine result");
})
}
- Что касается исключения, выдаваемого функцией KeepTrying()
- использование Execute вместо ExecuteAsync
Обновление 3
Вы можете избежать создания исключения. Вы можете просто использовать .Any внутри HandleResult
Извините, это могло сбить с толку из-за того же результата именования — это выдержка из моей базы данных функция, в которой я выдаю исключение, если result.Count == 0, или возвращаю результат в противном случае.
Я создал dotnetfiddle с текущей версией
Поэтому я теперь тоже запутываюсь, не уверен, что вы имели в виду исключение внутри .HandleResult() - могу ли я удалить флаг bool? handleResult = true из KeepTrying() и внутри HandleResult вместо этого выполните:
Код: Выделить всё
if (!result.Any()) // In case I don't want to check result?
return false;
с помощью селектора свойств
Конечно, я могу попробовать, по крайней мере сейчас это работает. Я буду продолжать корректировать и посмотреть.
Основываясь на этом описании, я предполагаю, что вы не ожидаете метода KeepTrying внутри своего теста. дождитесь его, и оно должно выдать исключение.
На самом деле я использую await (см. Тестовый класс в скрипте) - если Я удаляю await, получаю сообщение об ошибке Невозможно разрешить символ 'First' из следующей строки Assert.That(myNumber.First().ReturnedInteger), что странно, потому что я изменил KeepTrying() для синхронизации, но это может быть потому, что тест является асинхронным?
Странное поведение заключается в том, что, когда результат неверен, он правильно повторяет попытку, но не генерирует исключение, вот почему Я также использую Assert.That в следующей строке - если KeepTrying выдаст исключение, я мог бы удалить его.
Я получал бы исключение из HandleResult() только тогда, когда я передал бы его. аргументов имеет значение null, например ожидаемый номер = null. Есть некоторые странные варианты поведения, но я могу избежать их, если буду использовать функцию только так, как ожидалось - возможно, еще один вопрос:
Для функций БД, когда я не проверяю результаты и просто хочу убедиться, что что-то вернулось (т.е. NotFoundException не было создано), является ли мой флаг handleResult достаточно хорошим решением, чтобы игнорировать проверяемое решение?
В любом случае, если на данный момент это слишком запутанно, не беспокойтесь, вы уже мне помогло и заставило функцию работать! Спасибо большое за это.
Подробнее здесь: https://stackoverflow.com/questions/781 ... th-generic