First a little background: The idea of what is going on here is to take a collection of objects that implement an interface. This interface defines generic attributes about the appearance of the object. Because not all objects support all of the possible appearance options its necessary to have both a property for the appearance and a boolean “Supports” property to indicate whether the first property is usable.
For example, if I have a TextBox and an Image control. Both implement this interface, and certain properties apply to both controls (f.e. Size and BackColor) however there are certain properties that could only apply to some of the controls (f.e. ForeColor on the TextBox and ImageSizing on the Image).
What the code I’m writing needs to do is, first determine whether the object in the collection supports the property being get/set, and if it does support it get/set it. When I was writing the code for this, it became obvious that the only things changing between any two sets of properties was just the name of the property. This made it a prime candidate in my mind for refactoring, but how?
It’s clear that the method needs to accept 2 delegates, the first is a delegate which returns a boolean and takes in the object in the collection (a
Predicate<T> in .NET 2.0+). The second is one to do the actual property setting on the object in the collection (an
Action<T> in .NET 2.0+).
If I were writing .NET 1.x, I’d have to create a method for each of the properties so I could create a delegate to them, or use reflection…I’m not sure which is worse there. Beginning with .NET 2.0 I could create anonymous methods, but that’s almost as much typing as the .NET 1.x way.
Thankfully I’m using .NET 3.5 for this project, so I can make use of lambda expressions. The result of calling the methods looks like so:
SetAggregateValue( p => p.SupportsForeColor, p => p.ForeColor = value );
As I mentioned before, this allows me to make use of the two delegates, the first a predicate; the second the action. In the corresponding get method, the compiler even takes care of inferring the return type so I don’t need to deal with typing it out, yet again.
A slight concern I have is that it isn’t readily apparent while reading the code that the first parameter is a predicate. Fortunately, this is just a research project and since we target .NET 2.0; I know there no chance this code will make it into the real code base 🙂
Just an observation at 3am 🙂