我可以访问 C#/.NET 中传递给 Func<> 的方法执行参数吗?

问题描述 投票:0回答:1

我正在尝试创建一种方法,可以迭代调用实现分页的 RESTful API 端点,直到找到特定的 JSON 对象。我将在下面概述预期的模式,然后更详细地描述该问题。

// ApiClient.cs
// Example methods that call REST API

public async Task<ICollection<PetsApiResonse>> GetPets(string searchQuery, int skip = 0, int take = 20, bool includeAdopted = false)
{
  // Logic that makes HTTP request to something like 'GET {baseUri}/pets'
}

public async Task<ICollection<EmployeesApiResonse>> GetEmployees(string searchQuery, int skip = 0, int take = 20)
{
  // Logic that makes HTTP request to something like 'GET {baseUri}/employees'
}
// RequestHandler.cs
// Example method expecting Func<> that doesn't work yet

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
  {
    // This is where I want to alter the 'skip' parameter's value so that each iteration observes a different page from the 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)));
}
// Example code that might be in the body of an NUnit test case

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);

您可能已经猜到,目标是测试记录是否存在且可搜索。问题是搜索并不总是在结果的第一页中返回所需的记录,这导致测试不稳定。明显的途径是简单地在需要此功能的每个测试用例中编写循环,但我希望有一种方法可以集中逻辑。

  1. 反射可用于访问传递给 Func<> 的方法吗?在上面的示例中,只需修改“skip”参数即可解决此问题,但据我所知,我只能访问 Func<> 的参数;不是 its 参数之一的参数。
  2. 如果第一个问题的答案是否定的,是否有更好的方法来集中我没有考虑过的逻辑?附加说明如下:
    • 发出 API 请求的方法是使用 OpenApi 规范生成的。我相信我可以扩展它们,但我没有直接访问权限来修改它们。
    • 我可以保证参数命名始终相同;即
      skip
      表示页面开始,
      take
      表示页面大小。
c# .net reflection paging func
1个回答
0
投票

一种方法是在回调中简单地包含分页参数

skip
take

public delegate Task<ICollection<T>> GetResponse<T>(int skip, int take);

public static async Task<T> PagedLookupAsync<T>(
    GetResponse<T> getResponse,
    string propertyToCompare,
    object valueToCompare,
    int maxIterations = 10,
    take = 20
)
{
  Type type = typeof(T);
  PropertyInfo propertyInfo = type.GetProperty(propertyToCompare);
  ICollection<T> response;
  int skip = 0;
  do
  {
    // This is where I want to alter the 'skip' parameter's value so that each iteration observes a different page from the API
    response = await getResponse(skip, take);
    skip += take;
    maxIterations--;
  }
  while (maxIterations >= 0 && !response.Any(o => valueToCompare.Equals(propertyInfo.GetValue(o))));

  return response.FirstOrDefault(o => valueToCompare.Equals(propertyInfo.GetValue(o)));
}

然后这样称呼它:

var response = RequestHandler.PagedLookupAsync((skip, take) => ApiClient.GetPetsAsync("sparky", skip, take), nameof(PetsApiResonse.Id), petIdToFind, take: 50);
© www.soinside.com 2019 - 2024. All rights reserved.