OrchardCore 中为现有动态类型实现自定义Graphql 查询
很多情况下,需要自定义逻辑来实现 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 }