Практическое использование деревьев выражений

Деревья выражений - полезная функция, но каково ее практическое применение? Могут ли они использоваться для генерации кода, метапрограммирования или чего-то подобного?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
70
1
26 153
7

Ответы 7

Вы можете использовать их для создания собственного поставщика linq для веб-сайта, такого как Google, Flickr или Amazon, вашего собственного веб-сайта или другого поставщика данных.

Марк Гравелл использовал их с большим эффектом в MiscUtil для реализации общие операторы.

Черт побери меня к этому ;-p

Marc Gravell 31.12.2008 18:33

Реализация поставщиков LINQ в основном выполняется путем обработки деревьев выражений. Я также использую их для удаления буквальных строк из моего кода:

Как отмечает Джон, я использую их для предоставления общие операторы в .NET 3.5. Я также использую их (снова в MiscUtil) для обеспечения быстрого доступа к конструкторам, отличным от стандартных (вы не можете использовать Delegate.CreateDelegate с конструкторами, но Expression работает нормально).

Другое использование созданных вручную деревьев выражений:

Но на самом деле Expression - это очень универсальный способ написания любого динамического кода. Намного проще, чем Reflection.Emit, и, за мои деньги, проще для понимания, чем CodeDOM. А в .NET 4.0 у вас есть еще больше возможностей. Я показываю основы написания кода через Expressionв моем блоге.

Спасибо. блог не появляется !!!

pixparker 02.01.2016 19:08

@pixparker Я только что проверил: работает нормально

Marc Gravell 03.01.2016 02:44

Я использую их для создания динамических запросов, будь то сортировка или фильтрация данных. В качестве примера:

IQueryable<Data.Task> query = ctx.DataContext.Tasks;

if (criteria.ProjectId != Guid.Empty)
      query = query.Where(row => row.ProjectId == criteria.ProjectId);

if (criteria.Status != TaskStatus.NotSet)
      query = query.Where(row => row.Status == (int)criteria.Status);

if (criteria.DueDate.DateFrom != DateTime.MinValue)
      query = query.Where(row => row.DueDate >= criteria.DueDate.DateFrom);

if (criteria.DueDate.DateTo != DateTime.MaxValue)
     query = query.Where(row => row.DueDate <= criteria.DueDate.DateTo);

if (criteria.OpenDate.DateFrom != DateTime.MinValue)
     query = query.Where(row => row.OpenDate >= criteria.OpenDate.DateFrom);

var data = query.Select(row => TaskInfo.FetchTaskInfo(row));

Первоначально Джомо Фишер, Густаво Герра опубликовал исправленную версию статический строковый словарь.

Где через деревья выражений, динамическое выражение, которое предоставляет действительно (читай: смехотворно) Словарь.

Реализация создает динамическое дерево решений, которое выбирает соответствующее значение в соответствии с длиной входной строки, затем по первой букве, затем по второй букве и так далее.

В конечном итоге это работает намного быстрее, чем эквивалентный словарь.

Я только что создал общую функцию фильтра, используя дерево выражений, которым хочу поделиться с вами, ребята ...

Начинать

var allFiltered= Filter(AllCustomer, "Name", "Moumit");

public static List<T> Filter<T>(this List<T> Filterable, string PropertyName, object ParameterValue)
{
    ConstantExpression c = Expression.Constant(ParameterValue);
    ParameterExpression p = Expression.Parameter(typeof(T), "xx");
    MemberExpression m = Expression.PropertyOrField(p, PropertyName);
    var Lambda = Expression.Lambda<Func<T, Boolean>>(Expression.Equal(c, m), new[] { p });
    Func<T, Boolean> func = Lambda.Compile();
    return Filterable.Where(func).ToList();
}

Еще один

string singlePropertyName=GetPropertyName((Property.Customer p) => p.Name);

public static string GetPropertyName<T, U>(Expression<Func<T, U>> expression)
{
        MemberExpression body = expression.Body as MemberExpression;
        // if expression is not a member expression
        if (body == null)
        {
            UnaryExpression ubody = (UnaryExpression)expression.Body;
            body = ubody.Operand as MemberExpression;
        }
        return string.Join(".", body.ToString().Split('.').Skip(1));
}

Сделайте его более расширяемым

string multiCommaSeparatedPropertyNames=GetMultiplePropertyName<Property.Customer>(c => c.CustomerId, c => c.AuthorizationStatus)

public static string GetMultiplePropertyName<T>(params Expression<Func<T, object>>[] expressions)
{
        string[] propertyNames = new string[expressions.Count()];
        for (int i = 0; i < propertyNames.Length; i++)
        {
            propertyNames[i] = GetPropertyName(expressions[i]);
        }

        return propertyNames.Join();
}

Я знаю, что это также можно сделать с помощью отражения, но это очень быстро или, я могу сказать, эквивалентно лямбде после первой компиляции. Самая первая итерация занимает в среднем 10 миллисекунд. Итак, это магия Дерева выражений. Просто и фантастично (я думаю)!

Хороший! Спасибо за примеры.

Kiran Challa 19.09.2016 16:52

Может быть, я неправильно это читаю, но работает ли GetPropertyName только для свойств первого порядка? Найдет ли он имя Baz, если я дам ему GetPropertyName ((Foo f) => f.Bar.Baz); ?

Josh Gust 25.06.2018 20:09

@JoshGust .. Думаю, да ... вы получите Bar.Baz как string

Moumit 26.06.2018 13:48

@Moumit, в таком случае простое изменение string.Join(".", body.Split('.').Last() поможет, не так ли?

Josh Gust 26.06.2018 17:54

@JoshGust ... это пример ... вы можете настроить в соответствии с вашими потребностями ....

Moumit 27.06.2018 12:20

Другие вопросы по теме