Вот контекст моего вопроса:
Распространенным методом является объявление параметра метода как лямбда-выражения, а не делегата. Это сделано для того, чтобы метод мог исследовать выражение, чтобы делать интересные вещи, например узнавать имена вызовов методов в теле экземпляра делегата.
Проблема в том, что вы теряете некоторые интеллектуальные функции Resharper. Если параметр метода был объявлен как делегат, Resharper поможет при записи вызова этого метода, предложив вам с синтаксисом x => x указать значение аргумента для этого метода.
Итак ... возвращаясь к своему вопросу, я хотел бы сделать следующее:
MethodThatTakesDelegate(s => s.Length);
}
private void MethodThatTakesDelegate(Func<string, object> func)
{
//convert func into expression
//Expression<Func<string, object>> expr = "code I need to write"
MethodThatTakesExpression(expr);
}
private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
//code here to determine the name of the property called against string (ie the Length)
}





Я не верю, что здесь можно добиться того, чего вы хотите. Из комментариев в вашем коде похоже, что вы пытаетесь зафиксировать имя свойства, которому было присвоено значение в MethodThatTakesExpression. Для этого требуется лямбда-выражение дерева выражений, которое фиксирует контекст доступа к свойству.
Когда вы передаете делегата в MethodThatTakesDelegate, этот контекст теряется. Делегаты хранят только адрес метода, но не контекст информации о методе. Как только это преобразование будет выполнено, его невозможно вернуть.
Пример того, почему это невозможно, состоит в том, что может даже не существовать именованный метод, поддерживающий делегат. ReflectionEmit можно использовать для создания метода, который не имеет никакого имени и существует только в памяти. Однако можно назначить это объекту Func.
Нет, это невозможно.
Везде, где вы используете термин «лямбда-выражение», вы на самом деле имеете в виду «дерево выражений».
Лямбда-выражение - это бит в исходном коде, который
parameters => code
например
x => x * 2
Деревья выражений - это экземпляры класса System.Linq.Expressions.Expression (или, скорее, одного из производных классов), которые представляют код как данные.
Лямбда-выражения преобразуются компилятором в деревья выражений либо (или, скорее, в код, который генерирует дерево выражений во время выполнения) экземпляры делегатов или же.
Вы можете скомпилировать экземпляр LambdaExpression (который является одним из подклассов Expression) в делегат, но вы не можете пойти другим путем.
Теоретически мощь можно написать такой «декомпилятор» на основе IL, возвращаемого MethodBase.GetMethodBody в ситуациях некоторый, но в настоящее время существуют различные делегаты, которые не могут быть представлены деревьями выражений. Дерево выражений представляет собой выражение, а не утверждение или блок операторов, поэтому нет циклов, ветвлений (кроме условных выражений), присваивания и т. д. Я считаю, что это может измениться в .NET 4.0, хотя я бы не ожидал шага декомпиляции от Microsoft, если только для этого есть действительно веская причина.
Я замалчивал эта запись в блоге, и, похоже, он просто выполняет прямое назначение. Разве это не сработает для вас?