HotChocolate GraphQL 中的类型继承

问题描述

当我尝试返回从注册类型继承的内容时,HotChocolate 查询似乎总是返回基类。示例:

型号:

public interface ICar { int Wheels { get; } }
public class Car  : ICar { public int Wheels => 4; }
public class Bus : Car { }

查询

public class MyQuery
{
    public ICar test() { return new Bus(); }
}

启动:

services.AddGraphQLServer()
        .AddQueryType<MyQuery>()
        .AddType<Car>()
        .AddType<Bus>()

GraphQL 查询

query { 
  test {
    __typename
  } 
}

输出

{
  "data": {
    test": {
      "__typename": "Car"
    }
  }
}   

我希望输出中的“__typename”是“Bus”。如果我删除接口并将查询的返回类型设置为“汽车”,我会期望相同的行为。我很乐意听到有关为什么它会以这种方式行事以及如何解决此问题的任何想法。

解决方法

这里的问题是 GraphQL 没有继承的概念。 GraphQL 对象类型可以实现接口。 GraphQL 接口也可以实现接口。

因此,在这种情况下,GraphQL 模式中没有实现 Car 的总线。您可以打印架构以验证 C# 代码是如何转换为 GraphQL 的。

您仍然可以使用基类作为接口并构建某种继承树,但在这种情况下,Car 永远不会是具体实例。

services
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddInterfaceType<Car>()
    .AddType<Bus>();

这将转化为:

type Bus implements Car & ICar {
# shortened fro brevity 
}

interface Car implements ICar {
# shortened fro brevity 
}

interface ICar {
# shortened fro brevity 
}

这实际上对您的类型没有意义,只是给您一个想法。

你还能在我们的 GitHub 存储库上提出问题吗?我们可能应该抛出一个架构异常来暗示这里的问题。

如果你想阅读关于对象类型的 GraphQL 规范,可以在这里完成: https://spec.graphql.org/draft/#sec-Objects

这里指定了接口: https://spec.graphql.org/draft/#sec-Interfaces

Hot Chocolate 已经实施了新的 2021 规范草案。