Ilgenerator Catching Excepciones no funciona
-
28-10-2019 - |
Pregunta
Estoy generando envoltorios para tipos usando System.Reflection.Emit
. En un momento es posible que el objeto original esté lanzando un error al acceso ( FaultException
) y el error debe ser captado por mi try { } catch (Exception e) { }
que he implementado, pero no lo hace.
El código se muestra correctamente por Ilspy.
try
{
if (original.Station != null)
{
if (objectDictionary.ContainsKey(original.Station))
{
this.Station = (objectDictionary[original.Station] as StationWrapper);
}
else
{
this.Station = new StationWrapper(original.Station, objectDictionary);
}
}
}
catch (Exception arg_6D_0)
{
ReportManager.Log(arg_6D_0);
}
Codigo de GENERACION
Este es el código para la generación de ensamblaje.
Label ex = il.BeginExceptionBlock();
....
// Exception block end
il.Emit(OpCodes.Leave, ex);
il.BeginCatchBlock(typeof(Exception));
il.Emit(OpCodes.Call, ReportManager_Log);
il.EndExceptionBlock();
Editar
La excepción es ser atrapada por el código de usuario pero no por el código IL.
Desmontaje
Eliminó algunos espacios de nombres del cliente aquí. La línea de escritura se ha agregado los últimos minutos.
.try
{
IL_0019: ldarg.1
IL_001a: call instance class [...]...Station [...]...StationBase::get_Station()
IL_001f: brfalse IL_0063
IL_0024: ldarg.2
IL_0025: ldarg.1
IL_0026: call instance class [...]...Station [...]...StationBase::get_Station()
IL_002b: call instance bool class [mscorlib]System.Collections.Generic.Dictionary`2<object, object>::ContainsKey(!0)
IL_0030: brfalse IL_0051
IL_0035: ldarg.0
IL_0036: ldarg.2
IL_0037: ldarg.1
IL_0038: call instance class [...]...Station [...]...StationBase::get_Station()
IL_003d: call instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<object, object>::get_Item(!0)
IL_0042: isinst ...StationWrapper
IL_0047: call instance void ...StationBaseWrapper::set_Station(class ...StationWrapper)
IL_004c: br IL_0063
IL_0051: ldarg.0
IL_0052: ldarg.1
IL_0053: call instance class [...]...Station [...]...StationBase::get_Station()
IL_0058: ldarg.2
IL_0059: newobj instance void ....StationWrapper::.ctor(class [...]...Station, class [mscorlib]System.Collections.Generic.Dictionary`2<object, object>)
IL_005e: call instance void ...StationBaseWrapper::set_Station(class ...StationWrapper)
IL_0063: leave IL_007c
} // end .try
catch [mscorlib]System.Exception
{
IL_0068: ldstr "Its comming home"
IL_006d: call void [mscorlib]System.Console::WriteLine(string)
IL_0072: call void [...Report]...ReportManager::Log(class [mscorlib]System.Exception)
IL_0077: leave IL_007c
} // end handler
Edición 2
Al lanzar un System.Exception
en código IL, antes del FaultException'1
Puede ocurrir, la excepción se maneja. Probado con Exception
y ArgumentException
.
Solución 2
En realidad, este parece ser un error visual-studio 2010. Todas las excepciones se ignoran en VS cuando se atrapan, pero VS muestra la excepción de todos modos.
No se ignoran todas las excepciones, esto parece depender del código que arroja la excepción. Se ignoran las excepciones generadas (a través de EMIT), las excepciones que son de una DLL externa no se ignoran.
Otros consejos
Todo funciona bien aquí; ¿Estás seguro de que no es un bloque de excepción anidado?
Ejemplo:
using System;
using System.Reflection.Emit;
public class Test
{
static void Main()
{
var dm = new DynamicMethod("foo", null, new[] {typeof(bool)});
var il = dm.GetILGenerator();
Label ex = il.BeginExceptionBlock();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, typeof(Test).GetMethod("Throw"), null);
il.Emit(OpCodes.Leave, ex);
il.BeginCatchBlock(typeof(Exception));
il.EmitCall(OpCodes.Call, typeof(Test).GetMethod("Log"), null);
il.EndExceptionBlock();
il.Emit(OpCodes.Ldstr, "done");
il.EmitCall(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
new[] {typeof(string)}), null);
il.Emit(OpCodes.Ret);
var act = (Action<bool>)dm.CreateDelegate(typeof (Action<bool>));
Console.WriteLine("Expect success:");
act(false);
Console.WriteLine("Expect fail:");
act(true);
Console.WriteLine("(all done)");
}
public static void Throw(bool fatal)
{
if(fatal) throw new InvalidOperationException("Boom!");
}
public static void Log(Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}