You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Harmony或MonoMod对泛型类的静态非泛型方法做.NET运行时补丁?

如何用Harmony或MonoMod补丁泛型单例的get_Instance方法

你遇到的两个异常本质原因一致:直接尝试补丁未实例化的泛型方法定义(即QSingleton<>的get_Instance),而Harmony和MonoMod都不支持直接操作泛型定义,必须针对具体的泛型实例(比如QSingleton<MyConcreteSingleton>)来打补丁,或者通过反射扫描批量处理所有子类。

Harmony 解决方案

1. 针对具体泛型实例打补丁

如果你明确知道要补丁的具体单例类型(比如MySingleton),直接获取该实例化后的属性get方法即可:

namespace Patch {
    public static class HarmonyPatch {
        public static Harmony harmony = new Harmony("Try");

        public static void init() {
            // 替换为你实际要补丁的具体单例类型
            Type concreteSingletonType = typeof(MySingleton);
            
            // 获取该具体类型的Instance属性get方法
            MethodInfo miOriginal = AccessTools.Property(concreteSingletonType, "Instance").GetMethod;
            // 生成对应的TypeHelper<T>实例方法
            MethodInfo miHack = AccessTools.Method(
                typeof(TypeHelper<>).MakeGenericType(concreteSingletonType), 
                "InstanceHack"
            );
            
            harmony.Patch(miOriginal, prefix: new HarmonyMethod(miHack));
        }
    }
}

// 测试用的具体单例类
public class MySingleton : PatchTarget.QSingleton<MySingleton> { }

2. 自动批量补丁所有QSingleton子类

如果需要自动处理程序集中所有继承自QSingleton<T>的具体单例类型,可以通过反射扫描实现:

namespace Patch {
    public static class HarmonyPatch {
        public static Harmony harmony = new Harmony("Try");

        public static void init() {
            Type qSingletonGenericDef = typeof(PatchTarget.QSingleton<>);
            // 扫描当前程序集所有符合条件的类型
            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) {
                // 过滤:非抽象类、基类是QSingleton<T>的泛型实例
                if (!type.IsAbstract && type.BaseType != null 
                    && type.BaseType.IsGenericType 
                    && type.BaseType.GetGenericTypeDefinition() == qSingletonGenericDef) {
                    
                    MethodInfo miOriginal = AccessTools.Property(type, "Instance").GetMethod;
                    MethodInfo miHack = AccessTools.Method(
                        typeof(TypeHelper<>).MakeGenericType(type), 
                        "InstanceHack"
                    );
                    
                    harmony.Patch(miOriginal, prefix: new HarmonyMethod(miHack));
                }
            }
        }
    }
}

MonoMod 解决方案

MonoMod的处理逻辑和Harmony一致,同样需要针对具体泛型实例:

1. 针对具体泛型实例打补丁

namespace Patch {
    public static class MonoModPatch {
        public static MonoMod.RuntimeDetour.Detour sHook;

        public static void init() {
            Type concreteSingletonType = typeof(MySingleton);
            
            MethodInfo miOriginal = AccessTools.Property(concreteSingletonType, "Instance").GetMethod;
            MethodInfo miHack = AccessTools.Method(
                typeof(TypeHelper<>).MakeGenericType(concreteSingletonType), 
                "InstanceHack"
            );
            
            sHook = new MonoMod.RuntimeDetour.Detour(miOriginal, miHack);
        }
    }
}

// 测试用的具体单例类
public class MySingleton : PatchTarget.QSingleton<MySingleton> { }

2. 自动批量补丁所有QSingleton子类

namespace Patch {
    public static class MonoModPatch {
        public static List<MonoMod.RuntimeDetour.Detour> sHooks = new List<MonoMod.RuntimeDetour.Detour>();

        public static void init() {
            Type qSingletonGenericDef = typeof(PatchTarget.QSingleton<>);
            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) {
                if (!type.IsAbstract && type.BaseType != null 
                    && type.BaseType.IsGenericType 
                    && type.BaseType.GetGenericTypeDefinition() == qSingletonGenericDef) {
                    
                    MethodInfo miOriginal = AccessTools.Property(type, "Instance").GetMethod;
                    MethodInfo miHack = AccessTools.Method(
                        typeof(TypeHelper<>).MakeGenericType(type), 
                        "InstanceHack"
                    );
                    
                    sHooks.Add(new MonoMod.RuntimeDetour.Detour(miOriginal, miHack));
                }
            }
        }
    }
}

原代码报错原因说明

  • Harmony的System.NotSupportedException:Harmony不支持直接补丁泛型方法定义(QSingleton<>),必须针对实例化后的具体泛型方法。
  • MonoMod的System.ArgumentException:MonoMod的Detour要求目标方法是具体的、非泛型定义的方法,传递未实例化的泛型方法会触发参数验证失败。

内容的提问来源于stack exchange,提问作者user2771324

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:40:49