I've been playing with PostSharp a bit and I ran into a nasty problem.
Following IL in Silverlight assembly:
.method public hidebysig specialname newslot virtual final instance void
set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
.maxstack 2
.locals (
[0] bool ~propertyHasChanged,
[1] bool CS$4$0000)
L_0000: nop
L_0001: nop
L_0002: ldarg.0
L_0003: call instance valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::get_AccountProfileModifiedAt()
L_0008: ldarg.1
L_0009: call bool [mscorlib]System.DateTime::op_Inequality(valuetype
[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
L_000e: stloc.0
L_000f: ldarg.0
L_0010: ldarg.1
L_0011: stfld valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::accountProfileModifiedAt
L_0016: br.s L_0018
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
L_001e: brtrue.s L_002b
L_0020: ldarg.0
L_0021: ldstr "AccountProfileModifiedAt"
L_0026: call instance void
Accounts.AccountOwner::NotifyPropertyChanged(string)
L_002b: nop
L_002c: leave.s L_002e
L_002e: ret
}
triggers System.Security.VerificationException: Operation could destabilize the runtime. exception. Reflector parses it OK. What could be wrong with it?
Update 1 Code is intended to work as follows:
public void set_AccountProfileModifiedAt(DateTime value)
{
bool propertyHasChanged = this.AccountProfileModifiedAt != value;
this.accountProfileModifiedAt = value;
if (propertyHasChanged)
{
this.NotifyPropertyChanged("AccountProfileModifiedAt");
}
}
Update 2 I get specified exception inside the setter itself
Update 3 Making non-static calls as callvirt (NotifyPropertyChanged) does not help
Update 4 Commenting out (for test purposes) code:
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
and replacing L_001e: brtrue.s L_002b with L_001e: br.s L_002b does the trick but it's an unconditional return - not what I want.
Update 5 If I use C# compiler to mimic required behavior (I still need to do that with Postsharp) I get following IL:
.method public hidebysig specialname newslot virtual final instance void
set_AccountProfileModifiedAt(valuetype [mscorlib]System.DateTime 'value') cil managed
{
.maxstack 2
.locals init (
[0] bool val,
[1] bool CS$4$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: call instance valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::get_AccountProfileModifiedAt()
L_0007: ldarg.1
L_0008: call bool [mscorlib]System.DateTime::op_Inequality(valuetype
[mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime)
L_000d: stloc.0
L_000e: ldarg.0
L_000f: ldarg.1
L_0010: stfld valuetype [mscorlib]System.DateTime
Accounts.AccountOwner::accountProfileModifiedAt
L_0015: ldloc.0
L_0016: ldc.i4.0
L_0017: ceq
L_0019: stloc.1
L_001a: ldloc.1
L_001b: brtrue.s L_0029
L_001d: ldarg.0
L_001e: ldstr "AccountProfileModifiedAt"
L_0023: call instance void
Accounts.AccountOwner::NotifyPropertyChanged(string)
L_0028: nop
L_0029: ret
}
Note there are minor differences - extra br.s jump at L_0016 and some strange jump L_001e: brtrue.s L_002b. In compiler version I get direct jump to ret.
Here's a post that deals with that error. I don't know if your particular case is caused by the same problem, but in general it looks like this has to do with code access security and verification. If that's the case, Reflector will be able to read the IL just fine but the CAS system will kick it out for reasons unknown.
It looks like you have a property setter calling into a bunch of other objects. You should go through those other method calls looking for big switch statements, in case it is the specific issue mentioned in the post.
Did you use peverify? You should always run this utility when playing directly with MSIL (you can use the msbuild flag /p:PostSharpVerify=true).
Looking at your code:
Your local variables are not initialized (missing "init" keyword). This is a property of MethodBodyDeclaration.
You are using a 'leave' instead of a 'jmp' out of a protected block; this is useless but should not matter.
Good luck,
-gael
It is difficult to say - do you have a stack trace? This exception is usually thrown when the CLR is unable to verify the type-safety of your code. As this could have come from this code or from any of the methods or types you are using it will be difficult to say what the issue is without a stack trace.