我试图通过Expression检索属性的值。但是,当我运行代码时,我会得到异常。
未处理的异常。System.InvalidOperationException:类型为“GraphQlMcve.Program+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软件包 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> { }
}
}发布于 2019-11-18 21:33:02
IEnumerable<Pupil> pupilList = Expression.Lambda<Func<IReadOnlyCollection<Pupil>>>(pupils.Body).Compile()();这部分代码是错误的。选择表达式的一部分并对其进行编译。你编写的部分有一个老师的表达,你打破了它的关系。您可以做的是:编译主表达式,即您已经在函数中传递的表达式。
var pupilList = puplis.Compile()(/* you need to pass here an actual object */); 在编译表达式时,可以创建一个函数,该函数处理一个对象,但不传递该对象。在你的老师的例子中,它必须是一个老师的对象。
https://stackoverflow.com/questions/58922713
复制相似问题