3

尝试调试发出错误,是否有一种简单的方法可以找到有关由发出的代码引起的异常 c 的更多信息?

例如,使用以下代码:

let dynamicAssembly =
    let asmName = new AssemblyName("MyAsm")
    let asmBuilder = AssemblyBuilder.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run)
    let moduleBuilder = asmBuilder.DefineDynamicModule("MyModule")
    let typeBuilder = moduleBuilder.DefineType("MyDynamicType")
    let methodBuilder = 
        let build = typeBuilder.DefineMethod("MyMethod", MethodAttributes.Public, 
                                                CallingConventions.Standard,
                                                typeof<Int32>,
                                                [|typeof<Int32>; typeof<Int32>|])
        let ilGen = build.GetILGenerator()
        ilGen.Emit(OpCodes.Ldarg_0)
        ilGen.Emit(OpCodes.Ldarg_1)
        ilGen.Emit(OpCodes.Add)
        ilGen.Emit(OpCodes.Ret)

    typeBuilder.CreateType() |> ignore
    asmBuilder

let myType = dynamicAssembly.GetType("MyDynamicType")
let myObj = Activator.CreateInstance(myType)
myObj.GetType().GetMethod("MyMethod").Invoke(myObj, [|2; 3|])  |> ignore

当我尝试在倒数第二行调用时,我得到“调用的目标已引发异常Invoke。发出代码一直是有问题的,但如果我能弄清楚如何获得有意义的异常,它可能会不那么痛苦. 想法?

4

1 回答 1

5

获得无用的异常是生成 IL 代码的一部分乐趣。当您收到“调用的目标已引发异常”时,您可以查看该InnerException属性,看看是否可以在那里获得更有用的东西:

try
  myObj.GetType().GetMethod("MyMethod").Invoke(myObj, [|2; 3|])  |> printfn "%A"
with 
  e -> printfn "%A" e.InnerException

在这种情况下,内部异常说:

System.InvalidProgramException:公共语言运行时检测到无效程序。

这仅仅意味着您生成的 IL 是错误的 - 恐怕您不会得到更好的错误消息,但您可以将生成的程序集保存到磁盘并运行peverify或 Reflector/ILSpy 以查看它们将如何解释生成的代码。这意味着您需要添加另一个代码路径来生成正确的(非动态)程序集,但我认为这是值得的——您需要经常调试生成的 IL...

在这种情况下,问题在于Ldarg_0引用this(而不是第一个参数),因此您需要生成:

ilGen.Emit(OpCodes.Ldarg_1)
ilGen.Emit(OpCodes.Ldarg_2)
ilGen.Emit(OpCodes.Add)
ilGen.Emit(OpCodes.Ret)
于 2013-03-19T01:08:48.690 回答