Обратное выражение ‹Func‹ T, TResult ››. Compile ()?

Поскольку мы можем:

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. Является ли это возможным?


person Cheng Chen    schedule 28.09.2010    source источник
comment
Нет, это невозможно. Компилятору не передается конструкция выражения. Здесь нет алхимии.   -  person leppie    schedule 28.09.2010
comment
возможный дубликат преобразования .net Func ‹T› в .net Expression ‹Func ‹T››   -  person nawfal    schedule 08.08.2014


Ответы (4)


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

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

Func<string,int> parse = int.Parse;
person Marc Gravell    schedule 28.09.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.

person Nathan Baulch    schedule 28.09.2010
comment
Нет. Если вы передадите x=>x>5 Decompile, он передаст Expression. Я хочу декомпилировать Func<int,bool>, не зная его содержимого. - person Cheng Chen; 28.09.2010
comment
Как сказал Марк, это невозможно. Я просто подумал, что выложу пример самого близкого к декомпиляции. - person Nathan Baulch; 28.09.2010
comment
Да, я знал, что вы публикуете самый близкий пример, когда увидел ваш ответ. Но кто-то так не считает, и он голосует против :( - person Cheng Chen; 28.09.2010

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

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

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

person Andrey Shchekin    schedule 01.06.2011
comment
Здорово. Я попытаюсь. Большое спасибо. - person Cheng Chen; 02.06.2011

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

Func<int, bool> predicate = x => x > 5;
Expression<Func<int, bool>> exp = x => predicate(x);
person Timwi    schedule 26.02.2011