Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 塞西尔:尝试/最终?_.net_Mono.cecil - Fatal编程技术网

.net 塞西尔:尝试/最终?

.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;

对实现try/catch-in有很好的概述,但他在没有完成完整的try/catch/finally之前就停了下来。那么,如何使用Mono.Cecil实现try/finally呢?

下面是如何注入finally

首先,您需要修复返回语句。你只想要一个

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();
}