Harmony项目中的方法执行流程解析

Harmony项目中的方法执行流程解析

【免费下载链接】Harmony A library for patching, replacing and decorating .NET and Mono methods during runtime 【免费下载链接】Harmony 项目地址: https://gitcode.com/gh_mirrors/ha/Harmony

前言

在软件开发中,我们经常需要修改已有方法的行为而不改变原始代码。Harmony作为一个强大的方法补丁库,提供了这种能力。本文将深入解析Harmony如何处理方法的执行流程,帮助开发者理解其内部工作原理。

Harmony补丁执行概述

Harmony的核心思想是创建一个"替换方法"来包装原始方法,而不是直接覆盖它。这种设计允许多个补丁共存并按特定顺序执行。Harmony支持四种主要补丁类型:

  1. Prefix(前缀):在原始方法前执行
  2. Postfix(后缀):在原始方法后执行
  3. Transpiler(转换器):修改原始方法的IL代码
  4. Finalizer(终结器):处理异常和最终清理

无Finalizer补丁的执行流程

当方法不包含Finalizer补丁时,执行流程相对简单:

static R ReplacementMethod(T optionalThisArgument, params object[] arguments)
{
    R result = default;
    var run = true;

    // 执行所有无副作用的前缀补丁
    SimplePrefix1(arguments);
    
    // 执行可能影响结果的前缀补丁
    if (run) run = Prefix2();
    
    // 更多前缀补丁...
    
    // 如果所有前缀都允许,执行原始方法
    if (run) result = ModifiedOriginal(arguments);

    // 执行所有后缀补丁
    Postfix1(ref result);
    result = Postfix2(result, arguments);
    // 更多后缀补丁...

    return result;
}

关键点解析

  1. 前缀补丁分类

    • 无副作用前缀:总是执行,不影响原始方法是否运行
    • 有副作用前缀:可能通过返回值控制原始方法是否执行
  2. ModifiedOriginal

    • 这是原始方法经过所有Transpiler补丁修改后的版本
    • 在打补丁时一次性生成,运行时直接调用
  3. 执行控制

    • 任何有副作用的前缀返回false会跳过后续有副作用前缀和原始方法
    • 后缀补丁总是执行(除非抛出异常)

包含Finalizer补丁的执行流程

当方法包含Finalizer补丁时,执行流程会变得更加复杂,因为需要处理异常情况:

static R ReplacementMethod(T optionalThisArgument /*, ... arguments ... */ )
{
    R result = default;
    var finalized = false;
    Exception ex = null;

    try
    {
        result = Original(/* ... arguments ... */);

        // 正常流程下的Finalizer调用
        SimpleFinalizer(ref result);
        ex = EditFinalizer(ex, ref result);
        finalized = true;

        if (ex is not null) throw ex;
        return result;
    }
    catch (Exception e)
    {
        ex = e;
        
        // 异常情况下的Finalizer调用(保证执行)
        if (!finalized)
        {
            try { SimpleFinalizer(ref result); } catch { }
            try { ex = EditFinalizer(ex, ref result); } catch { }
        }

        // 根据Finalizer类型决定如何重新抛出异常
        if (allVoid)
        {
            throw;  // 所有Finalizer返回void,直接重新抛出
        }
        else
        {
            if (ex is not null) throw ex;  // 有Finalizer修改了异常
        }

        return result;
    }
}

关键点解析

  1. 异常处理机制

    • Finalizer补丁保证执行,无论原始方法是否抛出异常
    • 第一次Finalizer调用可能在正常流程中抛出异常
    • 第二次Finalizer调用在catch块中,确保最终执行
  2. 异常修改

    • Finalizer可以通过返回值修改要抛出的异常
    • 返回null表示不抛出异常
    • 返回新异常对象将替换原始异常
  3. 性能考虑

    • 无Finalizer时,不引入try-catch开销
    • 有Finalizer时,才添加异常处理逻辑

实际应用建议

  1. Prefix使用场景

    • 修改方法参数
    • 完全替换方法逻辑(返回false跳过原始方法)
    • 执行前置验证
  2. Postfix使用场景

    • 修改方法返回值
    • 记录方法调用信息
    • 执行后置处理
  3. Finalizer使用场景

    • 资源清理
    • 异常日志记录
    • 异常转换(如将底层异常包装为业务异常)
  4. 性能优化

    • 避免不必要的Finalizer,以减少try-catch开销
    • 将无副作用的前缀标记为void返回类型

总结

Harmony的执行流程设计既灵活又高效,通过动态生成替换方法实现了多种补丁的协同工作。理解这些执行细节有助于开发者编写更可靠、更高效的补丁代码,也能帮助调试复杂的补丁交互问题。无论是简单的日志记录还是复杂的业务逻辑修改,Harmony都提供了相应的机制来满足需求。

【免费下载链接】Harmony A library for patching, replacing and decorating .NET and Mono methods during runtime 【免费下载链接】Harmony 项目地址: https://gitcode.com/gh_mirrors/ha/Harmony

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值