преобразование .net Func <T> к .net Expression <Func <T>>

Для простоты вы можете встроить их в горизонтальное UIStackview и установить

self.rightlb.isHidden = true

, и оно автоматически исчезнет без ширины, также в вашем текущем коде убедитесь, что

tableCell?.layoutIfNeeded()

после изменения ограничений

113
задан Dave Cameron 8 November 2017 в 21:11
поделиться

5 ответов

Ох, это совсем не просто. Func представляет общий делегат , а не выражение. Если есть какой-либо способ сделать это (из-за оптимизаций и других действий, выполняемых компилятором, некоторые данные могут быть выброшены, поэтому может оказаться невозможным вернуть исходное выражение), это будет разборка IL на лету и вывод выражения (что ни в коем случае не легко). Обработка лямбда-выражений как данных ( Expression > ) - это магия, совершаемая компилятором (в основном компилятор создает дерево выражений в коде вместо компиляции в IL)

Связанный факт

Вот почему языки, которые толкают лямбды до крайности (например, Лисп), часто проще реализовать как интерпретаторы . В этих языках код и данные по сути одно и то же (даже во время выполнения ), но наш чип не может понять эту форму кода, поэтому мы должны эмулировать такую ​​машину, создавая интерпретатор поверх тот, кто понимает это (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно соответствовать данным) в некоторой степени (выбор, сделанный C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбда-символы как код ( Func ) и данные ( ] Выражение > ) во время компиляции .

таким образом, мы должны эмулировать такую ​​машину, создавая интерпретатор поверх нее, который понимает ее (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно соответствовать данным) в некоторой степени (выбор сделан по C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбда-символы как код ( Func ) и данные ( ] Выражение > ) во время компиляции .

таким образом, мы должны эмулировать такую ​​машину, создавая поверх нее интерпретатор, который понимает ее (выбор, сделанный Lisp-подобными языками) или жертвуя силой (код больше не будет точно равен данным) в некоторой степени (выбор сделан по C #). В C # компилятор создает иллюзию обработки кода как данных, позволяя интерпретировать лямбда-символы как код ( Func ) и данные ( ] Выражение > ) во время компиляции .

99
ответ дан 24 November 2019 в 02:43
поделиться

Вы можете пойти другим путем через метод .Compile (), однако - не уверен, что это полезно для вас:

public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
    try
    {
        var expr = dangerousCall.Compile();
        expr.Invoke();
    }
    catch (Exception e)
    {
        Expression<Func<T>> DangerousExpression = dangerousCall;
        var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
        throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    var thing = new Thing();
    ContainTheDanger(() => thing.CrossTheStreams());
}
7
ответ дан 24 November 2019 в 02:43
поделиться

Что вы, вероятно, должны сделать, это перевернуть метод. Возьмите Expression>, и скомпилируйте и запустите. Если это не помогло, у вас уже есть выражение, на которое вы можете посмотреть.

public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
    try 
    {
        dangerousCall().Compile().Invoke();;
    }
    catch (Exception e)
    {
        // This next line does not work...
        var nameOfDanger = 
            ((MemberExpression)dangerousCall.Body).Member.Name;
        throw new DangerContainer(
            "Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    ContainTheDanger(() => thing.CrossTheStreams());
}

Очевидно, что вам нужно учесть последствия этого для производительности и определить, действительно ли это то, что вам действительно нужно сделать.

21
ответ дан 24 November 2019 в 02:43
поделиться

Если вам иногда нужно выражение, а иногда делегат, у вас есть 2 варианта:

  • имеют разные методы ( 1 для каждого)
  • всегда принимают версию Expression <...> и просто .Compile (). Invoke (...) , если вы хотите делегата. Очевидно, что это дорого.
6
ответ дан 24 November 2019 в 02:43
поделиться

JB Evain из команды Cecil Mono делает некоторые успехи, чтобы включить это

http://evain.net/blog/articles/2009/04/22/converting-delegates-to -expression-trees

3
ответ дан 24 November 2019 в 02:43
поделиться
Другие вопросы по тегам:

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