HarmonyX
HarmonyX copied to clipboard
TypeLoadException when patching a method in a class, which inherits a class that has a generic argument of type enum
Describe the bug I want to patch a method which is residing in a class, that inherits from a class which has a generic argument of 'T' where 'T' is enum.
To Reproduce I compiled a little package with a simple repro.
You can download the zip file here: https://we.tl/t-yfbtmiVmA5
The packaged game is prepatched with MelonLoader 0.6.1
Steps to reproduce the behavior:
- The original method and its signature and class
using System;
using UnityEngine;
public enum GameScreen
{
Title = 0,
Game = 1,
}
public class MyGameScreen : GameScreen<GameScreen>
{
private int _something = 0;
public void SetSomething(int i)
{
_something = i;
}
void Start()
{
}
void Update()
{
}
}
public class GameScreen<T> : MonoBehaviour where T : Enum
{
}
- The patch code
[HarmonyPatch(typeof(MyGameScreen), "SetSomething", new Type[] { typeof(int) })]
public static class Patch
{
private static void Prefix()
{
// The code inside this method will run before 'PrivateMethod' is executed
}
private static void Postfix()
{
// The code inside this method will run after 'PrivateMethod' has executed
}
}
public class Mod : MelonMod
{
}
Errors:
[14:48:45.178] [PWS_Tool_Mod] System.TypeLoadException: GenericArguments[0], 'Il2Cpp.GameScreen', on 'Il2Cpp.GameScreen`1[T]' violates the constraint of type parameter 'T'.
at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, RuntimeType type, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
at System.RuntimeType.GetCustomAttributes(Boolean inherit)
at HarmonyLib.HarmonyMethodExtensions.GetFromType(Type type)
at HarmonyLib.PatchClassProcessor..ctor(Harmony instance, Type type, Boolean allowUnannotatedType)
at HarmonyLib.PatchClassProcessor..ctor(Harmony instance, Type type)
at HarmonyLib.Harmony.CreateClassProcessor(Type type)
at HarmonyLib.Harmony.<PatchAll>b__11_0(Type type)
at HarmonyLib.CollectionExtensions.Do[T](IEnumerable`1 sequence, Action`1 action)
at HarmonyLib.Harmony.PatchAll(Assembly assembly)
at MelonLoader.MelonMod.HarmonyInit() in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\MelonMod.cs:line 40
at MelonLoader.MelonEvent.<>c.<Invoke>b__1_0(LemonAction x) in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\Events\MelonEvent.cs:line 174
at MelonLoader.MelonEventBase`1.Invoke(Action`1 delegateInvoker) in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\Events\MelonEvent.cs:line 143
Expected behavior It should not error..?
Screenshots / Code Not much to say here. I originally intend to patch a game which uses the same unity version, the same code structure etc.
Runtime environment (please complete the following information):
- OS: Windows 11
- .NET version: .NET Standard
- Harmony version: 2.10.1.0
- Name of game or host application: doesn't matter, I included a custom made sample which reproduces the same error as in the game
Additional context Add any other context about the problem here.
It seems that the issue lies within how Il2CPP code is generated, maybe it can't be done in HarmonyX?
I added a reproducible branch here: https://github.com/btastic/HarmonyX/tree/generics_il2cpp (it includes some IL2CPP dll files)
I added a new test class GenericsFromIl2Cpp
which will fail with the error message I wrote earlier
Il2CPP code could in theory be changed to allow this, so that all instances of Il2CPPSystem.Enum are replaced with System.Enum. This would, however, be a breaking change, and it would mean that methods of the Enum class itself could no longer be patched.
I wonder if the best plan is to introduce some sort of equivalent to each type of enum that inherits from Il2CPPSystem.Enum, that can be used as a parameter? Maybe GenericType<AnEnum>
is replaced with GenericType<Il2CPPReferenceEnum<AnEnum>>
, or something like that?
Was there any progress on that? Im facing a similar issue