Ответ 1
Это действительно возможно, но это зависит от того, что вы передаете в этот метод. Предположим, у вас есть сценарий, в котором вы передаете метод экземпляра класса, в котором вы находитесь, в 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);
}
Немного сложнее, потому что компилятор должен создать анонимный внутренний класс.