一个抽象的例子。我有一个具有以下界面的客户端:
public interface IUserClient
{
Task<IUser> GetUserByIdAsync(int id);
Task<IUser> FindUserByFirstNameAndLastNameAsync(string firstName, string lastName);
Task<IUser> CreateUserAsync(string firstName, string lastName, string phone);
}
public interface IUser
{
int Id { get; }
string FirstName { get; set; }
string LastName { get; set; }
string Phone { get; set; }
}
我需要围绕这个客户端编写一个包装器,如果客户端方法抛出某个Exception. 到目前为止,我已经实现了这样的东西:
public class UserClientWrapper : IUserClient
{
private readonly IUserClient _userClient;
public UserClientWrapper(IUserClient userClient)
{
_userClient = userClient;
}
public async Task<IUser> GetUserByIdAsync(int id)
{
try
{
return await _userClient.GetUserByIdAsync(id);
}
catch (UnauthorizedAccessException)
{
// Пытаемся перелогиниться
try
{
return await _userClient.GetUserByIdAsync(id);
}
catch (UnauthorizedAccessException)
{
// Пишем в лог, что что-то не так, и пробрасываем выше этот exception
throw;
}
}
}
public async Task<IUser> FindUserByFirstNameAndLastNameAsync(string firstName, string lastName)
{
try
{
return await _userClient.FindUserByFirstNameAndLastNameAsync(firstName, lastName);
}
catch (UnauthorizedAccessException)
{
// Пытаемся перелогиниться
try
{
return await _userClient.FindUserByFirstNameAndLastNameAsync(firstName, lastName);
}
catch (UnauthorizedAccessException)
{
// Пишем в лог, что что-то не так, и пробрасываем выше этот exception
throw;
}
}
}
public async Task<IUser> CreateUserAsync(string firstName, string lastName, string phone)
{
// и тут тоже самое
}
}
但令我困惑的是,我不得不在每个方法中复制代码try-catch。我想把这个逻辑放在一个单独的方法中,但我不知道这是否可能。因此,问题来了:在这种情况下如何避免代码重复?
PS重要!客户端方法不同,具有不同的签名和返回类型,但它们都是异步的。
在英文 StackOverflow 上找到了答案。将异常处理逻辑移至我将委托传递给的方法
Func<Task<T>>用户@aepot在已删除的回复中建议改进
WrapClientCallAsync使用循环而不是嵌套的 try-catch 的方法。如果有很多尝试,这可能很有用,这可能会使很多嵌套混乱。就我而言,有 3 个。我使用 OAuth2 (Bearer) 授权,其中有访问+刷新令牌。这样:基于以上,我们得到如下代码: