Рефакторинг Func <T> в Выражение <Func <T>>

С lamba выражениями и инициализаторами класса можно получить то же поведение с небольшим количеством усилия.

public class Example {
    public Action DoStuff;
    public Action<int> DoStuffWithParameter;
    public Func<int> DoStuffWithReturnValue;
}

class Program {
    static void Main(string[] args) {
        var x = new Example() {
            DoStuff = () => {
                Console.WriteLine("Did Stuff");
            },
            DoStuffWithParameter = (p) => {
                Console.WriteLine("Did Stuff with parameter " + p);
            },
            DoStuffWithReturnValue = () => { return 99; }


        };

        x.DoStuff();
        x.DoStuffWithParameter(10);
        int value = x.DoStuffWithReturnValue();
        Console.WriteLine("Return value " + value);
        Console.ReadLine();
    }
}

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

Однако нет никакой причины, что Вы не могли передать экземпляр Примера к лямбда-выражениям, которые предоставят им доступ к любому общедоступному состоянию, которое мог бы содержать пример. AFAIK, который был бы функционально эквивалентен Java Анонимный Внутренний Класс.

P.S., Если Вы собираетесь провалить ответ, сделайте нас всех польза и добавьте комментарий относительно того, почему Вы не соглашаетесь :-)

5
задан Ecyrb 20 October 2009 в 17:02
поделиться

2 ответа

Невозможно объединить дерево выражений, представленное как объект Expression , в середину «литерал дерева», представленный лямбда-выражением. Вам нужно будет построить дерево выражений для перехода к GroupBy вручную:

// Need an explicitly named type to reference in typeof()
private class ResultType
{
     public string SubcategoryName { get; set; }
     public int ProductNumber { get; set; }|
}

private static void DoSomethingWithExpression(
    Expression<Func<Product,
    string>> myExpression)
{
    var productParam = Expression.Parameter(typeof(Product), "product");
    var groupExpr = (Expression<Func<Product, ResultType>>)Expression.Lambda(
        Expression.MemberInit(
           Expression.New(typeof(ResultType)),
           Expression.Bind(
               typeof(ResultType).GetProperty("SubcategoryName"),
               Expression.Invoke(myExpression, productParam)),
           Expression.Bind(
               typeof(ResultType).GetProperty("ProductNumber"),
               Expression.Property(productParam, "ProductNumber"))),
        productParam);
    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(groupExpr);
    }
}
4
ответ дан 14 December 2019 в 08:54
поделиться

Если подумать, компиляция выражения не сработает.

Вам нужно будет собрать свой Выражение GroupBy вручную, что означает, что вы не можете использовать анонимный тип. Я бы предложил построить остальную часть вашего выражения, а затем декомпилировать, чтобы увидеть сгенерированное дерево выражений. Конечный результат будет выглядеть примерно так, если использовать соответствующие части myExpression :

private static void DoSomethingWithExpression(Expression<Func<Product, string>> myExpression)
{
    var productParam = myExpression.Parameters[0];

    ConstructorInfo constructor = ...; // Get c'tor for return type

    var keySelector = Expression.Lambda(
                          Expression.New(constructor,
                              new Expression[] {
                                  productParam.Body,
                                  ... // Expressions to init other members
                              },
                              new MethodInfo[] { ... }), // Setters for your members
                          new [] { productParam });

    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(keySelector);

        // ...
    }
}
3
ответ дан 14 December 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: