Что я получу от UnaryExpression.Operand? - PullRequest
0 голосов
/ 27 января 2019

Я читаю код о том, как построить IQueryable Provider

Ниже приведен фрагмент кода

internal class QueryTranslator : ExpressionVisitor
    {
        .....
        private static Expression StripQuotes(Expression e)
        {
            while (e.NodeType == ExpressionType.Quote)
            {
                e = ((UnaryExpression)e).Operand;
            }
            return e;
        }
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable))
            {
                if (m.Method.Name == "Where")
                {
                    sb.Append("SELECT * FROM (");
                    this.Visit(m.Arguments[0]);
                    sb.Append(") AS T WHERE ");
                    LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
                    this.Visit(lambda.Body);
                    return m;
                }
                else if (m.Method.Name == "Select")
                {
                    LambdaExpression lambda = (LambdaExpression)StripQuotes(m.Arguments[1]);
                    ColumnProjection projection = new ColumnProjector().ProjectColumns(lambda.Body, this.row);
                    sb.Append("SELECT ");
                    sb.Append(projection.Columns);
                    sb.Append(" FROM (");
                    this.Visit(m.Arguments[0]);
                    sb.Append(") AS T ");
                    this.projection = projection;
                    return m;
                }
            }
            throw new NotSupportedException(string.Format("The method '{0}' is not supported", m.Method.Name));
        }
        .....
    }

Я не могу понять метод StripQuotes, что яполучить от e = ((UnaryExpression) e). Операнд?

1 Ответ

0 голосов
/ 27 января 2019

Что делает Expression.Quote (), что Expression.Constant () уже не может сделать? объясняет, что делает Quote.

Теперь вопрос в том, когда будет Quote Операция может быть обнаружена в реальном сценарии поставщиком LINQ.Появляется, когда вы вызываете IQueryable операции, которые принимают деревья выражений в качестве аргументов.Например, bool Queryable.Where(IQueryable inputQuery, Expression<Func<..., bool>> predicate) принимает дерево выражений.

Если вы скажете myQueryable.Where(x => ...), компилятор C # сгенерирует Expression.* вызовов для построения этого дерева выражений и передачи его в Where.Нет Quote здесь.

Но если генерация дерева выражений вложенная , то используется Quote:

myQueryable.Where(x => x.SomeCollection.Any(y => ...))

Здесь часть y => ...типа Expression<..., bool>.Это требует Quote.

Я полагаю, что простой поставщик LINQ может просто развернуть / выбросить Quote и сгенерировать код, как если бы он не существовал.Если вы хотите быть полностью правым, вам потребуется специальная обработка этого случая в поставщике LINQ.Код поставщика LINQ в вопросе имеет качество «демо-кода», поэтому он этого не делает.

Вы можете использовать https://sharplab.io/, чтобы играть с различными типами запросов, чтобы увидеть, что генерирует компилятор.Например,

using System;
using System.Linq;

public class C {
    public void M2() {
        var query =
            new SomeClass[0]
            .AsQueryable()
            .Where(x => x.SomeCollection.Any(y => y % 2 == 0));
    }
    static bool F(System.Linq.Expressions.Expression<Func<int, bool>> e) { return true; }

    class SomeClass {
        public IQueryable<int> SomeCollection { get; set; }
    }
}

https://sharplab.io/#v2:CYLg1APgAgDABFAjAbgLAChYMQOgDICWAdgI5roZQDMCATHAMJwDeGc7CNUALHALK0AFAEoWbDhIBuAQwBOcEgFcAprICecALziJuuEWUB3OAGUA9gFtlDADbSAzvYDaMALo69HHAEF7ARRV1aQAjG2URD084HAB1AAtVcIAPLQA+OCSccysGMxswgGMAFwIzIh8iNUENTXSNAFI4ek1NOBhhYXIJAF8PJAA2OGCzPLgAMUEkfGISHABRJIAHWWVHUqJ7eaWVtbKAHigAVj3iIoAaIZGbVPTlUWYEAHY4ItkVZDhe9Ak++mzrOyOMTfTzUOAASQCqjUITCJyIRXS/1y+WUxXWLDgAHNlEUPvZcR8vj0MF8gA

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...