C#/.NET中能否访问Func<>传入的方法参数?分页API查询方案
分页API迭代查找指定对象的实现问题与解决方案
我需要实现一个方法,能够迭代调用支持分页的RESTful API接口,直到找到指定的JSON对象。以下是相关代码示例及遇到的问题:
现有API客户端代码(ApiClient.cs)
// 调用REST API的示例方法 public async Task<ICollection<PetsApiResonse>> GetPets(string searchQuery, int skip = 0, int take = 20, bool includeAdopted = false) { // 发起HTTP请求的逻辑,例如 'GET {baseUri}/pets' } public async Task<ICollection<EmployeesApiResonse>> GetEmployees(string searchQuery, int skip = 0, int take = 20) { // 发起HTTP请求的逻辑,例如 'GET {baseUri}/employees' }
当前无法正常工作的分页查找方法(RequestHandler.cs)
// 目前无法正常工作的、接收Func<>的示例方法 public static async Task<T> PagedLookupAsync<T>(Func<Task<PetShopApiResponse<ICollection<T>>>> getResponse, string propertyToCompare, object valueToCompare, int maxIterations = 10) { Type type = typeof(T); PropertyInfo propertyInfo = type.GetProperty(propertyToCompare); ICollection<T> response; do { // 此处需要修改'skip'参数值,以获取API的不同分页结果 response = await getResponse(); maxIterations--; } while (maxIterations >= 0 && !response.Any(o => valueToCompare.Equals(propertyInfo.GetValue(o)))); return response.FirstOrDefault(o => valueToCompare.Equals(propertyInfo.GetValue(o))); }
NUnit测试用例示例
var petIdToFind = "123"; var response = RequestHandler.PagedLookupAsync(ApiClient.GetPetsAsync("sparky", take: 50), nameof(PetsApiResonse.Id), petIdToFind); response.Result.Should().NotBeNull(); response.Result.Id.Should().BeEquivalentTo(petIdToFind);
我的目标是测试记录是否存在且可被搜索,但搜索结果不一定在第一页,导致测试不稳定。我希望集中化该逻辑而非在每个测试用例中编写循环,因此有两个问题:
- 能否使用反射访问传入Func<>的方法的参数?我需要修改
skip参数,但目前似乎只能访问Func<>自身的参数,无法访问其内部方法的参数。 - 如果上述方案不可行,有没有更好的集中化逻辑实现方式?
补充说明:
- API请求方法由OpenApi规范生成,我无法直接修改,但可以扩展。
- 参数命名固定:用
skip表示分页起始位置,take表示分页大小。
更新:最终解决方案
基于建议调整后,移除了反射,实现如下:
修改后的分页查找方法(RequestHandler.cs)
public static async Task<T> PagedLookupAsync<T>( Func<(int SkipState, int TakeState), Task<PetShopApiResponse<ICollection<T>>>> getResponse, Func<T, bool> lookupFunction, int maxIterations = 10) { int skip = 0; int take = 20; ICollection<T> response; bool isFound = false; do { response = await getResponse((skip, take)); isFound = response.Any(o => lookupFunction(o)); skip += take; maxIterations--; } while (maxIterations >= 0 && !isFound); return response.FirstOrDefault(o => lookupFunction(o)); }
调用示例
var response = RequestHandler.PagedLookupAsync((s, t) => ApiClient.GetPetsAsync("sparky", skip: s, take: t), (lookup) => lookup.Id == petIdToFind);
内容的提问来源于stack exchange,提问作者officeSpacePirate
相关产品推荐
相关产品推荐

