HotChocolate中通过字符串引用Expression属性报错,寻求解决方案
解决方案
你当前代码的核心问题有两个:
- 错误地将
Build方法的调用嵌套在Field方法的表达式参数中,HotChocolate需要的是直接指向Profile属性的成员表达式,而非调用其他方法的表达式。 Build方法的泛型参数TClass传错了,应该是Profile而不是IFilterInputTypeDescriptor<Profile>。
以下是实现反射遍历Profile所有属性并添加字段描述符的正确代码:
public class ProfileFilterType : FilterInputType<Profile> { protected override void Configure(IFilterInputTypeDescriptor<Profile> descriptor) { descriptor.BindFieldsExplicitly(); // 反射获取Profile的所有公共实例属性 var properties = typeof(Profile).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { // 为每个属性创建对应表达式并添加字段 var fieldExpression = Build<Profile, object>(prop.Name); descriptor.Field(fieldExpression); } } public static Expression<Func<TClass, TProperty>> Build<TClass, TProperty>(string fieldName) { var param = Expression.Parameter(typeof(TClass), "x"); var property = Expression.Property(param, fieldName); // 处理属性类型与TProperty的转换(用object兼容所有类型) var converted = Expression.Convert(property, typeof(TProperty)); return Expression.Lambda<Func<TClass, TProperty>>(converted, param); } }
关键说明:
- 用
typeof(Profile).GetProperties()获取所有公共实例属性,确保遍历到目标字段。 Build方法的泛型参数TClass指定为Profile,生成的表达式才是针对Profile类型的成员访问。- 添加
Expression.Convert处理类型转换,避免因属性类型不匹配导致的编译错误。 - 直接将生成的表达式传入
descriptor.Field,符合HotChocolate对参数的要求。
如果需要更精准的类型匹配(不用object),可以通过反射动态构建泛型版本的Build方法调用:
protected override void Configure(IFilterInputTypeDescriptor<Profile> descriptor) { descriptor.BindFieldsExplicitly(); var properties = typeof(Profile).GetProperties(BindingFlags.Public | BindingFlags.Instance); var buildMethod = typeof(ProfileFilterType).GetMethod("Build", BindingFlags.Public | BindingFlags.Static); foreach (var prop in properties) { // 动态构建泛型方法:Build<Profile, PropType> var genericBuild = buildMethod.MakeGenericMethod(typeof(Profile), prop.PropertyType); var fieldExpression = genericBuild.Invoke(null, new object[] { prop.Name }) as LambdaExpression; // 调用Field的泛型方法 var fieldMethod = typeof(IFilterInputTypeDescriptor<Profile>).GetMethod("Field").MakeGenericMethod(prop.PropertyType); fieldMethod.Invoke(descriptor, new object[] { fieldExpression }); } } // 保留原Build方法 public static Expression<Func<TClass, TProperty>> Build<TClass, TProperty>(string fieldName) { var param = Expression.Parameter(typeof(TClass)); var field = Expression.PropertyOrField(param, fieldName); return Expression.Lambda<Func<TClass, TProperty>>(field, param); }
这个版本会针对每个属性的实际类型生成表达式,避免类型转换,更符合类型安全要求。
内容的提问来源于stack exchange,提问作者THE AMAZING
相关产品推荐
相关产品推荐

