2009-03-05 7 views
1

Je jouais un peu avec PostSharp et j'ai rencontré un vilain problème.CIL: "L'opération risque de déstabiliser l'exécution"

Suite IL dans l'assemblage Silverlight:

.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 
} 

déclenche System.Security.VerificationException: Opération pourrait déstabiliser le moteur d'exécution. exception. Le réflecteur l'analyse correctement. Quel pourrait être le problème avec?

Code Update 1 est destiné à fonctionner comme suit:

public void set_AccountProfileModifiedAt(DateTime value) 
{ 
    bool propertyHasChanged = this.AccountProfileModifiedAt != value; 
    this.accountProfileModifiedAt = value; 
    if (propertyHasChanged) 
    { 
     this.NotifyPropertyChanged("AccountProfileModifiedAt"); 
    } 
} 

Mise à jour 2 je suis spécifié exception à l'intérieur du setter se

Mise à jour 3 but non statique appelle comme callvirt (NotifyPropertyChanged) n'aide pas

Mise à jour 4 Décommenter (à des fins de test) Code:

L_0018: ldloc.0 
L_0019: ldc.i4.0 
L_001a: ceq 
L_001c: stloc.1 
L_001d: ldloc.1 

et le remplacement L_001e: brtrue.s L_002b avec L_001e: br.s L_002b fait le tour, mais il est un retour inconditionnel - pas ce que je vouloir.

Mise à jour 5 Si j'utilise le compilateur C# pour imiter le comportement requis (je dois encore le faire avec PostSharp) je me suit 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 
} 

Remarque il y a des différences mineures - br supplémentaire. S saute à L_0016 et saute étrangement L_001e: brtrue.s L_002b. Dans la version du compilateur, je reçois un saut direct vers ret.

Répondre

2

Avez-vous utilisé peverify? Vous devriez toujours exécuter cet utilitaire lorsque vous jouez directement avec MSIL (vous pouvez utiliser l'indicateur msbuild/p: PostSharpVerify = true).

En regardant votre code:

  1. Vos variables locales ne sont pas initialisés (manquant mot-clé "init"). Ceci est une propriété de MethodBodyDeclaration.

  2. Vous utilisez un 'congé' au lieu d'un 'jmp' hors d'un bloc protégé; C'est inutile, mais cela ne devrait pas avoir d'importance.

Bonne chance,

-gael

0

Il est difficile de dire - avez-vous une trace de pile? Cette exception est généralement levée lorsque le CLR est incapable de vérifier la sécurité de votre code. Comme cela pourrait provenir de ce code ou de l'une des méthodes ou des types que vous utilisez, il sera difficile de dire quel est le problème sans trace de pile.

+0

Haut de la pile est juste un poseur de propriété :(: System.Security.VerificationException: l'opération pourrait déstabiliser l'exécution à Domain.Accounts.AccountOwner.. set_AccountProfileModifiedAt (valeur DateTime) –

0

Here's un article traitant de cette erreur. Je ne sais pas si votre cas particulier est causé par le même problème, mais en général, il semble que cela ait à voir avec la sécurité et la vérification de l'accès au code. Si tel est le cas, Reflector sera capable de lire l'IL juste très bien mais le système CAS l'expulsera pour des raisons inconnues.

Il semble que vous ayez un accesseur de propriété appelant un tas d'autres objets. Vous devriez passer par ces autres appels de méthode à la recherche de grandes instructions de changement, au cas où c'est le problème spécifique mentionné dans le message.

+0

Voici comment il ressemble: bool propertyHasChanged = this.AccountProfileModifiedAt = valeur; this.accountProfileModifiedAt = valeur; si (propertyHasChanged) { this.NotifyPropertyChanged ("AccountProfileModifiedAt"); } IMO il ne devrait pas échouer dans setter si une autre méthode échoue? –

+0

L'exception peut être due à l'une des autres méthodes/propriétés auxquelles vous accédez. Comme test, essayez de retirer tout le code du setter et voyez si cela le corrige. Ensuite, ajoutez le code petit à petit pour comprendre exactement ce qui échoue. –

Questions connexes