我是GraphQL新手,目前正在尝试为现有的库构建api。
在这里,我有一个具有唯一别名的标记,一个可以具有不同类型和一些属性的值。
为了处理不同的值类型,我定义了一个包含别名和属性的接口,以及带有不同类型值字段的4个实现。
GraphQL模式如下:
schema {
query: Query
mutation: Mutation
}
type Query {
allTags: [Tag!]
tags(aliases: [ID!]!): [Tag]
tag(alias: ID!): Tag
}
interface Tag {
alias: ID! @isUnique
properties: [TagProperty]
}
type StringTag implements Tag {
alias: ID! @isUnique
properties: [TagProperty]
value: String
}
type IntegerTag implements Tag {
alias: ID! @isUnique
properties: [TagProperty]
value: Int
}
type FloatTag implements Tag {
alias: ID! @isUnique
properties: [TagProperty]
value: Float
}
type BooleanTag implements Tag {
alias: ID! @isUnique
properties: [TagProperty]
value: Boolean
}
type TagProperty {
name: String!
value: String!
}在C#中的接口实现中,我想按照graphql入门文档中的建议使用ResolveType。
接口实现的代码:
public TagInterface(
BooleanTag booleanTag,
IntegerTag integerTag,
FloatTag floatTag,
StringTag stringTag)
{
Name = "Tag";
Description = "A resource which points to a value";
Field<IdGraphType>(
"alias",
"the unique alias of the tag"
);
Field<ListGraphType<TagPropertyType>>(
"properties",
"the properties of a tag defined in the config XML"
);
ResolveType = obj =>
{
if (obj is HtTag)
{
switch ((obj as HtTag).DataType) {
case EDataType.Bool:
return booleanTag;
case EDataType.Byte:
case EDataType.Sbyte:
case EDataType.Short:
case EDataType.Ushort:
case EDataType.Int:
case EDataType.Uint:
case EDataType.Long:
case EDataType.Ulong:
return integerTag;
case EDataType.Double:
case EDataType.Float:
case EDataType.Decimal:
return floatTag;
default:
return stringTag;
}
}
throw new ArgumentOutOfRangeException($"Could not resolve graph type for {obj.GetType().Name}");
};
}}
当我运行以下查询时
query {
tags(aliases:["TagID_S1A02_IN","TagID_S1A03_IN"]) {
__typename
alias
... on StringTag {
value
}
... on IntegerTag {
value
}
... on BooleanTag {
value
}
... on FloatTag {
value
}
}
}我得到以下错误:
{
"errors": [
{
"message": "Für dieses Objekt wurde kein parameterloser Konstruktor definiert."
}
]
}这似乎是因为接口定义中的4个构造函数参数(根据docs中的示例)。如果在new StringTag()实现中删除它们并返回ResolveType等,则得到正确的结果数,但没有内容:
{
"data": {
"tags": [
{
"__typename": "StringTag",
"alias": null,
"value": null
},
{
"__typename": "StringTag",
"alias": null,
"value": null
}
]
}
}有人能告诉我我在这里做错了什么吗?
更新
我使用无参数构造函数并返回已解析的对象,使其工作,如下所示:
ResolveType = obj =>
{
if (obj is HtTag)
{
switch ((obj as HtTag).DataType) {
case EDataType.Bool:
return (from t in PossibleTypes where t is BooleanTag select t).First();
case EDataType.Byte:
case EDataType.Sbyte:
case EDataType.Short:
case EDataType.Ushort:
case EDataType.Int:
case EDataType.Uint:
case EDataType.Long:
case EDataType.Ulong:
return (from t in PossibleTypes where t is IntegerTag select t).First();
case EDataType.Double:
case EDataType.Float:
case EDataType.Decimal:
return (from t in PossibleTypes where t is FloatTag select t).First();
default:
return (from t in PossibleTypes where t is StringTag select t).First();
}
}
throw new ArgumentOutOfRangeException($"Could not resolve graph type for {obj.GetType().Name}");
};这就是我们应该使用的方式吗?
发布于 2017-11-16 04:30:28
为了能够解决您的TagInterface类型,您需要使用某种形式的依赖注入。您的TagInterface和所有其他GraphType模式类型都需要在DI容器中注册。
如果使用2.0预发行版,请使用以下内容(.NET核心示例):
services.AddSingleton<ISchema>(
s => new StarWarsSchema(new FuncDependencyResolver(type => (IGraphType)s.GetRequiredService(type))));https://github.com/graphql-dotnet/graphql-dotnet/blob/master/src/GraphQL.GraphiQLCore/Startup.cs#L29
您可以直接使用func的旧版本(.NET核心示例):
services.AddSingleton<ISchema>(
s => new StarWarsSchema(type => (IGraphType)s.GetRequiredService(type)));有关更多信息,请参见这些文档(尚未更新到2.0 alpha ):
https://graphql-dotnet.github.io/docs/getting-started/dependency-injection
如果这些标记类型没有在模式中的其他地方公开,您可能还需要在Schema上使用它们注册这些标记类型。
构建架构时,它会查看“根”类型(查询、变异、订阅),并收集它们公开的所有GraphTypes。在使用接口类型时,通常不会在根类型(或它们的任何子类型)上公开具体类型。由于这些具体类型从未在类型图中公开,模式不知道它们的存在。这就是架构上的RegisterType<>方法的作用所在。通过使用RegisterType<>,它将告诉架构有关特定类型的信息,并在初始化架构时正确地将其添加到接口类型上的PossibleTypes集合中。
https://graphql-dotnet.github.io/docs/getting-started/interfaces#registertype
https://stackoverflow.com/questions/47314451
复制相似问题