Это действительно возможно, но это зависит от того, что вы передаете в этот метод. Предположим, у вас есть сценарий, в котором вы передаете метод экземпляра класса, в котором вы находитесь, ProcessCommand
:
public class TestClass
{
public void TestMethod()
{
ProcessCommand(() => MethodToCall());
}
public bool MethodToCall() { return true; }
void ProcessCommand(Expression<Func<bool>> expression) { ... }
}
Тогда вы можете использовать следующий метод ProcessCommand
. Это работает только потому, что MethodToCall
вызывается в этом экземпляре.
void ProcessCommand(Expression<Func<bool>> expression)
{
var lambda = (LambdaExpression) expression;
var methodCall = (MethodCallExpression) lambda.Body;
var constant = (ConstantExpression) methodCall.Object;
var myObject = constant.Value;
}
Более сложный сценарий выглядит следующим образом:
public class CallingClass
{
public void TestMethod()
{
var calledClass = new CalledClass();
ProcessCommand(() => calledClass.MethodToCall());
}
void ProcessCommand(Expression<Func<bool>> expression) { ... }
}
public class CalledClass
{
public bool MethodToCall() { return true; }
}
Метод, который мы вызываем, теперь находится в другом классе и вызывается не в этом экземпляре, а в экземпляре CalledClass
с именем calledClass
. Но как компилятор передает переменную calledClass
в лямбда-выражение? Нет ничего, что определяло бы поле calledClass
, к которому может быть вызван метод MethodToCall
.
Компилятор решает эту проблему, генерируя внутренний класс с одним полем с именем calledClass
. В результате метод ProcessCommand
теперь становится таким:
public void ProcessCommand(Expression<Func<bool>> expression)
{
// The expression is a lambda expression with a method call body.
var lambda = (LambdaExpression) expression;
var methodCall = (MethodCallExpression) lambda.Body;
// The method is called on a member of some instance.
var member = (MemberExpression) methodCall.Object;
// The member expression contains an instance of the anonymous class that
// defines the member...
var constant = (ConstantExpression) member.Expression;
var anonymousClassInstance = constant.Value;
// ...and the member itself.
var calledClassField = (FieldInfo) member.Member;
// With an instance of the anonymous class and the field, we can get its value.
var calledClass =
(CalledClass) calledClassField.GetValue(anonymousClassInstance);
}
Немного сложнее, потому что компилятор должен генерировать анонимный внутренний класс.