public static class TupleExtensions {
public static async Task<T> TryAwaitOrLogAsync<T>(
this (Task<T> task, ILogger logger) t,
T defaultValue = default) {
try {
var result = await t.task;
return result == default ? defaultValue : result;
}
catch (Exception ex) {
if (t.logger != null) {
t.logger.LogError(ex, ex.Message);
}
return defaultValue;
}
}
}
public class InputOutputBoundRepository<T> : IIOBoundRepository<T> where T : IRecord {
private readonly IDataAccessLayer _iDal;
private readonly ILogger<InputOutputBoundRepository<IRecord>> _logger;
public InputOutputBoundRepository(
IDataAccessLayer iDal,
ILogger<InputOutputBoundRepository<IRecord>> logger) {
_iDal = iDal ?? throw new ArgumentNullException(nameof(iDal));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
// Avoid the `async` and `await` keyword here
// Single line expression
// Generic
// Task based async
// Encapsulates try / catch
// Handles logging
// Allows for default override
public Task<IEnumerable<T>> GetAsync(Func<T, bool> predicate)
=> (task: _iDal.GetRecordsWhereAsync(predicate), _logger).TryAwaitOrLogAsync(Enumerable.Empty<T>());
}