.net 塞西尔:尝试/最终?
对实现try/catch-in有很好的概述,但他在没有完成完整的try/catch/finally之前就停了下来。那么,如何使用Mono.Cecil实现try/finally呢?下面是如何注入finally 首先,您需要修复返回语句。你只想要一个.net 塞西尔:尝试/最终?,.net,mono.cecil,.net,Mono.cecil,对实现try/catch-in有很好的概述,但他在没有完成完整的try/catch/finally之前就停了下来。那么,如何使用Mono.Cecil实现try/finally呢?下面是如何注入finally 首先,您需要修复返回语句。你只想要一个 Instruction FixReturns() { if (Method.ReturnType == TypeSystem.Void) { var instructions = body.Instructions;
Instruction FixReturns()
{
if (Method.ReturnType == TypeSystem.Void)
{
var instructions = body.Instructions;
var lastRet = Instruction.Create(OpCodes.Ret);
instructions.Add(lastRet);
for (var index = 0; index < instructions.Count - 1; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastRet);
}
}
return lastRet;
}
else
{
var instructions = body.Instructions;
var returnVariable = new VariableDefinition("methodTimerReturn", Method.ReturnType);
body.Variables.Add(returnVariable);
var lastLd = Instruction.Create(OpCodes.Ldloc, returnVariable);
instructions.Add(lastLd);
instructions.Add(Instruction.Create(OpCodes.Ret));
for (var index = 0; index < instructions.Count - 2; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastLd);
instructions.Insert(index, Instruction.Create(OpCodes.Stloc, returnVariable));
index++;
}
}
return lastLd;
}
}
然后把它缝在一起
void InnerProcess()
{
body = Method.Body;
body.SimplifyMacros();
ilProcessor = body.GetILProcessor();
var returnInstruction = FixReturns();
var firstInstruction = FirstInstructionSkipCtor();
var beforeReturn = Instruction.Create(OpCodes.Nop);
ilProcessor.InsertBefore(returnInstruction, beforeReturn);
InjectIlForFinaly(returnInstruction);
var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
{
TryStart = firstInstruction,
TryEnd = beforeReturn,
HandlerStart = beforeReturn,
HandlerEnd = returnInstruction,
};
body.ExceptionHandlers.Add(handler);
body.InitLocals = true;
body.OptimizeMacros();
}
发现检查过的示例内容丰富且有用。但是,在更复杂的条件下,确实遇到了问题。在FixReturns()中,无论是void还是non-void返回作用域,通过创建新指令来更改ret->leave的方法都会删除原始指令。这可能会将其他指令作为操作数留给孤立指令(例如,分支到原始ret)。结果代码最终无效 我们只是简单地更新了现有ret指令的操作码/操作数对,而不是创建新的操作码/操作数对,所有这些看起来都很好
干杯。所以这基本上与那篇文章中描述的过程相同,只是将ExceptionHandlerType.Finally传递到新的ExceptionHandler()。如果您想要try/catch/finally,您将创建两个“ExceptionHandler”实例并将它们添加到方法中,一个用于catch,一个用于finally。如果是这种情况,那么名称肯定会令人困惑,因为您并没有真正创建新的异常处理程序,至少对于“finally”。谢谢你的指点。
void InnerProcess()
{
body = Method.Body;
body.SimplifyMacros();
ilProcessor = body.GetILProcessor();
var returnInstruction = FixReturns();
var firstInstruction = FirstInstructionSkipCtor();
var beforeReturn = Instruction.Create(OpCodes.Nop);
ilProcessor.InsertBefore(returnInstruction, beforeReturn);
InjectIlForFinaly(returnInstruction);
var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
{
TryStart = firstInstruction,
TryEnd = beforeReturn,
HandlerStart = beforeReturn,
HandlerEnd = returnInstruction,
};
body.ExceptionHandlers.Add(handler);
body.InitLocals = true;
body.OptimizeMacros();
}