Question

Je joue un peu avec PostSharp et je suis tombé sur un vilain problème.

Après l'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
public void set_AccountProfileModifiedAt(DateTime value)
{
    bool propertyHasChanged = this.AccountProfileModifiedAt != value;
    this.accountProfileModifiedAt = value;
    if (propertyHasChanged)
    {
        this.NotifyPropertyChanged("AccountProfileModifiedAt");
    }
}
) 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 une exception System.Security.VerificationException: l'opération pourrait déstabiliser l'exécution. exception. Le réflecteur l’analyse bien. Qu'est-ce qui ne va pas avec ça?

Mise à jour 1 Le code est conçu pour fonctionner comme suit:

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

Mise à jour 2 Je reçois une exception spécifiée à l'intérieur du séparateur lui-même

Mise à jour 3 Faire des appels non statiques en tant que callvirt (NotifyPropertyChanged) n’aide en rien

Mise à jour 4 Code de commentaire (à des fins de test):

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

et en remplaçant L_001e: brtrue.s L_002b par L_001e: br.s L_002b fait l'affaire mais c'est un retour inconditionnel - pas ce que je veux.

Mise à jour 5 Si j'utilise un compilateur C # pour imiter le comportement requis (je dois quand même le faire avec Postsharp) Je reçois l'IL suivant:

<*>

Notez qu'il existe des différences mineures - saut supplémentaire br.s à L_0016 et étrange saut L_001e: brtrue.s L_002b. Dans la version du compilateur, je reçois un saut direct sur Ret.

Était-ce utile?

La solution

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

En regardant votre code:

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

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

Bonne chance,

-gael

Autres conseils

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 type de votre code. Comme cela pourrait provenir de ce code ou de l’une des méthodes ou types que vous utilisez, il sera difficile de dire quel est le problème sans trace de pile.

Voici 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, cela semble lié à la sécurité et à la vérification de l'accès au code. Si tel est le cas, Reflector sera en mesure de lire l’IL parfaitement, mais le système CAS le rejettera pour des raisons inconnues.

Il semble que vous ayez un configurateur de propriété appelant un groupe d’autres objets. Vous devriez passer par ces autres appels de méthode à la recherche de grandes instructions switch, au cas où ce soit le problème spécifique mentionné dans le message.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top