OrchardCore 中为现有类型 实现自定义 Graphql 查询

发布时间 2023-04-02 14:59:22作者: 韩严重

很多情况下,需要自定义逻辑来实现 Graphql查询,

比如 通过Graphql 查询当前用户信息

因为 Graphql 是强类型的,所以我们要先实现一个Schema

定义一个类,实现 OrchardCore.Apis.GraphQL.ISchemaBuilder 接口

 public class UserInfoQueryFieldTypeProvider : ISchemaBuilder

构建自定义字段 

 1  public Task BuildAsync(ISchema schema)
 2         {
 3             //从已注册类型中查找指定类型字段
 4             var typetype = schema.Query.Fields.OfType<ContentItemsFieldType>()
 5                 .FirstOrDefault(x => x.Name == "UserProfile");
 6             if (typetype == null)
 7             {
 8                 return null;
 9             }
10             //因为系统自动注册的类型是集合形式的,所以先要进行转换
11             var type = (ListGraphType)typetype.ResolvedType;
12             var field = new FieldType
13             {
14                 Name = "Me",
15                 Description = S["Information about the current login user."],
16                 Type = typeof(ContentItemInterface),
17                 ResolvedType = type.ResolvedType,
18                 Resolver = new AsyncFieldResolver<ContentItem>(ResolveAsync)
19             };
20 
21             schema.Query.AddField(field);
22 
23             return Task.CompletedTask;
24         }

告知 系统何时更新Schema ,因为我们的 当前用户是 基于现有动态类型实现的,所以监听 类型定义的变更即可

1         public Task<string> GetIdentifierAsync()
2         {
3             var contentDefinitionManager = _httpContextAccessor.HttpContext.RequestServices.GetService<IContentDefinitionManager>();
4             return contentDefinitionManager.GetIdentifierAsync();
5         }

 

自定义逻辑实现:

 1  private async Task<ContentItem> ResolveAsync(IResolveFieldContext context)
 2         {
 3             var serviceProvider = _httpContextAccessor.HttpContext.RequestServices;
 4             var userManager = serviceProvider.GetRequiredService<UserManager<IUser>>();
 5             var user = await userManager.FindByNameAsync(_httpContextAccessor.HttpContext.User.Identity.Name) as User;
 6             var contentManager = serviceProvider.GetService<IContentManager>();
 7             var contentItem = await contentManager.GetAsync(user.UserId);
 8             if (contentItem == null)
 9             {
10                 contentItem = await contentManager.NewAsync("UserProfile");
11                 contentItem.Owner = user.UserId;
12 
13                 contentItem.Alter<UserProfile>(profile =>
14                 {
15                     profile.Roles.Values = user.RoleNames.ToArray();
16                     profile.UserName.Text = user.UserName;
17                     profile.Email.Text = user.Email;
18                 });
19             }
20 
21             return contentItem;
22         }

 

 最后别忘了向DI注册

services.AddSingleton<ISchemaBuilder, UserInfoQueryFieldTypeProvider>();

 

以上示例实现了一个 非集合类型的查询

如果 需要返回集合类型 参考如下代码: 

 1         public Task BuildAsync(ISchema schema)
 2         {
 3             var typetype = schema.Query.Fields.OfType<ContentItemsFieldType>()
 4                 .FirstOrDefault(x => x.Name == nameof(AntdMenuItem));
 5             if (typetype == null)
 6             {
 7                 return Task.CompletedTask;
 8             }
 9 
10             var field = new FieldType
11             {
12                 Name = "userMenus",
13                 Description = S["获取用户菜单"],
14                 Type = typeof(ListGraphType<ContentItemType>),
15                 ResolvedType = typetype.ResolvedType,
16                 Resolver = new LockedAsyncFieldResolver<IEnumerable<ContentItem>>(ResolveAsync)
17             };
18 
19             schema.Query.AddField(field);
20 
21             return Task.CompletedTask;
22         }