Extracting closure variable’s data from lambda expression in C#

Hi everyone! Today I want to talk about closures and extracting their values from lamda expression.

This article is the second version of the article in my blog. So, let’s get it started.

The problem

One of my project has a lot of Action and Func delegates as parameters for methods. It has them everywhere and I got a task to write some unit-tests for some of these methods. Let’s imagine that there is a method that take Actionlike a parameter.

The delegate can be initialized with lambda expression.

So, we call them in a way like in a snippet below.

Because I was writing unit-tests I had to get some values from Action for Asserts. But It tended to be a real problem, because I couldn’t use Expression, because of some historical reasons.

So, I decided to write a simple parser with using of Reflection.


Helper

I have created a library which contains a simple helper. You can find it on github. Also, you can install it by nuget.

Install-Package LambdaVariableExtractor

In the next sections of the article, I’ll tell and show you, how this helper works.


What I did

In this code, first of all we check lambda expression for existing and then do some magic. What is a DeclaringType in this context? For understanding this, we should take a short look on some parts of C# specification. As we all know, lambda expressions are just syntactic sugar.

7.15 Anonymous function expressions An anonymous function is an expression that represents an “in-line” method definition. An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression tree type. The evaluation of an anonymous function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method which the anonymous function defines.

In this context lambda is some kind of anonymous function. Let’s take a look on a few examples.

Here is the simple unit-test which contains lambda with closure.

The code below shows how compilator doing some job for us.

There is a class named the strange name <>c__DisplayClass0_0. And this is a class which was generated by compilator. Usually this class contains only your lambda as a method. But sometimes, when you have closures it starts to contain some variable. In example, you can see that there is closure variable there.

So, DeclaringType returns Type for this generated class. After that it’s easy to fetch fields of this class. And the last thing, if you want to get values from these fields you should pass Target as the parameter to the GetValue function.Target keeps reference to the object of the generated class and we need to pass it for right working of Reflection. In the example Targetkeeps reference to <>c__DisplayClass0 object.

Conclusion

That’s all. I’ll be happy, if this article helps you.

Like what you read? Give Egor Grishechko a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.