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.

Phased Execution

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.
Like week-end I have been working on a breaking feature of PostSharp: the possibility to use it at runtime. So PostSharp is not only a post-compiler any more. Of course, the core technology is still and will stay MSIL manipulation. When I say that PostSharp can be used at runtime, I mean that .NET modules can be woven just before they are loaded by the Virtual Runtime Engine (VRE). After they have been loaded, they cannot be modified. Obviously. Why at runtime? Weaving an assembly at runtime makes sense principally within application servers. These servers typically offer services like transactions or persistence. These aspects may be defined, for instance, at deployment time in a management console. So they have to be woven outside the development environment. How does it work? If you liked the Platform Infrastructure (what makes PostSharp really different from an ordinary IL reader/writer), you will have another reason to be satisfied: the same infrastructure is now available at runtime. It has been redesigned to make no difference between runtime and compile-time use. The MSBuild task and the command-line utility have been corrected to use the new design. Concretely, I defined a new object PostSharpObject that is the entry point for the Platform Infrastructure. You can create an instance (either in the current AppDomain either in a private one) using the PostSharpObjectFactory -- in any case you will only get the interface IPostSharpObjectFactory. This interface has a single method InvokeProjects, that allows to execute a set of project. Each project has its own source module and its own properties. This satisfies most compile-time scenarios and even some runtime ones! Things become more interesting when you need to weave assembly in deep-first order. That means that you need to weave referred assemblies first, then referring. This is typically the case when you need to change the public interface of assemblies (for instance change fields into properties). In this case, you have to implement the new IPostSharpHost interface. This interface is called every time an assembly reference should be resolved. You get the opportunity to tell how assemblies should be processed, i.e. you can ask there to transform it using a project and given parameters. On the other extreme, lazy weaving of assemblies (weave just before the assembly is required by the VRE) needs a more complex interaction between the host and PostSharp. The host has to implement the AppDomain.AssemblyResolve event. Do you want to try? The changes have been merged in the trunk of the SVN repository. I have built a prerelease of the 1.0 Beta 1 version. It is largely documented and I wrote a sample. Feedback welcome!