我正在尝试通过Expression
检索属性的值。但是,当我运行代码时,出现异常
未处理的异常。 System.InvalidOperationException:从作用域“”引用的类型为“ GraphQlMcve.Program + Teacher”的变量“ teacher”,但未定义
当我尝试编译表达式时,会在下面的方法中发生这种情况。
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 package Install-Package GraphQL -Version 2.4.0
。
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> { }
}
}
答案 0 :(得分:1)
IEnumerable<Pupil> pupilList = Expression.Lambda<Func<IReadOnlyCollection<Pupil>>>(pupils.Body).Compile()();
这部分代码是错误的。您选择表达式的一部分并进行编译。您编译的部分具有教师表达,并且您破坏了与之的联系。您可以做的是:编译已经在函数中传递的主表达式。
var pupilList = puplis.Compile()(/* you need to pass here an actual object */);
编译表达式时,将创建一个处理对象的函数,但您没有传递该对象。在您的教师示例中,它必须是教师对象。