You need to enable JavaScript to run this app. 如何将Linq Expression<Func<object,bool>>编译为Func<object,bool>并解决ArgumentException
优惠活动
大模型
产品
解决方案
定价
更多

如何将Linq Expression<Func<object,bool>>编译为Func<object,bool>并解决ArgumentException

错误原因

报错的核心是表达式体的返回类型不匹配:

  • CreateExpression 方法最后返回的是 LambdaExpression 类型,你在方法内部已经套了一层Lambda,这个表达式的计算结果是 Func<object, bool> 委托,不是你需要的 bool 类型的条件结果
  • 你在 CompileExpression 中又把这个返回委托的表达式作为Lambda体,再包了一层 Expression.Lambda<Func<object, bool>>,等于外层Lambda的返回值是委托,和你指定的返回类型 bool 冲突,和异常提示的内容完全对应。

修复方案

提供两种改法,第一种逻辑更简洁、可维护性更高:

改法1:去掉CreateExpression里多余的Lambda包装,直接返回条件表达式

注意要保证两层方法用的是同一个ParameterExpression实例,不能重复创建参数,否则会出现参数不匹配的问题:

public delegate Expression ComparisonExpressionDelegate(Expression property, Expression value);
public class ConditionCompiler
{
    public class TestClass
    {
        public string StringProperty1 { get; set; }
        public string StringProperty2 { get; set; }
        public string StringProperty3 { get; set; }
        public int IntProperty1 { get; set; }
        public double DoubleProperty1 { get; set; }
    }
    public static Func<object, bool> Test() 
    {
        PropertyInfo property = typeof(TestClass).GetProperty(nameof(TestClass.StringProperty1));
        object value = "1";
        return CompileExpression(property, value);
    }
    public static Func<object, bool> CompileExpression(PropertyInfo property, object value)
    {
        ParameterExpression obj = Expression.Parameter(typeof(object), "obj");
        // 把外层创建的参数实例传到CreateExpression
        Expression resultExpression = CreateExpression(obj, property, value);
        Func<object, bool> resultLambda
            = Expression.Lambda<Func<object, bool>>(resultExpression, obj).Compile(); 
        return resultLambda;
    }

    // 新增参数接收外部的ParameterExpression实例
    public static Expression CreateExpression(ParameterExpression obj, PropertyInfo property, object value)
    {
        bool isGetMethodStatic = property.GetGetMethod().IsStatic;
        UnaryExpression typedTarget = Expression.Convert(obj, property.DeclaringType);
        MemberExpression memberAccess = Expression.Property(isGetMethodStatic ? null : typedTarget, property);
        UnaryExpression boxedGetter = Expression.TypeAs(memberAccess, typeof(object));
        ConstantExpression valueExpression = Expression.Constant(value);
        ComparisonExpressionDelegate comparisonExpressionDelegate = ToString_Equals_ToString_Expression;
        Expression conditionExpression = comparisonExpressionDelegate(boxedGetter, valueExpression);
        // 直接返回bool类型的条件表达式,去掉多余的Lambda包装
        return conditionExpression;
    }
    private static ComparisonExpressionDelegate ToString_Equals_ToString_Expression
        = (property, value) => Expression.Equal(
            Expression.Call(
                typeof(string),
                nameof(String.Compare),
                null,
                Expression.Call(property, "ToString", null),
                value, Expression.Constant(StringComparison.OrdinalIgnoreCase)
                ),
            Expression.Constant(0)
            );
}

改法2:直接编译CreateExpression返回的Lambda

不需要在CompileExpression里重复套Lambda,直接编译CreateExpression返回的Lambda即可:

public static Func<object, bool> CompileExpression(PropertyInfo property, object value)
{
    LambdaExpression resultExpression = (LambdaExpression)CreateExpression(property, value);
    return (Func<object, bool>)resultExpression.Compile();
}

内容的提问来源于stack exchange,提问作者Michael Wagner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 05:00:02