I know I can iterate through all locally defined variables in a method using MethodInfo.GetMethodBody().LocalVariables.
But if I define a method as:
public static void somemethod( int someint )
{
int test = 1;
HM.M(() =>
{
test = 2;
});
}
The anonymous method can access someint and test as closures, but GetMethodBody().LocalVariables will be empty.
Is there a way to use reflection to detect the closures?
Well, I found the answer. A closure in c# is implemented by the compiler with a compiler-generated class. The compiler generates a class where it copies all variables that will be accessible in the method, and the method itself is encapsulated in this class. The external variables values are copied to the class.
So, in my example above, the M method has the signature:
public void M( Action method )
The steps to get the list of closures are:
MethodInfo mi = method.Method;
FieldInfo[] fields = mi.DeclaringType.GetFields
(
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.Static
);
DeclaringType will be the compiler-generated class used to implement the closures.
In the fields array all closures will be listed.
To get the VALUES of the closures is another story, but it is not part of this question.
EDIT: As pointed out by @leppie, get the values is easy:
object res = fields[ 0 ].GetValue( method.Target );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With