C# 使用ResolveType的GraphQL.NET接口
我是GraphQL新手,目前正在尝试为现有库构建api 在那里我有一个唯一的别名,一个可以是不同类型的值和一些属性的标记 为了处理不同的值类型,我定义了一个包含别名和属性的接口,以及4个具有不同类型值字段的实现 GraphQL模式如下所示:C# 使用ResolveType的GraphQL.NET接口,c#,graphql,graphql-dotnet,C#,Graphql,Graphql Dotnet,我是GraphQL新手,目前正在尝试为现有库构建api 在那里我有一个唯一的别名,一个可以是不同类型的值和一些属性的标记 为了处理不同的值类型,我定义了一个包含别名和属性的接口,以及4个具有不同类型值字段的实现 GraphQL模式如下所示: schema { query: Query mutation: Mutation } type Query { allTags: [Tag!] tags(aliases: [ID!]!): [Tag] tag(alias:
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 dotnet入门文档中的建议使用
接口实现的代码:
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}");
};
}
我得到以下错误:
{
"errors": [
{
"message": "Für dieses Objekt wurde kein parameterloser Konstruktor definiert."
}
]
}
这似乎是因为接口定义中有4个构造函数参数(根据文档中的示例)。如果在ResolveType实现中删除它们并返回new StringTag()
等,则会得到正确数量的结果,但没有内容:
{
"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}");
};
这就是它应该使用的方式吗?为了能够解析您的
TagInterface
类型,您需要使用某种形式的依赖项注入。您的TagInterface
和所有其他GraphType
架构类型都需要在DI容器中注册
如果使用2.0预发行版,请使用以下(.NET核心示例):
services.AddSingleton(
s=>new StarWarsSchema(新的FuncDependencyResolver(类型=>(IGraphType)s.GetRequiredService(类型));
旧版本可以直接使用func(.NET核心示例):
services.AddSingleton(
s=>newstarwarsschema(type=>(IGraphType)s.GetRequiredService(type));
有关更多信息,请参阅这些文档(尚未更新到2.0 alpha版本):
如果这些标记类型未在架构中的其他地方公开,您可能还需要使用Schema
上的RegisterType
注册它们
构建模式时,它会查看“根”类型(查询、,
突变、订阅)并收集它们公开的所有图形类型。
在使用接口类型时,通常会使用具体类型
未暴露在根类型(或其任何子类型)上。自从
这些具体类型永远不会在模式的类型图中公开
不知道他们的存在。这就是
模式是用于。通过使用RegisterType,它告诉模式
它将正确地将其添加到可能的类型中
初始化架构时接口类型上的集合
嗨,乔,谢谢你的回复。我已经使用
RegisterType()
注册了接口实现。这些类型也得到了正确的解析(请参阅orig.post中的最后一个代码片段)。当我在StringTag
的alias resolve函数中设置断点时,正确的数据也在那里。但它不会在响应中返回!我很困惑,因为只有当它试图使用默认实现Activator.CreateInstance
创建类型时,您才会遇到您发布的错误。您是说TagInterface
及其所有构造函数参数都已解析?你用的是什么DI容器?玩了一会儿。您需要确保将DI解析器传递给基类Schema
class<代码>标记模式(IDependencyResolver解析器):基本(resolver)。您还需要确保您的*标记类型注册为单例,因为在ctor
中解析的实例可能与在模式
查找中注册的实例不同。这可能是你遇到的两个问题。嗯,我目前没有使用任何DI容器,我在没有ASP.Net的纯.NET4.5上。。。我也不直接使用依赖解析程序。使用ctor
注入的唯一方法是使用DI容器(graphql dotnet没有为您提供),因此这将是您的问题。
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}");
};
services.AddSingleton<ISchema>(
s => new StarWarsSchema(new FuncDependencyResolver(type => (IGraphType)s.GetRequiredService(type))));
services.AddSingleton<ISchema>(
s => new StarWarsSchema(type => (IGraphType)s.GetRequiredService(type)));