从MethodCallExpression获取投影

时间:2015-04-18 18:42:04

标签: c# .net linq expression-trees

我有一个select的Linq查询,来自我的Linq查询提供程序,我得到一个包含MethodCallExpression表达式树,但我怎样才能获得选择来自MethodCallExpression

投影
    internal static object Execute(Expression expression, bool isEnumerable)
    {
        var whereExpression = expression as MethodCallExpression;
        if (whereExpression == null) throw new InvalidProgramException("Error");

        foreach (var arg in whereExpression.Arguments)
        {
            if (arg is UnaryExpression)
            {
                var unaryExpression = arg as UnaryExpression;

                var lambdaExpression = unaryExpression.Operand as LambdaExpression;
                if (lambdaExpression == null) continue;

                // Here I would like to get the select projections, in this example the "word" projection ...

查询可能如下所示:

var queryable = new MyQueriableClass();

var query = from thing in queryable 
            where thing.id == 1
            select word;

1 个答案:

答案 0 :(得分:3)

目前还不清楚你在做什么,但是

// note the AsQueryable! Otherwise there is no
// Expression tree!
var words = new List<string>() { "an", "apple", "a", "day" }.AsQueryable();

// Note that even IQueryable<string> query = words; 
// is a perfectly good query without a projection!
// The query 
// from word in words where word.Length > 0 select word
// doesn't have a select too (try looking at the 
// expression tree... The select has been elided)
// The projection if not present is implicit, the
// whole object.
var query = from word in words
            select word;

var exp = query.Expression;
var methodCallExpression = exp as MethodCallExpression;

if (methodCallExpression != null)
{
    MethodInfo method = methodCallExpression.Method;

    if (method.DeclaringType == typeof(Queryable) && method.Name == "Select")
    {
        var source = methodCallExpression.Arguments[0];
        var selector = methodCallExpression.Arguments[1];

        // The selector parameter passed to Select is an
        // Expression.Quote(subexpression),
        // where subexpression is the lambda expression
        // word => word here
        if (selector.NodeType != ExpressionType.Quote)
        {
            throw new NotSupportedException();
        }

        UnaryExpression unary = (UnaryExpression)selector;
        Expression operand = unary.Operand;

        if (operand.NodeType != ExpressionType.Lambda)
        {
            throw new NotSupportedException();
        }

        LambdaExpression lambda = (LambdaExpression)operand;

        // This is the "thing" that returns the result
        Expression body = lambda.Body; 
    }
}

最后的body应该是您想要的(或者在结束之前的lambda)。请注意代码块开头的注释。