Archive

The ones who already use the Code Weaver will maybe get angry but that's something I needed to do before going beta: I have redesigned quite deeply the low-level code weaver. Most changes are documented in the CHANGELOG.txt file. So what has changed? First, the notions of local and global advices has been deprecated. There is instead a unified notion of method-level advices and unified semantics to express what is called elsewhere pointcuts, i.e. to apply advices to join points. When you add an advice to the weaver, you can now specify on which methods it applies and on which operands. We use the IEnumerable interface to pass sets of methods and operands, so it should be forward compatible with C# 3.0 / LINQ. If I said method-level advices, that's because PostSharp now supports also type-level advices: the only join point currently supported is after instance construction, i.e. in the constructor, just after the base constructor has been called. Secondly, you cannot call the weaver for individual methods. The Weave method now weaves the complete module according to the advices that were previously added to it. And finally, the IAdviceProvider has changed. There is now a single ProvideAdvices method in which you should add advices to the given weaver. That's all. The internal workings have been considerably optimized to work with operand-sensitive join points. Say you want to intercept all calls to the Thread.Sleep() method. You create an advice and apply it to the join points of kind InsteadOfCall with operand Thread.Sleep. Before redesign, the weaver would have woven every method of the module. But now, it will only weave methods that effectively use the Thread.Sleep method. In order to make it possible, I have implemented the new task IndexUsagesTask, which reads all method bodies an indexes 'uses' and 'used-by' relationships. Why is it better than the previous design? First, because inspection algorithm of this task is much simpler than the one of the weaver. Secondly, because the same information can be used by other tasks. So at the end of the day, will you be still angry of this design change? Hopefully not, because these changes don't affect your code too much. All you have to do is to change your implementation of IAdviceProvider. And this new design is much better and is prepared for the future. So let's go!

Remote Host

I wrote in the previous post that PostSharp now offers more possibilities for the host to customize the execution process, for instance phased execution and events. In order to enable it, we missed a functionality: to be able to run host code in the PostSharp application domain, not only in the host AppDomain. This is the role of the new concept of local host. The local host is an object that resides in the PostSharp application domain between the PostSharpObject and the host object residing in the host application domain (IPostSharpHost). The whole communication between the PostSharpObject and the remote host now goes through the local host. We provide a default implementation in the PostSharpLocalHost class, but you can override it and pass your own implementation using the LocalHostImplementation property of the PostSharpObjectSettings object.
There is a lot of new things to tell today. To make it simpler I will make a post for each of them. Let me start with the first: phased execution. You probably know that PostSharp projects are composed of tasks. Indexing types is a task, weaving is a task, and even compiling back the code is a task. What you maybe don't know if that tasks are grouped in phase. PostSharp defines four standard phases: load, analyze, transform and generate. When you execute a single project, i.e. when you transform a single module, the situation is trivial: we execute one phase after the other. However, when you transform multiple modules in a single invocation of PostSharp, then you have the question: should I analyse all module, then transform them all, then compile them all, or should I process one module completely, then go to the next one. You have now the choice. PostSharp can do both: the phases and the sequential execution. I have defined a new property ProjectExecutionOrder on the PostSharpObjectSettings object so you can choose. If you host PostSharp yourself, of course! If you don't, anyway, each invocation of PostSharp processes only one module and this discussion is useless. But if you do host PostSharp, you have the possibility to execute custom code between phases. If you really need this (and think twice if it cannot be implemented as a normal task), look at the events PhaseExecuting and PhaseExecuted of the PostSharpObject event. How would you get a chance to register your own event handlers? Good question, you have to implement a local host. I explain it in my next post.