views:

1351

answers:

3

Which is the better in terms of capabilities, easy of use, documentation, samples, community/support, VS integration, known implementations, long-term viability, and build speed to implement a custom AOP framework?

I'll start with what I know (I have only tried PostSharp to so far):

  • Microsoft Common Compiler Instrastruture (CCI): I've read that is used for FxCop, ILMerge, Spec# and Code Contracts. It seems to be very low level as it does not even take care of correcting offsets for branch codes that are borken when IL is modified with it.
  • PostSharp is 5 years old, has many capabilities for AOP (e.g. abstracts some things you would need to have to do manually with IL away), source code available, developed/supported by only one guy but he is planning on making this a business, has documentation but could be better, builds take about twice as long, very little samples on how to inject IL and version 2.0 will be released soon which promises to be much improved.
  • Mono Cecil: Written by one guy, part of the Mono suite and there is a plug-in for Reflector called Reflexil that uses Mono Cecil.
+3  A: 

As with most frameworks that are already out there, I would suggest to you, regarding implementing your own AOP framework: Don't do it. There are several already out there, including (soon-to-be) commercially supported PostSharp, and CThru, an AOP framework powered by Typemock.

But anyway, I found Mono.Cecil very easy to use. It abstracts away the need to deal with Reflection.Emit nicely, and it has the support of the Mono community.

I suggest you have a look at LinFu - it's an open-source set of libraries, one of them is an AOP framework implemented on top of Mono.Cecil. There is a nice article on LinFu AOP on CodeProject.

hmemcpy
I'm only interested in AOP that injects code during compile-time.
Hermann
LinFu does that. It has with a post-compiler task to weave the IL.
hmemcpy
While LinFu.AOP weaves IL that modifies types to enable code injection with a post-compiler task, the actual code is injected during run-time which is less performant.
Hermann
+3  A: 

Both Microsoft.CCI and Mono.Cecil are low-level, and don't validate produced assemblies. It takes lots of time to find the reason of problem, if there is any error in generated code or assembly structure.
I'd recommend using PostSharp if it's features are enough for you tasks.
Otherwise... Mono.Cecil has better, more understandable and easy in use object model. However, I had an ugly bug when used it in my program (reference to the wrong method was saved in the assembly; I think there was some bug with metadata tokens handling)
Microsoft.CCI has an ugly, utterly over-designed object model in the same time lacking many simple features; however, it's more mature than Mono.Cecil. Finally, I abandoned Mono.Cecil and used Microsoft.CCI for my program.

skevar7
Thank you for sharing your experiences! I think you can always use PEVerify Tool to validate your produced assemblies. I am using PostSharp right now and I've been able to do everything I wanted to with it so far (and you are right about finding the reason, it can be very frustating...). What do you mean by more mature? Less buggy? Is there a particular reason why you are not using PostSharp? Out of curiosity, what's your program doing?
Hermann
My program is assembly merger/shrinker, thus PostSharp was no help for me. And yes, I found Microsoft.CCI less buggy, and it supports more CLI features (mixed assemblies, for instance). It's object model is really hard in use, though. I used PEVerify to check generated assemblies (and not sure if I could succeed without it :) ) However, errors often break assembly generation process, and PEVerify is useless in such cases.
skevar7
+4  A: 

AFAIK, LinFu is built on Mono.Cecil.

I would say that PostSharp.Core has more high-level features than other frameworks, so it's less difficult to use for larger works. You can work at low level too, but not at binary level (by design). You could do an assembly merger/shrinker using PostSharp, but the fact that it compiles back using ILASM would set some limitations (for instance that even internal members should be named). On the other side, having ILASM as the backend makes it much easier to develop on the top of PostSharp, since ILASM verify many rules and you can easily read the produced MSIL code. PostSharp even let you put comments into MSIL to help debugging code generation.

Another point: if you want to do a custom aspect (for instance, you develop a database engine and want to deliver a persistence aspect), you need much more than just an MSIL rewriter. You need an AO infrastructure that will do much of the job for you. When you are developing a custom aspect, I would say 1% of the work is specific to your custom aspect, 39% is the aspect infrastructure, and 60% is the MSIL rewriter stuff. I am often able to program a very specific aspect in a couple of hours based on PostSharp.

So, back to your question, and of course with my own biais, I would say: if you want to write an obfuscator, merger/shrinker and so on, rather go for Mono.Cecil or Microsoft.CCI for the only reason that their license if more friendly than PostSharp's one. But if just want to develop a custom aspect, using PostSharp will make you save weeks, and you would be surprised by commercial conditions we could offer if you plan to redistribute PostSharp.

Gael Fraiteur
Sounds good. I guess I am gonna stick with PostSharp then since I've been happy with it so far.
Hermann