Обратное выражение <Func <T, TResult >>. Compile ()? - PullRequest
8 голосов
/ 28 сентября 2010

Так как мы можем:

Expression<Func<int, bool>> predicate = x => x > 5;
var result = Enumerable.Range(0,10).Where(predicate.Compile());

Как я могу:

Func<int,bool> predicate = x => x > 5;
Expression<Func<int,bool>> exp = predicate.Decompile();

То есть я хочу получить Expression из Func. Возможно ли это?

Ответы [ 4 ]

7 голосов
/ 28 сентября 2010

Нет волшебства Decompile() для экземпляра делегата , за исключением деконструкции IL (возможно, с помощью mono.cecil).Если вам нужно дерево выражений, вам нужно начать с дерева выражений, поэтому Expression<Func<int, bool>> througout.

В качестве крайнего случая вы можете получить basic *Метод 1010 * делегирует информацию из делегатов .Method (MethodInfo) и .Target (arg0) - однако, для большинства сценариев, включающих лямбда или анонимный метод, это будет указывать на метод генерирования компиляторомзахватить класс, так что не очень вам поможет.Это в значительной степени ограничено сценариями, такими как:

Func<string,int> parse = int.Parse;
5 голосов
/ 28 сентября 2010

Передайте лямбду методу, который принимает выражение Expression <> , и компилятор C # передаст вам дерево выражений во время выполнения. Однако это работает только при прямой передаче лямбды, а не при попытке передать экземпляр делегата, созданный из лямбды.

var exp = Decompile(x => x > 5);

public Expression<Func<int, bool>> Decompile(Expression<Func<int, bool>> exp)
{
    return exp;
}

Ближайший вариант, который я нашел для декомпиляции экземпляра делегата, подробно описан в этом блоге от Жана-Батиста Эвена, который работает в команде Mono . Он использует превосходный проект Mono.Cecil для декомпиляции IL в пользовательский AST, а затем максимально точно отображает его в выражениях LINQ.

3 голосов
/ 01 июня 2011

Вы можете попробовать использовать мою библиотеку:
https://github.com/ashmind/expressive

Хотя она может не работать как есть для результатов Compile(), так как это DynamicMethod и получение IL этого значенияне просто.Однако если вы реализуете собственную реализацию IManagedMethod для DynamicMethod, она должна просто работать.

Я планирую внедрить DynamicMethod адаптеры, но пока не знаю, когда.

1 голос
/ 26 февраля 2011

Вы не можете декомпилировать делегат, но вы, безусловно, можете создать новое дерево выражений, которое просто вызывает делегат:

Func<int, bool> predicate = x => x > 5;
Expression<Func<int, bool>> exp = x => predicate(x);
...