CIL: Excepción de "operación podría desestabilizar el tiempo de ejecución"
-
03-07-2019 - |
Pregunta
He estado jugando con PostSharp un poco y me encontré con un problema desagradable.
Siguiendo IL en el ensamblaje de 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$4public 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
}
activa System.Security.VerificationException: la operación podría desestabilizar el tiempo de ejecución. excepción. El reflector lo analiza OK. ¿Qué podría estar mal con él?
Actualización 1 El código está diseñado para funcionar de la siguiente manera:
L_0018: ldloc.0
L_0019: ldc.i4.0
L_001a: ceq
L_001c: stloc.1
L_001d: ldloc.1
Actualización 2 Obtengo una excepción específica dentro del configurador mismo
Actualización 3 Hacer llamadas no estáticas como callvirt (NotifyPropertyChanged) no ayuda
Actualización 4 Código de comentarios (para fines de prueba):
.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
}
y reemplazando L_001e: brtrue.s L_002b con L_001e: br.s L_002b hace el truco pero es un retorno incondicional, no es lo que quiero.
Actualización 5 Si uso el compilador de C # para imitar el comportamiento requerido (todavía tengo que hacer eso con Postsharp) Me sale la siguiente IL:
<*>Tenga en cuenta que hay pequeñas diferencias: los br.s extra saltan a L_0016 y algunos saltos extraños L_001e: brtrue.s L_002b. En la versión del compilador obtengo salto directo a ret.
Solución
¿Usaste Peverify? Siempre debes ejecutar esta utilidad cuando juegues directamente con MSIL (puedes usar el / msbild flag / p: PostSharpVerify = true).
Mirando tu código:
-
Sus variables locales no están inicializadas (falta la palabra " init " init). Esta es una propiedad de MethodBodyDeclaration.
-
Estás utilizando un 'leave' en lugar de un 'jmp' fuera de un bloque protegido; esto es inútil pero no debería importar.
Buena suerte,
-gael
Otros consejos
Es difícil decirlo: ¿tienes un rastro de pila? Esta excepción generalmente se lanza cuando el CLR no puede verificar la seguridad de tipo de su código. Como esto podría provenir de este código o de cualquiera de los métodos o tipos que está utilizando, será difícil decir cuál es el problema sin un seguimiento de la pila.
Aquí hay una publicación que se ocupa de ese error. No sé si su caso particular es causado por el mismo problema, pero en general parece que esto tiene que ver con la seguridad y la verificación del acceso al código. Si ese es el caso, Reflector podrá leer el IL bien, pero el sistema CAS lo echará fuera por razones desconocidas.
Parece que tienes un establecedor de propiedades llamando a un montón de otros objetos. Debes pasar por esos otros métodos de llamadas en busca de grandes declaraciones de cambio, en caso de que sea el problema específico mencionado en la publicación.