Подтвердить что ты не робот

Какой хороший вариант использования для .net 4.0 Expression Trees?

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

Теперь я знаю, что эти концепции, как правило, становятся намного легче, когда вы получаете некоторые хорошие практические причины.

На данный момент кажется, что его единственная цель - позволить вам написать поставщика Linq?

Это что? Есть ли другие преимущества для этого?

4b9b3361

Ответ 1

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

Деревья выражений позволяют делать то же самое с кодом. Например, вы можете ввести свой пользовательский ввод (флажки, диапазоны номеров и т.д.) И перевести его в дерево выражений. Это дерево выражений может быть выполнено или сохранено для последующего использования. Очень круто.

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

Здесь немного кода MSDN для сериализации деревьев выражений (http://code.msdn.microsoft.com/exprserialization), которые должны генерировать идеи.

Ответ 2

Вы можете использовать деревья выражений для преобразования языка домена в исполняемый код.

Ответ 3

Решение, ищущее проблему eh?

Деревья выражений позволяют представить код как преобразуемую структуру данных, поэтому они идеально подходят для преобразования между языками Linq To SQL, являющимся наиболее мощным в настоящее время.

Другое использование, помимо DSL (которое является преобразованием), - это распараллеливание (которое разделяется), а пример в этом пространстве - PLINQ.

Ответ 4

.NET 4.0 Деревья выражений также являются основой для DLR AST

Ответ 5

Быстрый ответ: "Нет, это не только для поставщиков LINQ сейчас". Во-первых, деревья выражений были расширены динамическим языком для поддержки динамических языков. В принципе, если вы хотите портировать свой собственный динамический язык на .NET(например, IronPython и IronRuby), вам придется использовать деревья выражений. Хорошо, не так много людей имеют свои языки. Каковы другие варианты использования? Один из них - генерировать динамический код во время выполнения. У меня есть пример: Создание динамических методов с деревьями выражений в Visual Studio 2010. В нем объясняется, как использовать ET вместо генерации MSIL для создания динамических методов. На самом деле, существуют некоторые примеры использования деревьев выражений вне LINQ даже в .NET 3.5, но эти записи еще не записаны.

Ответ 6

У меня был хороший опыт с тем, чтобы преобразовать АСТ в доменные имена в деревья выражений. Это также довольно легко с помощью ANTLR адаптера дерева для создания дерева выражений непосредственно из грамматики.

Ответ 8

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

[TestClass]
public class WhenINeedToAccessPropertiesByNameHavingATypeReference
{
    public class SomeCategoryData
    {
        public DateTime CreatedDate { get; set; }
    }

    [TestMethod]
    public void ICanDoThatWithAnExpressionAndItPerformsWell()
    {
        // INIT

        var someCategoryData =
            Enumerable.Range(1970, 100).Select(year =>
                new SomeCategoryData { CreatedDate = new DateTime(year, 1, 1) }).Cast<object>();
        var t = typeof(SomeCategoryData); // or it can be: t = someCategoryData.First().GetType();
        var compiled = Stopwatch.StartNew();

        // ACT

        var filter = AccessPropertyByNameInCompiledMannerSomehow(t, "CreatedDate");

        // ASSERT

        Trace.WriteLine(string.Format("compiled in: {0}", compiled.Elapsed));
        Assert.IsTrue(compiled.ElapsedMilliseconds < 3, "compiles fast enough");

        var executed = Stopwatch.StartNew();

        // ACT
        List<object> result = null;
        for (var i = 0; i < 10000; i++)
        {
            result = someCategoryData.Where(d => filter(d, new DateTime(2000, 1, 1), new DateTime(2009, 1, 1)))
                .ToList();
        }
        executed.Stop();
        Trace.WriteLine(string.Format("executed in: {0}", executed.Elapsed));

        // ASSERT
        Assert.AreEqual(10, result.Count, "insure compiled code actually works");
        Assert.IsTrue(executed.ElapsedMilliseconds < 300, "runs fast enough");
    }

    private static Func<object, DateTime, DateTime, bool>
        AccessPropertyByNameInCompiledMannerSomehow(Type t, string fieldToFilterBy)
    {
        var objectParameter = Expression.Parameter(typeof(object), "p");
        var instance = Expression.Convert(objectParameter, t);
        var lower = Expression.Parameter(typeof(DateTime), "l");
        var upper = Expression.Parameter(typeof(DateTime), "u");

        var composite = Expression.Lambda<Func<object, DateTime, DateTime, bool>>(
            Expression.And(
                Expression.LessThanOrEqual(
                    lower,
                    Expression.PropertyOrField(instance, fieldToFilterBy)
                    ),
                Expression.GreaterThanOrEqual(
                    upper,
                    Expression.PropertyOrField(instance, fieldToFilterBy)
                    )
                ), objectParameter, lower, upper
            );

        return composite.Compile();
    }
}

Ответ 9

У меня есть несколько примеров здесь

(извините за форматирование разбитого кода)