C# 使用Microsoft Graph客户端库减少代码重复

C# 使用Microsoft Graph客户端库减少代码重复,c#,microsoft-graph-api,C#,Microsoft Graph Api,我正在开发一个类,该类负责使用Microsoft Graph客户端库与O365通信。在每个方法中,对NextPageRequest.GetAsync的调用都在不同的类型上,该类型也会返回不同的类型,但在其他情况下,分页逻辑是相同的: 公共异步任务FindAllUsers { var usersFound=新列表; var usersPage=await-GraphClient.Users.Request.GetAsync; usersFound.AddRangeusersPage; 而users

我正在开发一个类,该类负责使用Microsoft Graph客户端库与O365通信。在每个方法中,对NextPageRequest.GetAsync的调用都在不同的类型上,该类型也会返回不同的类型,但在其他情况下,分页逻辑是相同的:

公共异步任务FindAllUsers { var usersFound=新列表; var usersPage=await-GraphClient.Users.Request.GetAsync; usersFound.AddRangeusersPage; 而usersPage.NextPageRequest!=null { usersPage=await usersPage.NextPageRequest.GetAsync; usersFound.AddRangeusersPage; } 返回usersFound; } 公共异步任务findallgroup { var groupsFound=新列表; var groupsPage=await GraphClient.Groups.Request.GetAsync; groupsFound.AddRangegroupsPage; 而groupsPage.NextPageRequest!=null { groupsPage=await groupsPage.NextPageRequest.GetAsync; groupsFound.AddRangegroupsPage; } 返回组基金; } 公共异步任务FindGroupMembersstring组ID { var usersFound=新列表; var membersPage=await GraphClient.Groups[groupId].Members.Request.GetAsync; usersFound.AddRangemembersPage.Whered=>d.ODataType.Equalsmicrosoft.graph.user.Cast; 而membersPage.NextPageRequest!=null { membersPage=await membersPage.NextPageRequest.GetAsync; usersFound.AddRangeListmembersPage; } 返回usersFound; } 我想编写泛型方法来减少重复,但在上述每个方法中,GetAsync的返回类型都是一个不同的接口,它在自身上定义自己的NextPageRequest属性。这使得无法告诉泛型方法需要调用什么特定类型的NextPageRequest才能编译该方法


有没有办法改进这一点,或者我只需要接受我想要实现的每种查询类型的重复逻辑?

多亏了Microsoft Graph API架构师,我们似乎只能通过使用反射或动态来消除这种冗余。从理论上讲,由于动力学应该提供更好的性能,下面是基于它们的示例代码版本:

private void ProcessAllResultPages<TResult, TItem>(IBaseRequest request,
                                                   Action<TResult> processorDelegate)
                                                   where TResult : ICollectionPage<TItem>
{
    do
    {
        Task<TResult> task = ((dynamic)request).GetAsync();
        processorDelegate(task.Result); // This will implicitly call Wait() on the task.
        request = ((dynamic)task.Result).NextPageRequest;
    } while (request != null);
}
示例用法:

IGraphServiceGroupsCollectionRequest request = graphServiceClient.Groups.Request().
                                                                         Filter(...).
                                                                         Select(...).
                                                                         Top(pageSize);
ProcessAllResultPages<IGraphServiceGroupsCollectionPage, Group>(request,
    result =>
    {
        // Process page results here.
    });

您可以编写一个非泛型方法,该方法接受pagination对象并确定NextPageRequest对象,然后从您的泛型方法调用该对象。它看起来是使用C dynamic关键字的好地方。这是一个有趣的想法@johnnyjob,我以前从未使用过dynamic。这是一个有趣的解决方案。我之所以没有最终实现它,是因为我担心将来其他开发人员会遇到一些可以理解的问题,但它确实解决了前面提到的问题。