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最後から 2 行目で呼び出そうとすると、「呼び出しのターゲットによって例外がスローされました。 . 感想?

4

1 に答える 1

5

役に立たない例外を取得することは、IL コードを生成する楽しみの 1 つです。「呼び出しのターゲットによって例外がスローされました」というメッセージが表示されInnerExceptionたら、プロパティを見て、より便利なものを取得できるかどうかを確認できます。

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

この場合、内部例外は次のように述べています。

System.InvalidProgramException: 共通言語ランタイムが無効なプログラムを検出しました。

これは単に、生成された IL が間違っていることを意味します - より良いエラー メッセージが表示されることはないと思いますが、生成されたアセンブリをディスクに保存し、peverifyReflector/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 に答える