{"record":{"id":"c62ff304d613ce18","repo":"egametang/ET","slug":"wraning-you-can-not-hook-abstract-method-method","errorCode":null,"errorMessage":"WRANING: you can not hook abstract method [{methodName}]","messagePattern":"WRANING: you can not hook abstract method \\[(.+?)\\]","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs","lineNumber":192,"sourceCode":"                    UnityEngine.Debug.Log($\"New [{targetMethod.DeclaringType.Name}.{targetMethod.Name}]: {HookUtils.HexToString(_targetPtr.ToPointer(), 64, -16)}\");\n                    UnityEngine.Debug.Log($\"New [{replacementMethod.DeclaringType.Name}.{replacementMethod.Name}]: {HookUtils.HexToString(_replacementPtr.ToPointer(), 64, -16)}\");\n                    if(proxyMethod != null)\n                        UnityEngine.Debug.Log($\"New [{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}]: {HookUtils.HexToString(_proxyPtr.ToPointer(), 64, -16)}\");\n#endif\n                }\n            }\n\n            isHooked = true;\n        }\n\n        private void CheckMethod()\n        {\n            if (targetMethod == null || replacementMethod == null)\n                throw new Exception(\"MethodHook:targetMethod and replacementMethod and proxyMethod can not be null\");\n\n            string methodName = $\"{targetMethod.DeclaringType.Name}.{targetMethod.Name}\";\n            if (targetMethod.IsAbstract)\n                throw new Exception($\"WRANING: you can not hook abstract method [{methodName}]\");\n\n#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER\n            int minMethodBodySize = 10;\n\n            {\n                if ((targetMethod.MethodImplementationFlags & MethodImplAttributes.InternalCall) != MethodImplAttributes.InternalCall)\n                {\n                    int codeSize = targetMethod.GetMethodBody().GetILAsByteArray().Length; // GetMethodBody can not call on il2cpp\n                    if (codeSize < minMethodBodySize)\n                        UnityEngine.Debug.LogWarning($\"WRANING: you can not hook method [{methodName}], cause its method body is too short({codeSize}), will random crash on IL2CPP release mode\");\n                }\n            }\n\n            if(proxyMethod != null)\n            {\n                methodName = $\"{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}\";\n                int codeSize = proxyMethod.GetMethodBody().GetILAsByteArray().Length;\n                if (codeSize < minMethodBodySize)","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/MethodHook.cs#L174-L210","documentation":"Thrown by MethodHook.CheckMethod() when targetMethod.IsAbstract is true. Abstract methods (including interface methods without an implementation) have no method body — no IL code and no native code to patch. Code patching hooks work by overwriting the prologue of the target method's compiled code, so hooking an abstract method is fundamentally impossible.","triggerScenarios":"CheckMethod() is called on a MethodHook whose targetMethod is an abstract method — e.g. a method declared on an abstract class without implementation, or an interface member. The IsAbstract property returns true and the exception fires.","commonSituations":"Attempting to hook an interface method instead of its concrete implementation; hooking an abstract base class method that has no body; the type was refactored and a previously-concrete method became abstract; confusion between the interface declaration and the implementing class's override.","solutions":["Hook the concrete implementation method instead of the abstract/interface declaration — find the class that actually implements the method.","If you need to intercept all implementations, hook each override individually or use a higher-level interception pattern.","Check targetMethod.DeclaringType.IsAbstract and targetMethod.IsAbstract before constructing the hook and skip or log a warning.","If hooking a virtual method on a base class, ensure it has a body (non-abstract) — virtual methods with bodies can be hooked."],"exampleFix":"// before — hooking an abstract method throws\nvar target = typeof(IRepository).GetMethod(\"Save\");\nvar hook = new MethodHook(target, replacement);\nhook.CheckMethod();\n\n// after — hook the concrete implementation\nvar target = typeof(SqlRepository).GetMethod(\"Save\"); // concrete override\nvar hook = new MethodHook(target, replacement);\nhook.CheckMethod();","handlingStrategy":"validation","validationCode":"if (targetMethod.IsAbstract)\n{\n    Debug.LogError($\"Cannot hook abstract method '{targetMethod.DeclaringType.Name}.{targetMethod.Name}'. \" +\n        \"Hook the concrete implementation instead.\");\n    return;\n}","typeGuard":"static bool IsHookableMethod(MethodInfo method)\n{\n    return method != null && !method.IsAbstract;\n}","tryCatchPattern":"try\n{\n    hook.CheckMethod();\n}\ncatch (Exception ex) when (ex.Message.Contains(\"abstract method\"))\n{\n    Debug.LogError($\"Cannot hook abstract method. Find the concrete override on the implementing class \" +\n        $\"and hook that instead. Target was: {targetMethod.DeclaringType.Name}.{targetMethod.Name}\");\n}","preventionTips":["Never attempt to hook interface methods or abstract declarations directly.","Before hooking, check targetMethod.IsAbstract and redirect to the concrete implementation.","When hooking virtual methods, verify they have a body (non-abstract overrides are fine).","Use targetMethod.DeclaringType to determine if you are targeting an interface/abstract class by mistake."],"tags":["unityhook","method-hook","abstract-method","reflection","unsupported"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}