Mono.Cecil과 함께 예외 처리기를 추가하는 것은 어렵지 않으며 예외 처리기가 메타 데이터에 배치되는 방법을 알아야합니다. 당신이 그것을 컴파일하면
static void Throw()
{
throw new Exception ("oups");
}
, 그것은이 다소 유사합니다 :
하자 당신이 C#을 방법이 있다고
.method private static hidebysig default void Throw() cil managed
{
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::.ctor(string)
IL_000a: throw
}
이제이 코드를 삽입 할 것을 가정 해 봅시다 메서드는 C# 코드와 비슷합니다.
static void Throw()
{
try {
throw new Exception ("oups");
} catch (Exception e) {
Console.WriteLine (e);
}
}
즉, 기존 코드를 try catch 핸들러.
var method = ...;
var il = method.Body.GetILProcessor();
var write = il.Create (
OpCodes.Call,
module.Import (typeof (Console).GetMethod ("WriteLine", new [] { typeof (object)})));
var ret = il.Create (OpCodes.Ret);
var leave = il.Create (OpCodes.Leave, ret);
il.InsertAfter (
method.Body.Instructions.Last(),
write);
il.InsertAfter (write, leave);
il.InsertAfter (leave, ret);
var handler = new ExceptionHandler (ExceptionHandlerType.Catch) {
TryStart = method.Body.Instructions.First(),
TryEnd = write,
HandlerStart = write,
HandlerEnd = ret,
CatchType = module.Import (typeof (Exception)),
};
method.Body.ExceptionHandlers.Add (handler);
이 코드는 다음과 같이하는 이전 방법을 조작한다 : 우리는 세 개의 새로운 명령어를 추가하는
.method private static hidebysig default void Throw() cil managed
{
.maxstack 1
.try { // 0
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::'.ctor'(string)
IL_000a: throw
} // end .try 0
catch class [mscorlib]System.Exception { // 0
IL_000b: call void class [mscorlib]System.Console::WriteLine(object)
IL_0010: leave IL_0015
} // end handler 0
IL_0015: ret
}
: 당신은 세실 쉽게 이런 식으로 그것을 할 수 Console.WriteLine을 호출 , 캐치 핸들러를 정상적으로 나가기위한 휴가, 마침내 (말장난 의도), ret. 그런 다음 ExceptionHandler 인스턴스를 작성하여 try가 기존 본문을 포함하고 catch가 WriteLine 문인 try catch 핸들러를 나타냅니다.
한 가지 중요한 점은 범위의 끝 명령이 범위 내에 포함되지 않는다는 것입니다. 그것은 기본적으로 [TryStart : TryEnd [범위.
제어 흐름이 이와 같은 catch 처리기에서 벗어날 수 없습니다. ECMA-335, §12.4.2.8.1 "보호 된 블록, 필터 또는 처리기를 종료 할 때 가을을 통해 수행 할 수 없습니다." (Microsoft CLR은이 규칙을 적용하지 않는 것 같지만) – Daniel
@Daniel, 좋은 소식, 누락 된 휴가를 추가하겠습니다. 머리를 가져 주셔서 감사합니다. –
이 빠른 답변에 감사드립니다! 잘 작동 - 그리고 너무 쉽게! 대단히 감사합니다! – cyptus