In my previous post I claimed that it was not possible, in general, to merge assemblies enhanced by PostSharp, because it would break the assembly references stored as strings in aspect serialization data.

I did not realize that the BinaryFormatter provides a way to solve our problem. It is indeed possible to provide its own SerializationBinder, whose role is precisely to return the System.Type corresponding to an assembly name and a type name. We can provide a custom binder to redirect merged assemblies.

This is the feature I have added to build available for download in the builds section; I could still do it in 1.0 since it is a no-risk feature, breaking nothing existing (if you don't use it, nothing can go wrong).

I have added a new class PostSharp.Laos.LaosSerializationBinder. You can set the static property Current to your own implementation of SerializationBinder. If you don't set it, nothing is changed. The LaosSerializationBinder class it itself derived from SerializationBinder and implements the feature we need: assembly retargeting. So all you have to do is to create an instance of this class, set up retargeting policies, and assign it to LaosSerializationBinder.Current.

The following code sets up PostSharp Laos so that references to 'MergedPostSharpLib.dll' are retargeted to 'MergedPostSharp.exe' (supposing that the library has been merged into the executable):

LaosSerializationBinder binder = new LaosSerializationBinder();
binder.Retarget("MergedPostSharpLib", "MergedPostSharp");
LaosSerializationBinder.Current = binder;

The only thing you have to really take care about is to set up the binder before the first aspect is deserialized. Aspect deserialization is triggered from static constructors of enhanced classes, so you may need to initialize the weaver very soon, and eventually to refactor your "Main(string args[])" method.

Apart from that, it should work very well.

Happy PostSharping!


Comments (3) -

7/29/2008 7:32:00 PM #

Super good news!!
Let me try that :-)

7/30/2008 4:00:00 PM #

Many thanks for this tip, it indeed works for merging libraries inside the exe.

As far as I am concerned, it's a step forward, but it's not a solution for the following reason:

When using this technique, the actual executable has to be aware of the dependency on PostSharp (by referencing the libs in the project) and even worse, the main executable to which the post processed library was totally invisible has all of the sudden the need to add additional code to fix the binding.

This means that it works when I want to ship an application.exe file, but it doesn't when I want to ship a library.dll because I would need to ask my clients to reference postsharp and add code to their project.

Don't mistake me though, this is a great improvement at least for self contained app and I am very grateful that you implemented this solution.

I am some kind of a perfectionist and am trying to make my point and help improve postsharp.

Gael Fraiteur
Gael Fraiteur
7/30/2008 4:22:00 PM #

Sure, it does not work in all scenarios. It was not the objective to support library merging.

There are big problems associated to it, the main being that PostSharp will not be able to instantiate aspects at compile-time since the base classes will now be located in another assembly. There would be a cast exception.

The solution would be *not* to instantiate aspects in PostSharp at all. This is actually how the 1.5 version works for Silverlight and CF. But the price in usability is quite high. It would be possible, althought not effortless, to develop something similar to allow aspect vendors to merge postsharp.laos and postsharp.public into their assembies.

I guess the next comment will be that someone needs to have postsharp without having postsharp at all on the machine, but I fear it's not going to be possible in predictable future ;-P.

Comments are closed