C# 从MethodCallExpression获取投影

C# 从MethodCallExpression获取投影,c#,.net,linq,expression-trees,C#,.net,Linq,Expression Trees,我有一个带有select的Linq查询,从我的Linq查询提供程序中,我得到一个包含MethodCallExpression的表达式树,但是我如何从MethodCallExpression中获得select投影呢 internal static object Execute(Expression expression, bool isEnumerable) { var whereExpression = expression as MethodCallExpres

我有一个带有
select
的Linq查询,从我的Linq查询提供程序中,我得到一个包含
MethodCallExpression
的表达式树,但是我如何从
MethodCallExpression
中获得select投影呢

    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;

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

// 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; 
    }
}
//注意AsQueryable!否则就没有了
//表情树!
var words=new List(){“an”、“apple”、“a”、“day”}.AsQueryable();
//请注意,即使IQueryable查询=单词;
//是一个没有投影的非常好的查询!
//询问
//从word.Length>0的word中选择word
//也没有选择(请尝试查看
//表达式树…选择已删除)
//投影如果不存在,则为隐式投影
//整个物体。
var query=从word到words
选择单词;
var exp=query.Expression;
var methodCallExpression=exp作为methodCallExpression;
if(methodCallExpression!=null)
{
MethodInfo方法=methodCallExpression.method;
if(method.DeclaringType==typeof(Queryable)&&method.Name==Select)
{
var source=methodCallExpression.Arguments[0];
var selector=methodCallExpression.Arguments[1];
//传递给Select的选择器参数是
//Expression.Quote(子表达式),
//其中,子表达式是lambda表达式
//word=>word在这里
if(selector.NodeType!=ExpressionType.Quote)
{
抛出新的NotSupportedException();
}
一元表达式一元=(一元表达式)选择器;
表达式操作数=一元操作数;
if(operand.NodeType!=ExpressionType.Lambda)
{
抛出新的NotSupportedException();
}
LambdaExpression lambda=(LambdaExpression)操作数;
//这是返回结果的“东西”
表达式body=lambda.body;
}
}

结尾处的
主体
应该是您想要的(或者可能是结尾前的
lambda
)。请注意代码块开头的注释。

使用您的方法,那么
body
在我的代码中是
thing.id==1
,而不是我希望的“单词”投影。@IngeHenriksen我只是在添加注释。。。查询
来自word in words,其中word.Length>0 select word
也没有select(因此您的显然没有)。。。如果您使用函数表示法,那么原因就很清楚了:
query.Where(word=>word.Length>0)
这里的
选择在哪里?没有@英格恩里克森是的。。。但问题是你不清楚你想要得到什么。。。例如:
query.Select(x=>new{Foo=x}).Where(x=>x.Foo.id==1).Select(x=>new{Bar=x.Foo}
这里有两个投影…你想要得到的就是complex@IngeHenriksen
query.Select(x=>new{Foo=x})。其中(x=>x.Foo.id==1)
这里的
Select
是“隐藏的”在
Where
后面,我看到了
method.Name==“Where”
。我如何“取消隐藏”选择?