Skip to main content

Posts tagged with 'Cecil'

Intro to Fireweaver

March 28, 2012 mgroves 0 Comments
Tags: FireWeaver Cecil

I've been trying on and off to figure out Mono.Cecil, and so far it's not very encouraging. It's a bit above my pay grade, it seems.

But all is not lost: I came across a tool while browsing NuGet called FireWeaver. It sits on top of Mono.Cecil, which means it does its work after compilation. It provides you with a way to replace a class with an entire other class. So it's not exactly intercepting or proxying classes, the way other AOP frameworks do: it flat out replaces it and is "essentially duct typing(sic) the entire object definition". I don't know if that's supposed to be "duct taping" or "duck typing", but I rather like the term "duct typing".

Here's a quick example of how it works, taken from the FireWeaver CodePlex site. First, I added FireWeaver with NuGet. Then I created a console app like this:

Compile and run as normal and here's the output:

Before FireWeaver

Next, run the FireWeaver.Bootstrapper.exe tool against your assembly/assemblies. In my case, my Replace class is in the same assembly as the class it's replacing, so my arguments are identical, but you could certainly specify another assembly as the second argument:

And here's the output of the console app after I ran FireWeaver.

After FireWeaver

And here's what the assemblies look like (decompiled) before and after FireWeaver. Warning, your head may explode:

JustDecompile before and after

I'm just as confused about Cecil looking at these JustDecompile screenshots as I was before. But I assure you, it does work.

There's definitely some potential here, since this is a pretty easy tool to use, and integrating FireWeaver into your build script(s) shouldn't be too difficult if you don't want to hit the command line after every build. And it almost looks like pure duck typing brought to C#.

But this could also lead to some really wild code if you aren't careful with it. "Dogs and cats living together, mass hysteria" code.

One of the problems with object-oriented programming that AOP aims to solve is excessive boilerplate. And there's no more stark example of excessive boilerplate than the use of INotifyPropertyChanged.

NotifyPropertyWeaver is a tool that adds an MSBuild task to your project. It will find all your implementations of INotifyPropertyChanged and rewrite the properties to do all the notification code for you. So you don't have to worry about mistyping that property name string, and you don't have to worry about refactoring when you rename or remove properties.

In this code example below, the first file is a typical implementation of INotifyPropertyChanged, done entirely by hand. Notice all the noise and duplication: explicit backing properties, multiple calls to NotifyPropertyChanged to account for the derived property, the use of a string that exactly matches the property names. And this is a class with only three properties. Imagine if you had a whole bunch more properties, and imagine the maintenance problem to add/remove/change one of the derived properties!

The second file is an example of how you would do the exact same thing using NotifyPropertyWeaver. You don't have to write the NotifyPropertyChanged method, or call it in the setters, or write backing properties. This class is so much easier to read and maintain. The third file is actually a look at the class after it's been compiled, run through NotifyPropertyWeaver, and then disassembled with Telerik's JustDecompile. Look familiar? It's almost exactly the same as the hand-coded implementation.

And finally, the fourth file is the change that will be made to your project file when you add NotifyPropertyWeaver with NuGet. It calls a task that uses Mono.Cecil to rewrite the code for you. You don't need to reference the build task DLL in your project.

NotifyPropertyWeaver is a tool that does a single task, but this approach (an MSBuild post-compiler task) can be used to implement other AOP features. Fody is a tool by the creator of NotifyPropertyWeaver to do just that.

SheepAspect: a closer look

February 09, 2012 mgroves 0 Comments
Tags: SheepAspect Cecil

Recently I was made aware of another AOP tool for .NET that uses a post-compile step to do the weaving (similar to PostSharp). SheepAspect appears to use the Mono.Cecil library, which is a powerful utility to work with CIL assemblies. I mentioned SheepAspect in an earlier post, and I thought it deserved a closer look.

SheepAspect is available via NuGet, so it's an easy install. Here's a 'Hello, World' aspect in a console app that I threw together:

It's a somewhat unfamiliar approach to me, being used to PostSharp.

  • To define an aspect, create a class and put the [Aspect] attribute on it. So far so good.
  • You don't use attributes to apply the aspect to your code. Notice that MyClass and DoStuff are not decorated with any attributes.
  • Instead, you define a pointcut by creating an empty "marker" method (MyPointcut in the above example), and placing a selector attribute on that. The one I'm using is SelectMethods, but there are others available.
  • The string in that SelectMethods attribute is called SheepAop Query Language (SAQL).
  • The advice goes into the InterceptMethod method, which returns an object and gets an MethodJointPoint (yes MethodJointPoint, not MethodJoinPoint, that's not a typo). MethodJointPoint is very similar to DynamicProxy's IIntercept or PostSharp's MethodInterceptionArgs, in that it gives you a context to work with.
  • I put an "Around" attribute on this method to specify that I want this advice to surround the pointcut, and I specified the pointcut with the string.

Compile and run, and here's the output:

Sheep Aspect example console output

After using SheepAspect in this admittedly trivial way, I do think it has some potential, but it also feels like a project that's in its very early stages and is a little rough around the edges still.

  • SAQL is a very interesting way to select pointcuts, and based on the SAQL documentation that I've read, it can be very powerful. This is a double-edged sword though: this query language is specific to SheepAspect, so you'll have to spend some time learning it to get the most use out of it.
  • SAQL queries are just strings, so refactoring/renaming could be problematic. Perhaps if you are coming from an AspectJ environment, this would not be as difficult, since that's what SheepAspect seems to modeled on. A Linq provider would be tremendous, but that might be very ambitious, if not impossible.
  • The fact that SheepAspects are only connected to your regular code by SAQL is also an interesting approach: your pre-compile source code goes completely untouched, which is nice and clean, but it could also be hard to keep track of what aspects are being applied where.
  • Finally, while there is some good documentation, it looks like some of it has yet to be written, which indicates to me that it's still very much a work in progress.

I can't say I'd recommend using SheepAspect over more mature and supported tools like PostSharp or Castle DynamicProxy, but it might be worth a look for specialized usage in low risk situations. In the future, who knows; it could develop into a very popular tool.

Matthew D. Groves

About the Author

Matthew D. Groves lives in Central Ohio. He works remotely, loves to code, and is a Microsoft MVP.

Latest Comments

Twitter