C# ILGenerator捕获异常不';行不通

C# ILGenerator捕获异常不';行不通,c#,exception-handling,reflection.emit,ilgenerator,C#,Exception Handling,Reflection.emit,Ilgenerator,我正在使用System.Reflection.Emit为类型生成包装。在某一点上,可能原始对象在访问时抛出错误(FaultException),错误应该由我已经实现的try{}catch(Exception e){}捕获,但它没有 代码正确显示为 代码生成 这是程序集生成的代码 Label ex = il.BeginExceptionBlock(); .... // Exception block end il.Emit(OpCodes.Leave, ex); il.BeginCatchBloc

我正在使用
System.Reflection.Emit
为类型生成包装。在某一点上,可能原始对象在访问时抛出错误(
FaultException
),错误应该由我已经实现的
try{}catch(Exception e){}
捕获,但它没有

代码正确显示为

代码生成 这是程序集生成的代码

Label ex = il.BeginExceptionBlock();
....
// Exception block end
il.Emit(OpCodes.Leave, ex);
il.BeginCatchBlock(typeof(Exception));
il.Emit(OpCodes.Call, ReportManager_Log);
il.EndExceptionBlock();
编辑 异常被用户代码捕获,但不被IL代码捕获

拆卸 在此处删除了客户的一些名称空间。写入行已在最后几分钟添加

.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
。试试看
{
IL_0019:ldarg.1
IL_001a:调用实例类[…]…站[…]…StationBase::get_Station()
IL_001f:brfalse IL_0063
IL_0024:ldarg.2
IL_0025:ldarg.1
IL_0026:调用实例类[…]…站[…]…StationBase::get_Station()
IL_002b:调用实例bool类[mscorlib]System.Collections.Generic.Dictionary`2::ContainsKey(!0)
IL_0030:brfalse IL_0051
IL_0035:ldarg.0
IL_0036:ldarg.2
IL_0037:ldarg.1
IL_0038:调用实例类[…]…站[…]…StationBase::get_Station()
IL_003d:调用实例!1类[mscorlib]System.Collections.Generic.Dictionary`2::get_项(!0)
IL_0042:isinst…站包装器
IL_0047:调用实例void…StationBaseWrapper::set_Station(类…StationWrapper)
IL_004c:br IL_0063
IL_0051:ldarg.0
IL_0052:ldarg.1
IL_0053:调用实例类[…]…站[…]…StationBase::get_Station()
IL_0058:ldarg.2
IL_0059:newobj实例void…StationWrapper::.ctor(类[…]…站,类[mscorlib]System.Collections.Generic.Dictionary`2)
IL_005e:调用实例void…StationBaseWrapper::set_Station(类…StationWrapper)
IL_0063:离开IL_007c
}//结束,再试一次
捕获[mscorlib]System.Exception
{
IL_0068:ldstr“它即将到家”
IL_006d:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0072:调用void[…Report]…ReportManager::Log(类[mscorlib]System.Exception)
IL_0077:离开IL_007c
}//结束处理程序
编辑2
在IL代码中抛出
System.Exception
时,在发生
FaultException'1
之前,将处理异常。使用
异常测试
参数异常测试

在这里一切正常;您确定它不是嵌套的异常块吗

例如:

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);
    }
}
使用系统;
使用System.Reflection.Emit;
公开课考试
{
静态void Main()
{
var dm=newdynamicmethod(“foo”,null,new[]{typeof(bool)});
var il=dm.GetILGenerator();
Label ex=il.beginceptionblock();
il.Emit(操作码.Ldarg_0);
EmitCall(OpCodes.Call,typeof(Test).GetMethod(“Throw”),null;
il.Emit(操作码、休假、ex);
il.BeginCatchBlock(类型(例外));
EmitCall(opcode.Call,typeof(Test).GetMethod(“Log”),null;
il.EndExceptionBlock();
il.Emit(opcode.Ldstr,“完成”);
EmitCall(OpCodes.Call,typeof(Console).GetMethod(“WriteLine”,
新[]{typeof(string)},空);
发射(操作码Ret);
var act=(Action)dm.CreateDelegate(typeof(Action));
Console.WriteLine(“期望成功:”);
行为(虚假);
Console.WriteLine(“预期失败:”);
行为(真实);
Console.WriteLine(“(全部完成)”);
}
公共静态无效抛出(bool致命)
{
如果(致命)抛出新的InvalidOperationException(“Boom!”);
}
公共静态无效日志(例外情况除外)
{
Console.WriteLine(“错误:+ex.Message”);
}
}

这实际上似乎是Visual Studio 2010的一个bug。捕获时,VS中的所有异常都会被忽略,但VS仍会显示异常

并非所有异常都被忽略,这似乎取决于引发异常的代码。
生成的异常(通过Emit)被忽略,来自外部DLL的异常不会被忽略。

绝对地,我用另一个包装器复制了相同的错误。调用堆栈指向
Station
-属性的
get_Station
-方法,此访问位于
try catch
块内。
FaultException'1
异常正在进行。@Felix困难在于:我使用了您问题中的所有IL生成了一个工作样本;对我来说,其他任何东西都是纯粹的发明,毫无帮助。我建议您使用工作版本(如上),并一点一点地进行调整,直到重现问题。然后你就知道该去哪里找了。@FelixK我当然假设
ReportManager\u Log
实际上是一个方法信息?是的,异常被用户代码捕获了。但不是我的密码。所以它的老问题。@ Felixk,有没有可能是C++投掷的东西不是一个例外,而你是自动包装被禁用?对于信息,我已经用FrutExExcel测试了我的样本,它仍然很好用;坦白地说,我不确定我们能做什么,除非你能提供一个失败的例子。我仅有的一个例子(确实是:使用你的代码)工作得很好。那么:问题中没有提到的真实场景有什么不同呢?@MarcGravel发现这似乎是一个VS2010错误,异常显示为未捕获,但在继续应用程序时被异常块捕获(没有注意到这一点,因为我有一个未捕获的异常处理程序)。不知道为什么会发生这种情况,它是一个外部dll,甚至VS中的异常都被禁用。未显示其他例外情况。
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);
    }
}