The code part II: EventTester with expression trees

The first post of this series gave a quick overview over the event tester usage, the last post gave a deep dive into some part of the event tester code. When talking about line numbers or certain code expression I’m always referring to the code provided in the last post.

When talking about the expression tree construction in the last post the last thing we got into was the build up of the if/then/else expression. After building up the if/then/else expression we need to build the expression code which calls the if/then/else expression by passing in the parameter array which we built up with the GetParameterExpressionsFor method.

The easiest approach can be achieved by building up a lambda expression after the following pseudo code:

(sender, eventargs) => {
	if(matcher(sender, eventargs))
	{
	   // Fire event handler delegate and increment fire counter
	}
	else
	{
	   // Do nothing
	}
}

To construct expression trees like the pseudo code above we only need to call the static method Expression.Lambda passing in the parameter array and the if/then/else expression as shown in method GetLambdaExpression.

Before we can attach the lambda expression built up with the expression tree we need to dynamically expose a delegate which matches the event handler type we reflected upon. The purpose of this delegate is the invocation of the lambda expression constructed with the expression tree. This is done in the method GetDynamicEventHandler.

GetDynamicEventHandler creates according to the event handler type a delegate. By calling lambdaExpression.Compile() the expression tree is compiled into executable code.The third parameter of  Delegate.CreateDelegate specifies the name of the instance method the delegate is to represent. Therefore when the dynamic delegate is executed the invoke method of the lambda expression is executed.

Finally when the EventAttachBehavior is set to AutoAttach the dynamically created event handler is added to the reflected event information.

The last part to discuss are the two static implicit operators which allow to auto convert EventTester to either EventHandler types or generic event handler types of EventHandler<TEventArgs>. This offers us the possibility to place the event tester object at the right side of the event add such as

    var eventTester = new EventTester<EventArgs>(testee, "Started");
    testee.Started += eventTester;

Have fun playing around with expression trees!

About the author

Daniel Marbach

2 comments

  • With some additional “expression tree”-ing you could as well get rid of the string “Started”, a syntax like in Moq:

    new EventTester(testee, t => t.Started += null)

    This would be a bit more refactoring friendly.

  • I thought about that too. But I didn’t like the fact that you have to assign null as event handler in order to be able to produce valid code that compiles. But for sure a good idea. Enhancement is left as an exercise to the reader 😉

By Daniel Marbach

Recent Posts