c# - ExpressionTree 否定字符串操作

标签 c# lambda expression-trees

我有一个将 lambda 添加到 IQueryable 的通用方法。下面的代码添加了一个 StartsWith lambda。我现在要做的是创建一个 NotStartsWith lambda。由于 NotStartsWith 不是字符串运算符,我不确定从哪里开始。

我认为有(应该)有一种方法可以构建处理否定操作的 EpressionTree。但看起来它们都与 Type 上的当前方法调用一起工作,所以我的下一个想法是做一个 IndexOf 并测试 != 0。

因为我确定我需要解决方案来处理其他运算符,所以我希望找到一种创建 lambda 的方法,我可以在其中进行方法调用并将该结果与另一个常量(即(字符串))进行比较.Substring(3,7) == “abcd”。我只是想不出一种在 ExpressionTree 中进行比较的方法。

这就是我为 StartsWith 准备的,它运行良好。我只需要一种方法来否定它,或者(对于 future 的操作甚至更好)找到一种通过比较构建表达式的方法。

    static IQueryable<T> ETForStartsWith<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo)
    {
        ParameterExpression e = Expression.Parameter(typeof(T), "e");
        MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
        ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
        MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
        Expression call = Expression.Call(m, mi, c);

        Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e);
        return query.Where(lambda);
    }

感谢您的帮助!

最佳答案

只是negate方法调用结果:

    /// <summary>
    /// Adds "Where(_ => !_.StringProperty.StartsWith("someValue"))" to the query.
    /// </summary>
    static IQueryable<T> AddNotStartsWith<T>(IQueryable<T> query, PropertyInfo propertyInfo, string value)
    {
        var parameter = Expression.Parameter(typeof(T));
        var memberAccess = Expression.MakeMemberAccess(parameter, propertyInfo);
        var startsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
        var methodCall = Expression.Call(memberAccess, startsWithMethod, Expression.Constant(value));

        return query
            .Where(Expression.Lambda<Func<T, bool>>(Expression.Not(methodCall), parameter));
    }

或以更通用的方式:

    static IQueryable<T> AddComparisonExpression<T>(IQueryable<T> query, PropertyInfo propertyInfo, Func<Expression, Expression> getComparisonExpression)
    {
        var parameter = Expression.Parameter(typeof(T));
        var memberAccess = Expression.MakeMemberAccess(parameter, propertyInfo);

        return query
            .Where(Expression.Lambda<Func<T, bool>>(getComparisonExpression(memberAccess), parameter));
    }

    /// <summary>
    /// Adds "Where(_ => !_.StringProperty.StartsWith("someValue"))" to the query.
    /// </summary>
    static IQueryable<T> AddNotStartsWith<T>(IQueryable<T> query, PropertyInfo propertyInfo, string value)
    {
        return AddComparisonExpression(query, propertyInfo, memberAccess =>
        {
            var startsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
            var methodCall = Expression.Call(memberAccess, startsWithMethod, Expression.Constant(value));

            return Expression.Not(methodCall);
        });
    }

    /// <summary>
    /// Adds "Where(_ => _.StringProperty.Substring(startIndex, length) == value)" to the query.
    /// </summary>
    static IQueryable<T> AddSubstringEquals<T>(IQueryable<T> query, PropertyInfo propertyInfo, int startIndex, int length, string value)
    {
        return AddComparisonExpression(query, propertyInfo, memberAccess =>
        {
            var substringMethod = typeof(string).GetMethod("Substring", new[] { typeof(int), typeof(int) });
            var methodCall = Expression.Call(memberAccess, substringMethod, Expression.Constant(startIndex), Expression.Constant(length));

            return Expression.Equal(methodCall, Expression.Constant(value));
        });
    }

关于c# - ExpressionTree 否定字符串操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32450048/

相关文章:

c# - "Two-way binding requires Path or XPath"编辑 wpf 数据网格时

C# 使光标消失

c++ - 为什么不能在 lambda 中使用私有(private)方法?

c# - LinqKit Predicate Builder 抛出 TypeLoadException?

c# - 使用动态表达式 API 选择匿名类型

Python:使用 lambda 函数按照用户定义的对象的属性进行排序

Java 8 lambda 添加到 Hashmap 中的列表,在 Hashmap 中

c# - LINQ to Entities 仅支持使用 IEntity 接口(interface)转换 EDM 原语或枚举类型

c# - 表达式树作为用户定义查询引擎的基础(使用 EAV)?

.net - 如何指定要从表达式树方法返回的对象?