ChilliCream Hot Chocolate 方法级别扩展ObjectType方案咨询
[ExtendObjectType] 原生设计为类级别特性,不支持直接标记在单个方法上,但无需编写代理类,通过Hot Chocolate原生提供的几种方式即可实现「将同一个类的不同方法分别归入Query/Mutation等不同操作类型」的细粒度控制:
方式1:方法级操作特性标记(适合可修改业务类的场景)
Hot Chocolate提供
[Query]、[Mutation]、[Subscription]三个操作类型特性,直接标记在对应方法上即可指定方法所属的操作根类型,不受类级别的扩展特性影响。
示例代码:// 业务类无需做特殊类级别标记 public class UserService { // 标记为Query字段 [Query] public User? GetUserById(Guid id) { // 业务逻辑 } // 标记为Mutation字段 [Mutation] public User UpdateUserName(Guid id, string newName) { // 业务逻辑 } // 不打操作特性的内部方法不会被暴露到GraphQL Schema public void InternalLogic() { } }服务注册配置:
public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddGraphQLServer() .AddQueryType(d => d.Name("Query")) .AddMutationType(d => d.Name("Mutation")) // 注册业务类为DI服务,框架自动解析实例 .AddScoped<UserService>() // 自动识别类中标记了操作特性的方法,归入对应根类型 .AddTypes<UserService>(); } }如果希望默认不公开任何未显式标记的方法,可以全局开启显式绑定规则,避免内部方法意外暴露:
services.AddGraphQLServer() .ModifyOptions(o => o.DefaultBindingBehavior = BindingBehavior.Explicit);方式2:Fluent API 按规则绑定字段(零侵入,适合不可修改业务类代码的场景)
如果不想在业务类上引入任何GraphQL相关的特性,可以在服务配置阶段直接按自定义规则从同一个业务类中筛选字段,分别绑定到Query和Mutation类型:
public class Startup { public void ConfigureServices(IServiceCollection services) { services .AddGraphQLServer() .AddQueryType(q => q .Name("Query") // 绑定UserService中所有Get开头的方法到Query .BindFields<UserService>(f => f.Name.StartsWith("Get")) ) .AddMutationType(m => m .Name("Mutation") // 绑定UserService中所有Create/Update/Delete/Set开头的方法到Mutation .BindFields<UserService>(f => f.Name.StartsWith("Create") || f.Name.StartsWith("Update") || f.Name.StartsWith("Delete") || f.Name.StartsWith("Set") ) ) .AddScoped<UserService>(); } }这种方式完全不需要修改业务类代码,筛选规则可以根据团队命名习惯灵活调整。
方式3:逐字段显式注册(适合只需要抽取个别方法的场景)
如果只需要从现有类中选取少数几个方法暴露到GraphQL,可以在配置根类型的时候逐字段指定解析逻辑对应的方法:
services .AddGraphQLServer() .AddQueryType(q => q .Field<UserService>("userById") .Argument<Guid>("id") .ResolveWith<UserService>(s => s.GetUserById(default)) ) .AddMutationType(m => m .Field<UserService>("updateUserName") .Argument<Guid>("id") .Argument<string>("newName") .ResolveWith<UserService>(s => s.UpdateUserName(default, default)) ) .AddScoped<UserService>();
以上能力在Hot Chocolate 12及以上版本均原生支持,不需要额外引入第三方包,也不需要编写冗余的代理类。
内容的提问来源于stack exchange,提问作者YungDeiza
相关产品推荐
相关产品推荐

