First Steps with Post Sharp
PostSharp is an AOP framework that works using byte code weaving. That is, it re-writes your IL to add behaviors to it. From my point of view, it is like having the cake (interception, byte code weaving) and eating it (I haven't even looked at the PostSharp source code, just used the binary release).
My initial spike with it went very well. Here it is:
[Serializable] public class Logger : OnFieldAccessAspect { public override void OnGetValue(FieldAccessEventArgs eventArgs) { Console.WriteLine(eventArgs.InstanceTag); Console.WriteLine("get value"); base.OnGetValue(eventArgs); } public override InstanceTagRequest GetInstanceTagRequest() { return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false); } public override void OnSetValue(FieldAccessEventArgs eventArgs) { int i = (int?)eventArgs.InstanceTag ?? 0; eventArgs.InstanceTag = i + 1; Console.WriteLine("set value"); base.OnSetValue(eventArgs); } }
This is an aspect that run on each field access. It is not really useful, but it helps to show how things works. A couple of things that are I think are insanely useful:
- Aspects are instantiated at compile time, allowed time to set themselves up, then serialized to an resource in the assembly. At runtime, they are de-serialized and ready to run. The possibilities this give you are amazing.
- InstanceTag is a way to keep additional data per aspect.
Now, let us assume that I want to add the aspect to this code:
[Logger] public class Customer { public string Name { get; set; } }
Note, there is no field. (Well, there is, it is generated by the compiler). Now we compile and run the PostSharp post compile step. With that, we can now investigate what is going on.
As you can see, we are deserializing the attribute and storing it in a field that we can now access. Let us check the Customer implementation now:
We have the logger field, which is used for something, but we also have the ~get~<Name>k__Backingfield and ~set~<Name>k__BackingField. <Name>k__BackingField (and I would love to hear the story behind that) is the compiler generated field that was created for us. The ~get~... and ~set~ are generated by PostSharp. Before we look at them, we will look at the implementation of Name.
Where it used to call the field directly, now it is doing this via a method call. And now we can look at those method calls.
There is a lot going on here. We create a new field access event arg, call the aspect method, and return the value. Note that the state (instance tag) is stored in the object as well, for each field access.
It looks very well done.
Comments
Ruurd Boeke used PostSharp in a very large open source project to generate a POCO version of Entity Framework v1. The details are at www.sitechno.com/.../...PocoImplementationV01.aspx.
--rj
What happens when you need to debug your code? Do the [Debugger] attributes let you step through your code as you wrote it ignoring the PostSharp goo?
Yes, they do
@Chris
You can debug your code and your aspects like you write. Debugging is verry well with postsharp.
Postsharp is great, but i think something changed between versions.
I noticed that it generates the IL source code!!! I posted with consternation on the forum and it was confirmed by Frateur.
In my simple projects it is very slow. I have a machine above average, 4G DDR2, best Raptor150, it is unacceptable from my point of view.
I don't have this problem with boo macros :-), where although a newbie, the performance is simply great.
I would move my codebase to boo if it were 1.0....
Really cool, I keep wondering if aspect orientated stuff will make it into c#'s next version.. not sure if that would be classed as polution of the language.
I've pulled in postsharp for things like:
-singleton
-Inotifypropertychanged
-validation
its occasionally a worthwhile trick to cut back on repetitive code
I pitched in some examples on:
http://code.google.com/p/postsharp-user-samples/
this kind of thing comes for free in Boo, doesnt it?
@liviu - I use PostSharp to give me property changed notification and to do some other set up in my object model. I have a lower spec machine than you and have no major problems with speed. Sure, it's noticable during the compile, but only a few extra seconds. As I see it now it's well worth the massive simplification to my domain objects. What are you using PostSharp for? I'm interested in case there are some gotchas waiting for me!!
Does this work with virtual properties ?
I'm not getting it to work, was wondering if that is why
Yes, it should.
Comment preview