C# 表达式树:未为类型定义二进制运算符
我使用ExpressionVisitor类动态更改发送到数据库的搜索查询。我想用Contains方法替换二进制或表达式,它是AndAlso表达式的左操作数,但我当前的代码生成以下错误: 没有为类型定义二进制运算符AndAlso 'System.Func`2[foo.MV,System.Boolean]'和'System.Boolean' 文档表明,我应该能够提供(表达式,表达式)作为此二进制AndAlso表达式的参数,但下面的代码显然不满足左操作数的要求:C# 表达式树:未为类型定义二进制运算符,c#,linq,expression-trees,C#,Linq,Expression Trees,我使用ExpressionVisitor类动态更改发送到数据库的搜索查询。我想用Contains方法替换二进制或表达式,它是AndAlso表达式的左操作数,但我当前的代码生成以下错误: 没有为类型定义二进制运算符AndAlso 'System.Func`2[foo.MV,System.Boolean]'和'System.Boolean' 文档表明,我应该能够提供(表达式,表达式)作为此二进制AndAlso表达式的参数,但下面的代码显然不满足左操作数的要求: protected override
protected override Expression VisitBinary(BinaryExpression b) {
if (b.NodeType == ExpressionType.Or) {
ParameterExpression vParam = Expression.Parameter(typeof(MV), "mv");
var mvID = Expression.Property(vParam, "MVID");
ConstantExpression ftsIDs = Expression.Constant(FtsIds, typeof(List<long>));
var containsInfo = typeof(List<long>).GetMethod("Contains", new Type[] { typeof(long) });
var containsExp = Expression.Call(ftsIDs, containsInfo, new Expression[] { mvID });
return Expression.Lambda<Func<MV, bool>>(containsExp, vParam);
}
}
受保护的重写表达式访问二进制(二进制表达式b){
如果(b.NodeType==ExpressionType.Or){
ParameterExpression vParam=表达式参数(类型(MV),“MV”);
var mvID=Expression.Property(vParam,“mvID”);
ConstantExpression ftsIDs=表达式.常量(ftsIDs,typeof(List));
var containsInfo=typeof(List).GetMethod(“Contains”,新类型[]{typeof(long)});
var containsExp=Expression.Call(ftsIDs,containsInfo,新表达式[]{mvID});
返回表达式.Lambda(containsExp,vParam);
}
}
我理解基本信息:类型不匹配,但我看不出我还需要做些什么才能将替换代码转换为可以工作的代码,而且我看过的所有示例代码都有太简单的场景
更新:
多亏了安东宁。关键词:“外部环境”。vParam已定义
上面的代码正在重新创建它,编译器可能会给它起一个时髦的名字。。。。并最终成为一个引用不同实例的用户。实际需要做的是获取现有的vParam表达式,如下所示:
protected override Expression VisitBinary(BinaryExpression b) {
if (b.NodeType == ExpressionType.Or) {
MethodCallExpression mce = this.Visit(b.Left) as MethodCallExpression;
MemberExpression mex = mce?.Object as MemberExpression;
var mvID = Expression.Property(mex.Expression, "MVID"); // << Injecting existing param here
ConstantExpression ftsIDs = Expression.Constant(FtsIds, typeof(List<long>));
var containsInfo = typeof(List<long>).GetMethod("Contains", new Type[] { typeof(long) });
var containsExp = Expression.Call(ftsIDs, containsInfo, new Expression[] { mvID });
return containsExp;
}
}
受保护的重写表达式访问二进制(二进制表达式b){
如果(b.NodeType==ExpressionType.Or){
MethodCallExpression mce=this.Visit(b.Left)作为MethodCallExpression;
MemberExpression mex=mce?对象作为MemberExpression;
var mvID=Expression.Property(mex.Expression,“mvID”);//您应该直接返回containsExp
,传递表达式。Lambda
作为和
的参数是没有意义的。和
可以对布尔值进行运算。如果结果是布尔值,它可以对函数的结果进行运算。但它不能将函数本身作为参数
你所做的基本上是
bool res = ((Func<MV, bool>)(mv => FtsIds.Contains(mv.MVID))) && true;
bool res=((Func)(mv=>FtsIds.Contains(mv.MVID))&&true;
我已经尝试过了,但是我需要Lambda来包含vParam。当我直接返回containExp时,我得到一个关于缺少的参数没有定义的不同错误。vParam是我正在对照列表检查其ID的参数。例如,没有vParam就没有上下文,我看不出没有Lambda如何返回它。您必须e参数vParam,您必须向其提供一些数据。这些数据可能位于此表达式之外的某个位置,因此使用此参数构建lambda的正确位置位于整个表达式的顶部,位于和
上方。