【问题标题】:Getting projections from MethodCallExpression从 MethodCallExpression 获取预测
【发布时间】:2015-04-18 18:42:04
【问题描述】:

我有一个带有 select 的 Linq 查询,从我的 Linq 查询提供程序我得到一个包含 MethodCallExpression表达式树,但我怎样才能获得选择 projections 来自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;

【问题讨论】:

    标签: c# .net linq expression-trees


    【解决方案1】:

    不清楚你在做什么,但是

    // 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)。注意代码块开头的 cmets。

    【讨论】:

    • 使用您的方法,然后 body 在我的代码中是 thing.id == 1,而不是我希望的“单词”投影。
    • @IngeHenriksen 我只是在添加评论... 查询from word in words where word.Length &gt; 0 select word 也没有选择(所以显然不是你的)...如果你使用函数符号,很清楚为什么:query.Where(word =&gt; word.Length &gt; 0)Select 在哪里?没有!
    • @IngeHenriksen 是的...但问题是不清楚您想要获得什么...例如:query.Select(x =&gt; new { Foo = x }).Where(x =&gt; x.Foo.id == 1).Select(x =&gt; new { Bar = x.Foo } 这里有两个预测...无论您想要什么获取复杂
    • @IngeHenriksen query.Select(x =&gt; new { Foo = x }).Where(x =&gt; x.Foo.id == 1) 这里 Select 被“隐藏”在 Where 后面...
    • 我看到 method.Name == "Where" 在我的情况下。如何“取消隐藏”选择?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 2019-11-15
    • 2016-06-21
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    相关资源
    最近更新 更多