So I officially hate my life!  I just lost a day of my life trying to get NotifyPropertyChanged weaving working with Mono.Cecil.  It worked brilliantly in .Net, but blew up in Silverlight with a VerificationException (“Operation could destabilize the runtime”) as soon as I tried to invoke my rewritten Property Setters.

I literally combed through every IL instruction in both Reflector and ILDASM and verified everything was as it should be.  In the end the issue was a peculiarity with the CoreCLR as oposed to the full blown CLR.  The CoreCLR requires all locals to be flagged as init even if play by the rules and assign to the local before reading from it.

Here’s the offending IL:

.method public hidebysig specialname instance void set_Property(string 'value') cil managed
{
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] string str,
        [1] bool flag)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: call instance string SynerG.Weaving.Tests.DecoratedClass::get_Property()
    L_0007: stloc.0 
    L_0008: ldarg.0 
    L_0009: ldarg.1 
    L_000a: stfld string SynerG.Weaving.Tests.DecoratedClass::<Property>k__BackingField
    L_000f: ldarg.1 
    L_0010: ldloc.0 
    L_0011: call bool [mscorlib]System.Object::Equals(object, object)
    L_0016: stloc.1 
    L_0017: ldloc.1 
    L_0018: brtrue.s L_0028
    L_001a: nop 
    L_001b: ldarg.0 
    L_001c: ldstr "Property"
    L_0021: callvirt instance void [SynerG.Silverlight]SynerG.Notification.NotifyingBase::OnPropertyChanged(string)
    L_0026: nop 
    L_0027: nop 
    L_0028: ret 
}

 You can fix this with a cheeky:

methodBody.InitLocals = true;

Phew.  That’s a day of my life that I’m never going to get back again!

Advertisements

A common gripe with WPF and Silverlight development is having to implement INotifyPropertyChanged in your Models and ViewModels. You then have to remember (most of the time) to fire the PropertyChanged event whenever you change a property.

On the project I’m working on we’ve been using PostSharp for a while to automatically weave in the code to do this for us. The other day I set about converting our app to .Net 4 and Silverlight 4. Sadly, the version of PostSharp we were using (1.5) doesn’t play nicely with .Net 4. Fine I thought, I’ll simple update to version 2.0. I then found out that the functionality we need is only available in the licensed version. Although PostSharp is a great product, we only use it for this exact problem and it doesn’t justify forking out for a license for all the devs on my team.

So I decided to set out weaving in the IL myself. I tried various different methods including Microsoft’s CCI and CciSharp. I found these to be very powerful, but fiendishly complicated. Then I tried out Mono.Cecil. This is a fantastic bit of software and is very easy to use.

I stumbled upon a great blog post by Justin Angel. It describes exactly how you can achieve this using Mono.Cecil. The only problem is that if you rewrite a silverlight application assembly in the AfterBuild Target as Justin describes, the XAP file generated contains the DLL before the rewrite and therefore doesn’t work.

I managed to get around this problem by hacking my .csproj file thusly:

  <UsingTask TaskName=”CecilPropertyChanged.MSBuild.WeaveNotifyPropertyChangedTask” AssemblyFile=”$(SolutionDir)Lib\CecilPropertyChanged.MSBuild.dll” />
  <Target Name=”WeaveNotifyPropertyChanged”>
    <CecilPropertyChanged.MSBuild.WeaveNotifyPropertyChangedTask AssemblyPath=”$(IntermediateOutputPath)$(AssemblyName).dll” />
    <Copy SourceFiles=”$(IntermediateOutputPath)$(AssemblyName).dll” DestinationFolder=”$(OutputPath)” />
  </Target>

  <PropertyGroup>
    <XapPackagerDependsOn>
      _CreateSLProperties;
      MarkupCompilePass1;
      ValidateXaml;
      WeaveNotifyPropertyChanged;
      FilesToXap;
      CreateSilverlightAppManifest;
    </XapPackagerDependsOn>
  </PropertyGroup>

Works like a charm!