Sometimes doing the simplest things is difficult. In order to make any headway on SharpMock, I’ll need to be able to understand the basics of PostSharp. What could be more basic than getting PostSharp to execute a task that ouputs a ‘Hello World’ message during the postcompilation process? We’re not decorating any types with attributes; we’re not intercepting any calls; we’re not outputting any IL. This should be a snap! And yet, I haven’t posted in weeks….
First thing’s first – we need a ‘Hello World’ task. In a project called PostSharpPlugin I have defined the following class:
using PostSharp.Extensibility;
namespace PostSharpPlugin
{
public class SayHelloTask : Task
{
public override bool Execute()
{
Console.WriteLine("Hello, PostCompiler!");
// Task executed successfully
return true;
}
}
}
I have also created a .psplugin file that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<PlugIn xmlns="http://schemas.postsharp.org/1.0/configuration">
<TaskType Name="SayHello" Implementation="PostSharpPlugin.SayHelloTask, PostSharpPlugin" Phase="Analyze">
</TaskType>
</PlugIn>
So, there we have a plugin that will perform some tasks during postcompilation. We want this task to be performed during postcompilation of some other assembly if it references this plugin, so we need some way to tell PostSharp about this requirement. To do so, we add an attribute to PostSharpPlugin:
[assembly: ReferencingAssembliesRequirePostSharp("SayHello", "PostSharpPlugin")]
I have created another assembly called (very cleverly) ReferencingAssembly and added a reference to PostSharpPlugin. That assembly contains this .psproj file:
<Project xmlns="http://schemas.postsharp.org/1.0/configuration" ReferenceDirectory="{$ReferenceDirectory}">
<SearchPath Directory="{$SearchPath}" />
<Using PlugInFile="../PostSharpPlugin/bin/Debug/PostSharpPlugin.psplugin" />
<Tasks>
<AutoDetect />
<SayHello />
<Compile TargetFile="{$Output}"
IntermediateDirectory="{$IntermediateDirectory}"
CleanIntermediate="{$CleanIntermediate}"
SignAssembly="{$SignAssembly}"
PrivateKeyLocation="{$PrivateKeyLocation}"/>
</Tasks>
</Project>
The Using element tells PostSharp where to get the definition for the task SayHello. This is critical. I spent every spare hour I had for weeks trying to get this seemingly simple example to work without defining or importing the definition of the SayHello task in this file. In fact, I don’t think I should have to explicitly specify the SayHello task to be executed here either. All the tracing, debugging, and specifying different search paths I could do didn’t help me get this example working, so for now importing the task definition like so is the solution I’m rolling with. It will allow us to make some headway, like figuring out how to check a test assembly for methods that need to be mocked. Ultimately, though, we’ll need PostSharp to automatically detect and use tasks that provide services like ICustomAttributeProvider, and this solution won’t handle that.
Oh, by the way, don’t forget that we need to invoke PostSharp when we compile our assembly. For that we need to import the PostSharp MSBuild task. The modified ReferencingAssembly.csproj file for this example looks like this at the end (the second element is what has been added):
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\ThirdParty\PostSharp.targets" />
I have uploaded the code for this example here. I have included all of the needed PostSharp files in the ThirdParty directory. (I’m not sure this distribution is allowed.) So, it should “just work”… you can open the solution in Visual Studio, build, and see something like this in the build output window:
...
PostSharp 1.0 [1.0.11.424] - Copyright (c) Gael Fraiteur, 2005-2008.
Hello, PostCompiler!
...
Comments
ReferencingAssembliesRequirePostSharp should work, but PostSharp should know where your plug-in lays.
So either you add it to the plug-in directory, either you add the location of your plug-in to "Reference Path", in Visual Studio properties.
In case of problem, you can always try to ask on the forum.
Good luck!
-gael