0

我创建了一个帮助类,它能够从字符串参数构建 lambda 表达式,我可以使用它过滤查询结果。

但是我对 LINQ.Expressions.Expression 没有 Contains 方法没有什么问题。

这是我的代码:

 string member = d.Member;
        object value = d.Value;

        System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");

        foreach (var property in member.Split('.'))
        {
            expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
        }

        ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string));

        BinaryExpression b = null;

        switch (d.Operator)
        {
            case FilterOperator.IsEqualTo:

                b = System.Linq.Expressions.Expression.Equal(expression, c);

                break;

            case FilterOperator.Contains:

                b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression;

                break;

            case FilterOperator.IsGreaterThanOrEqualTo:

                b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c);

                break;

            case FilterOperator.IsLessThanOrEqualTo:

                b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c);

                break;
        }


        CriteriaCollection.Add(b);

static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
    {
        var parameterExp = Expression.Parameter(typeof(T), "type");
        var propertyExp = Expression.Property(parameterExp, propertyName);
        MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        var someValue = Expression.Constant(propertyValue, typeof(string));
        var containsMethodExp = Expression.Call(propertyExp, method, someValue);

        return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
    }

它应该可以工作,但是我如何将 Expression 转换为 BinaryExpression?

有人知道这一点或知道其他有效的解决方案吗?

4

2 回答 2

1

我知道这个问题已经很久没有问过了,但是,好吧,我想我已经找到了答案,基本上,答案就在MakeBinary.

首先,我必须创建一个类似 Contains 的方法,但不是自引用扩展方法,如下所示:

public static bool Containss(string text, string text2)
{
    return text.Contains(text2, StringComparison.OrdinalIgnoreCase);
}

然后你像这样使用它:

MethodInfo method = typeof(StackOverflowAnswer).GetMethod("Containss", new[] { typeof(string), typeof(string) });
var constainsExp = Expression.MakeBinary(ExpressionType.Equal, Expression.Constant("FULL TEXT"), Expression.Constant("TEXT"), false, method);

考虑到您的可证明目标,也可能有所帮助的是接收成员、参数和值来组成您的最终表达式。这是一个例子:

class StackOverflowAnswer
{
    static void Main()
    {
        ParameterExpression parameter = Expression.Parameter(typeof(Student), typeof(Student).Name);

        var exp1 = GetBinaryExpression(parameter, "Name", "Foo");
        var exp2 = GetBinaryExpression(parameter, "Name", "Bar");
        BinaryExpression[] expressions = new BinaryExpression[] { exp1, exp2 };

        var bin = CombineExpressions(expressions, parameter);
        var func = Expression.Lambda<Func<Student, bool>>(bin, parameter);
        var exp = func.Compile();

        Student student = new Student { Name = "Foo Bar" };

        var x = exp(student);

        Console.WriteLine(x);
    }

    public static BinaryExpression GetBinaryExpression(ParameterExpression parameter, string property, object comparissonValue)
    {
        MemberExpression member = Expression.Property(parameter, property);
        ConstantExpression constant = Expression.Constant(comparissonValue, comparissonValue.GetType());

        MethodInfo method = typeof(StackOverflowAnswer).GetMethod("Containss", new[] { typeof(string), typeof(string) });
        var containsExp = Expression.MakeBinary(ExpressionType.Equal, member, constant, false, method);
        return containsExp ;
    }

    public static BinaryExpression CombineExpressions(BinaryExpression[] expressions, ParameterExpression parameter)
    {
        bool first = true;
        BinaryExpression expFull = expressions[0];
        foreach (BinaryExpression item in expressions)
        {
            if (first)
                first = false;
            else
            {
                expFull = Expression.AndAlso(expFull, item);
            }
        }
        return expFull;
    }

    internal class Student
    {
        public string Name { get; set; }
    }
}
于 2020-08-19T13:05:42.807 回答
-2
 public class FilterExpressionHelper<T> where T : class
{
    public FilterExpressionHelper()
    {
        CriteriaCollection = new List<BinaryExpression>();
    }

    public List<BinaryExpression> CriteriaCollection { get; set; }

    public Expression<Func<T, bool>> NoFilterExpression { get; set; }

    public void RemoveFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
    {
        string member = d.Member;
        object value = d.Value;

        System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");

        foreach (var property in member.Split('.'))
        {
            expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
        }

        ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string));
        BinaryExpression b = System.Linq.Expressions.Expression.Equal(expression, c);

        BinaryExpression expr = CriteriaCollection.Where(cr => cr.Right.ToString() == b.Right.ToString()).FirstOrDefault();

        CriteriaCollection.Remove(expr);
    }

    public void AddFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
    {
        string member = d.Member;
        object value = d.Value;

        System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");

        foreach (var property in member.Split('.'))
        {
            expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
        }

        ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, value.GetType());

        BinaryExpression b = null;

        switch (d.Operator)
        {
            case FilterOperator.IsEqualTo:

                b = System.Linq.Expressions.Expression.Equal(expression, c);

                break;

            case FilterOperator.Contains:

                //b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression;


                break;

            case FilterOperator.IsGreaterThanOrEqualTo:

                b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c);

                break;

            case FilterOperator.IsLessThanOrEqualTo:


                    b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c);

                break;
        }


        CriteriaCollection.Add(b);
    }

    public  Expression<Func<T, bool>> GetLambdaExpression()
    {
        ParameterExpression e = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");

        var orderedList = CriteriaCollection.OrderBy(cr => cr.Left.ToString()).ToList();

        var disctinctValues = CriteriaCollection.Distinct(new BinaryExpressionComparer()).ToList();

        List<BinaryExpression> orElseExpressionList = new List<BinaryExpression>();

        foreach (var value in disctinctValues)
        {
            System.Linq.Expressions.BinaryExpression expression = null;

            foreach (var criteria in orderedList.Where(cr => cr.Left.ToString().Equals(value.Left.ToString())))
            {
                if (expression == null)
                {
                    expression = criteria;
                }
                else
                {
                    if (expression.Left.ToString() == criteria.Left.ToString())
                        expression = System.Linq.Expressions.BinaryExpression.OrElse(expression, criteria);
                    else
                        expression = System.Linq.Expressions.BinaryExpression.AndAlso(expression, criteria);

                }
            }

            orElseExpressionList.Add(expression);
        }

        System.Linq.Expressions.BinaryExpression expressionAnd = null;

        foreach (var ex in orElseExpressionList)
        {
            if (expressionAnd == null)
            {
                expressionAnd = ex;
            }
            else
            {
                expressionAnd = System.Linq.Expressions.BinaryExpression.AndAlso(expressionAnd, ex);
            }
        }

        if (expressionAnd != null)
        {
            return System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(expressionAnd, e);
        }
        else
        {
            return NoFilterExpression;
        }
    }

    static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
    {
        var parameterExp = Expression.Parameter(typeof(T), "type");
        var propertyExp = Expression.Property(parameterExp, propertyName);
        MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        var someValue = Expression.Constant(propertyValue, typeof(string));
        var containsMethodExp = Expression.Call(propertyExp, method, someValue);

        return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
    }

    private static System.Linq.Expressions.BinaryExpression Like(Expression lhs, Expression rhs)
    {
        //typeof(string).GetMethod("Contains", new Type[] { typeof(string) }, null);

        Expression expression = Expression.Call(
            typeof(FileInfoHelper).GetMethod("Like",
                BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
                , lhs, rhs);

        return expression as BinaryExpression;
    }

    class BinaryExpressionComparer : IEqualityComparer<BinaryExpression>
    {
        #region IEqualityComparer<Contact> Members

        public bool Equals(BinaryExpression x, BinaryExpression y)
        {
            return x.Left.ToString().Equals(y.Left.ToString());
        }

        public int GetHashCode(BinaryExpression obj)
        {
            return obj.Left.ToString().GetHashCode();
        }

        #endregion
    }
}
于 2012-07-09T12:20:46.623 回答