Я пытаюсь использовать Harmony 2.3.3 с Godot 4.2.1, и в редакторе он работает как положено, но не в экспортированной сборке.
Я пытаюсь исправить префикс метода, и в редакторе метод успешно исправлен, но в экспортированной сборке метод не удается исправить, и выдается следующее исключение:
System.ArgumentException: GenericArguments[0], 'MonoMod.Utils.Cil.CecilILGenerator', on 'MonoMod.Utils.Cil.ILGeneratorProxy[TTarget]' violates the constraint of type 'TTarget'.
---> System.TypeLoadException: GenericArguments[0], 'MonoMod.Utils.Cil.CecilILGenerator', on 'MonoMod.Utils.Cil.ILGeneratorProxy[TTarget]' violates the constraint of type parameter 'TTarget'.
at System.RuntimeTypeHandle.Instantiate(RuntimeType inst)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
--- End of inner exception stack trace ---
at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
at MonoMod.Utils.Cil.ILGeneratorShim.GetProxy()
at MonoMod.Utils.DynamicMethodDefinition.GetILGenerator()
at HarmonyLib.MethodPatcher..ctor(MethodBase original, MethodBase source, List`1 prefixes, List`1 postfixes, List`1 transpilers, List`1 finalizers, Boolean debug)
at HarmonyLib.PatchFunctions.UpdateWrapper(MethodBase original, PatchInfo patchInfo)
at HarmonyLib.PatchProcessor.Patch()
at HarmonyLib.Harmony.Patch(MethodBase original, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod transpiler, HarmonyMethod finalizer)
at HarmonyTester.Test() in G:\Godot Projects\HarmonyExportIssue\HarmonyTesting\HarmonyTester.cs:line 24
Кажется, это какая-то проблема с зависимостями, как обсуждалось в этой проблеме на Harmony Github, но я понятия не имею, куда идти дальше и как решить эту проблему.
После дополнительных исследований выяснилось, что это известная проблема с Godot и внешними файлами .dll. https://github.com/godotengine/godot/issues/75160
Это можно обойти, используя отражение, как описано в этом ответе: https://github.com/godotengine/godot/issues/75160#issuecomment-2071203840
public partial class ModLoader : Node
{
public override void _Ready()
{
string modPath = ProjectSettings.GlobalizePath("user://TestMod.dll");
var alc = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly());
Assembly assembly = alc.LoadFromAssemblyPath(modPath);
Type t = assembly.GetType("TestMod.TestModInit");
t.GetMethod("Init")?.Invoke(null, null);
}
}
Обратите внимание, что во время выполнения вам нужно будет получить файл dll, используя
OS.GetExecutablePath().GetBaseDir().PathJoin(file: "dllname.dll")
вместо