如何将谓词表达式分解为查询? [英] How do I decompose a Predicate Expression into a query?

查看:88
本文介绍了如何将谓词表达式分解为查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类Person,带有自定义的Where方法:

I have the following class Person, with a custom Where method:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public string Where(Expression<Func<Person, bool>> predicate)
    {
        return String.Empty;
    }
}

如何以可枚举的方式检索Expression参数名称和值?

How can I retrieve the Expression parameter names and values in an enumerable manner?

Person p = new Person();
p.Where(i => i.Name == "Shlomi" && i.Age == 26);

为了构建一个字符串查询,并根据表达式的名称和值附加参数.

For the purpose of building a string query with parameters attached according to the name and value of the expression.

// Eventually I will convert the above into the following:
string Query = "select * from person where name = @Name AND Age = @Age";

SqlParameter[] param = new SqlParameter[] { 
    new SqlParameter("@Name","Shlomi"),
    new SqlParameter("@Age","26")
};

推荐答案

我当然认为我的先前答案.

I certainly think you should follow StriplingWarrior's advice and use LINQ to Entities or LINQ to SQL, but for the sake of reinventing the wheel (poorly) I'll build off of a prior answer of mine.

// Start with a method that takes a predicate and retrieves the property names
static IEnumerable<string> GetColumnNames<T>(Expression<Func<T,bool>> predicate)
{
    // Use Expression.Body to gather the necessary details
    var members = GetMemberExpressions(predicate.Body);
    if (!members.Any())
    {
        throw new ArgumentException(
            "Not reducible to a Member Access", 
            "predicate");
    }

    return members.Select(m => m.Member.Name);
}

现在,您需要遍历表达式树,访问每个候选表达式,并确定其中是否包含MemberExpression.下面的GetMemberExpressions方法将遍历表达式树并检索在以下位置找到的每个MemberExpression:

Now you need to walk the expression tree, visiting each candidate expression, and determine if it includes a MemberExpression. The GetMemberExpressions method below will walk an expression tree and retrieve each of the MemberExpressions found within:

static IEnumerable<MemberExpression> GetMemberExpressions(Expression body)
{
    // A Queue preserves left to right reading order of expressions in the tree
    var candidates = new Queue<Expression>(new[] { body });
    while (candidates.Count > 0)
    {
        var expr = candidates.Dequeue();
        if (expr is MemberExpression)
        {
            yield return ((MemberExpression)expr);
        }
        else if (expr is UnaryExpression)
        {
            candidates.Enqueue(((UnaryExpression)expr).Operand);
        }
        else if (expr is BinaryExpression)
        {
            var binary = expr as BinaryExpression;
            candidates.Enqueue(binary.Left);
            candidates.Enqueue(binary.Right);
        }
        else if (expr is MethodCallExpression)
        {
            var method = expr as MethodCallExpression;
            foreach (var argument in method.Arguments)
            {
                candidates.Enqueue(argument);
            }
        }
        else if (expr is LambdaExpression)
        {
            candidates.Enqueue(((LambdaExpression)expr).Body);
        }
    }
}

这篇关于如何将谓词表达式分解为查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆