Domanda

Ho giocato un po 'con PostSharp e ho riscontrato un brutto problema.

A seguito di IL nell'assemblaggio 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 }

attiva System.Security.VerificationException: l'operazione potrebbe destabilizzare il runtime. eccezione. Il riflettore lo analizza OK. Cosa potrebbe esserci di sbagliato in questo?

Aggiornamento 1 Il codice funziona come segue:

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

Aggiornamento 2 Ottengo un'eccezione specifica all'interno del setter stesso

Aggiornamento 3 Effettuare chiamate non statiche come callvirt (NotifyPropertyChanged) non aiuta

Aggiornamento 4 Commentare (a scopo di test) il codice:

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

e sostituendo L_001e: brtrue.s L_002b con L_001e: br.s L_002b fa il trucco ma è un ritorno incondizionato - non quello che voglio.

Aggiornamento 5 Se uso il compilatore C # per imitare il comportamento richiesto (devo ancora farlo con Postsharp) Ottengo il seguente IL:

<*>

Nota che ci sono differenze minori - salto extra di br.s su L_0016 e qualche strano salto L_001e: brtrue.s L_002b. Nella versione del compilatore ottengo il salto diretto per ret.

È stato utile?

Soluzione

Hai usato peverify? Dovresti sempre eseguire questa utility quando giochi direttamente con MSIL (puoi usare il flag msbuild / p: PostSharpVerify = true).

Guardando il tuo codice:

  1. Le variabili locali non sono inizializzate (parola chiave " init " mancante). Questa è una proprietà di MethodBodyDeclaration.

  2. Stai usando un 'lasciare' invece di un 'jmp' fuori da un blocco protetto; questo è inutile ma non dovrebbe importare.

Buona fortuna

-gael

Altri suggerimenti

È difficile dirlo: hai una traccia dello stack? Questa eccezione viene generalmente generata quando il CLR non è in grado di verificare la sicurezza del tipo del codice. Poiché ciò potrebbe derivare da questo codice o da uno qualsiasi dei metodi o tipi che stai utilizzando, sarà difficile dire quale sia il problema senza una traccia dello stack.

Ecco un post che affronta questo errore. Non so se il tuo caso particolare sia causato dallo stesso problema, ma in generale sembra che questo abbia a che fare con la sicurezza e la verifica dell'accesso al codice. In tal caso, Reflector sarà in grado di leggere bene l'IL, ma il sistema CAS lo avvierà per motivi sconosciuti.

Sembra che tu abbia un setter di proprietà che chiama in un gruppo di altri oggetti. Dovresti passare attraverso quelle altre chiamate di metodo alla ricerca di grandi dichiarazioni switch, nel caso in cui si tratti del problema specifico menzionato nel post.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top