首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GraphQL:类型从作用域引用的变量,但未定义

GraphQL:类型从作用域引用的变量,但未定义
EN

Stack Overflow用户
提问于 2019-11-18 20:51:33
回答 1查看 180关注 0票数 0

我试图通过Expression检索属性的值。但是,当我运行代码时,我会得到异常。

未处理的异常。System.InvalidOperationException:类型为“GraphQlMcve.Program+Teacher”的变量“教师”,从范围中引用,但没有定义

这发生在下面的方法中,当我试图编译表达式时。

代码语言:javascript
复制
protected FieldBuilder<T, object> PupilListField(string name,
    Expression<Func<T, IReadOnlyCollection<Pupil>>> pupils)
{
    return BaseAugmentedPupilListQuery(name)
        .Resolve(context =>
        {
            IEnumerable<Pupil> pupilList =
                Expression.Lambda<Func<IReadOnlyCollection<Pupil>>>(pupils.Body).Compile()();
            return AugmentedPupilListQueryBaseResolver(context, pupilList);
        });
}

我使用的表达式是teacher => teacher.Pupils。为什么会发生这种情况?

下面是一个可运行的示例。

下面的代码示例使用GraphQL NuGet软件包 Install-Package GraphQL -Version 2.4.0

代码语言:javascript
复制
using GraphQL.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using GraphQL;
using GraphQL.Types;

namespace GraphQlMcve
{
    internal class Program
    {
        private static void Main()
        {
            const string query = @"{ teachers { id, name, pupils(id: ""2"") { id, name } } }";
            Schema schema = new Schema { Query = new SchoolQuery() };
            Console.WriteLine(schema.Execute(_ => { _.Query = query; _.ExposeExceptions = true; _.ThrowOnUnhandledException = true; }));
        }

        private class Pupil
        {
            public string Id { get; set; }
            public string Name { get; set; }
        }

        private class PupilType : ObjectGraphType
        {
            public PupilType()
            {
                Field<NonNullGraphType<IdGraphType>>(nameof(Pupil.Id));
                Field<StringGraphType>(nameof(Pupil.Name));
            }
        }

        private class Teacher
        {
            public string Id { get; set; }
            public string Name { get; set; }
            public List<Pupil> Pupils { get; set; }
        }

        private class TeacherType : BaseEntityGraphType<Teacher>
        {
            public TeacherType()
            {
                Field<NonNullGraphType<IdGraphType>>(nameof(Teacher.Id));
                Field<StringGraphType>(nameof(Teacher.Name));
                PupilListField(nameof(Teacher.Pupils), teacher => teacher.Pupils);
            }
        }

        private class SchoolQuery : BaseEntityGraphType
        {
            public SchoolQuery()
            {
                List<Pupil> pupils = new List<Pupil>
                {
                    new Pupil { Id = "1", Name = "Sarah" },
                    new Pupil { Id = "2", Name = "Adam" },
                    new Pupil { Id = "3", Name = "Gill" },
                };

                List<Teacher> teachers = new List<Teacher> { new Teacher { Id = "4", Name = "Sarah", Pupils = pupils} };

                PupilListField("pupils", pupils);

                Field<ListGraphType<TeacherType>>(
                    "teachers",
                    arguments: new QueryArguments(
                        new QueryArgument<IdGraphType> { Name = "id" }
                    ),
                    resolve: context => teachers
                );
            }
        }

        private abstract class BaseEntityGraphType<T> : ObjectGraphType<T>
        {
            protected FieldBuilder<T, object> PupilListField(string name,
                Expression<Func<T, IReadOnlyCollection<Pupil>>> pupils)
            {
                return BaseAugmentedPupilListQuery(name)
                    .Resolve(context =>
                    {
                        IEnumerable<Pupil> pupilList =
                            Expression.Lambda<Func<IReadOnlyCollection<Pupil>>>(pupils.Body).Compile()();
                        return AugmentedPupilListQueryBaseResolver(context, pupilList);
                    });
            }

            protected FieldBuilder<T, object> PupilListField(string name, IReadOnlyCollection<Pupil> pupils)
            {
                return BaseAugmentedPupilListQuery(name)
                    .Resolve(context => AugmentedPupilListQueryBaseResolver(context, pupils));
            }

            private FieldBuilder<T, object> BaseAugmentedPupilListQuery(string name)
            {
                return Field<ListGraphType<PupilType>>()
                    .Name(name)
                    .Description("")
                    .Argument<IdGraphType>("id", "");
            }

            private static IEnumerable<Pupil> AugmentedPupilListQueryBaseResolver(
                ResolveFieldContext<T> context,
                IEnumerable<Pupil> pupils)
            {
                string id = context.GetArgument<string>("id");
                return string.IsNullOrWhiteSpace(id) ? pupils : pupils.Where(pupil => pupil.Id == id);
            }
        }

        private abstract class BaseEntityGraphType : BaseEntityGraphType<object> { }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-18 21:33:02

代码语言:javascript
复制
IEnumerable<Pupil> pupilList = Expression.Lambda<Func<IReadOnlyCollection<Pupil>>>(pupils.Body).Compile()();

这部分代码是错误的。选择表达式的一部分并对其进行编译。你编写的部分有一个老师的表达,你打破了它的关系。您可以做的是:编译主表达式,即您已经在函数中传递的表达式。

代码语言:javascript
复制
var pupilList = puplis.Compile()(/* you need to pass here an actual object */); 

在编译表达式时,可以创建一个函数,该函数处理一个对象,但不传递该对象。在你的老师的例子中,它必须是一个老师的对象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58922713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档