I know many people get upset at the very idea of Extension Methods, but I already consider them to be an indispensable part of my programming toolkit. I’m seeing so many times where a quick extension method can make code be much more readable. Other times an extension method against even a core BCL type seems to fill in a natural hole in the official API’s and knocks out a lot of duplication.
Example 1: Custom Attributes
I do a lot of work with reflection in both StructureMap and my normal development. Using custom attributes has always been an important extension point in .Net frameworks, but the code to access attributes is awkward – until Extension Methods. I’ll bet you anything that at least a dozen other people reading this have written something exactly like this:
so that you can access attributes like:
and work with the attribute objects without all the icky casting and the goofy GetCustomAttributes business.
Example 2: Writing Xml
Here’s another example for Xml manipulation from what became Fluent NHibernate:
Programmatically building XmlDocument objects has always been tedious because of all the repetitious steps (create element, append element to its parent, set some attributes, rinse, repeat…) and the verbose API. I found that a few extension methods shrank that code down into things like this:
With the old Xml “push button API” this is about 6-7 lines of code.
Example 3: Reading and Working from Xml
Here’s one last example. When StructureMap loads an Xml configuration file, it will will allow you to “include” additional Xml files by specifying the files in an <Include> tag like this:
In StructureMap 2.0 the code that acted on the <Instance> nodes looked like this:
Old .Net 2.0-ish Code
Earlier this year I did a massive overhaul of the StructureMap core and used some .Net 3.5 language features to do this:
New .Net 3.5 Code
First, I wanted to separate the Xml manipulation code away from the code that locates and loads the additional Xml files. I wrote an extension method against XmlNode (plus a little bit of a Fluent Interface) like this:
That’s a lot more code for Xml manipulation than the original sample, but the great thing is that I can reuse this code up above in other scenarios.
This extension method on XmlNode enabled me to write code that made working with the Xml data become almost declarative. Instead of doing monotonous code to walk the Xml DOM and yank out the right nodes and attributes, I just say “do this thing (an Action<string> lambda) with each value of this attribute in every child node named ‘Include.’”
But wait, extension methods aren’t discoverable! I’ll concede this one a little bit. ReSharper has nice functionality to bring up extension methods with the CTRL-ALT-SPACE keyboard shortcut, and CTRL-B still works. I think that this yet another example of how ReSharper (or the equivalent) usage radically changes the rules for programming.