提问人:jmucchiello 提问时间:9/1/2023 最后编辑:user16217248jmucchiello 更新时间:10/11/2023 访问量:103
C# Harmony Transpiler 空字段异常,适用于两个几乎相同的调用之一
C# Harmony Transpiler null field exception for one of two nearly identical calls
问:
这是我的代码。问题在底部:
namespace DifficultyModNS
{
[HarmonyPatch(typeof(Boosterpack),nameof(Boosterpack.Clicked))]
public class OneVillagerChecks
{
public static Int32 frequency = 5;
public static Int32 startChecking = 10;
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
foreach (var instruction in instructions)
{
if (instruction.opcode == OpCodes.Ldc_I4_5)
{
DifficultyMod.Log("Transpiling const 5 to variable");
yield return new CodeInstruction(OpCodes.Ldfld, operand: AccessTools.Field(typeof(Int32), name: "DifficultyModNS.OneVillagerChecks::frequency"));
}
else if (instruction.opcode == OpCodes.Ldc_I4_S && Convert.ToInt32(instruction.operand) == 10)
{
DifficultyMod.Log("Transpiling const 10 to variable");
yield return new CodeInstruction(OpCodes.Ldfld, operand: AccessTools.Field(typeof(Int32), name: "DifficultyModNS.OneVillagerChecks::startChecking"));
}
else
{
yield return instruction;
}
}
}
}
}
打印第一条日志消息。然后,在第二条日志消息之后,有一个异常:
[17:18:44] [Log : difficulty_mod] Transpiling const 5 to variable
[17:18:44] [Log : difficulty_mod] Transpiling const 10 to variable
ArgumentNullException: Invalid argument for ldfld NULL
Parameter name: operand
at HarmonyLib.Internal.Patching.ILManipulator.WriteTo (Mono.Cecil.Cil.MethodBody body, System.Reflection.MethodBase original) [0x001b4] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.HarmonyManipulator.WriteTranspilers () [0x00084] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.HarmonyManipulator.WriteImpl () [0x00031] in <4a2409e6eb214388b8d6ab81d407350d>:0
Rethrow as HarmonyException: IL Compile Error (unknown location)
at HarmonyLib.Public.Patching.HarmonyManipulator.WriteImpl () [0x00382] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.HarmonyManipulator.Process (MonoMod.Cil.ILContext ilContext, System.Reflection.MethodBase originalMethod) [0x00042] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.HarmonyManipulator.Manipulate (System.Reflection.MethodBase original, HarmonyLib.PatchInfo patchInfo, MonoMod.Cil.ILContext ctx) [0x00006] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.HarmonyManipulator.Manipulate (System.Reflection.MethodBase original, MonoMod.Cil.ILContext ctx) [0x00007] in <4a2409e6eb214388b8d6ab81d407350d>:0
at HarmonyLib.Public.Patching.ManagedMethodPatcher.Manipulator (MonoMod.Cil.ILContext ctx) [0x00012] in <4a2409e6eb214388b8d6ab81d407350d>:0
at MonoMod.Cil.ILContext.Invoke (MonoMod.Cil.ILContext+Manipulator manip) [0x00087] in <92bbbc5a09fc417ca7426fbdd31824c2>:0
at MonoMod.RuntimeDetour.ILHook+Context.InvokeManipulator (Mono.Cecil.MethodDefinition def, MonoMod.Cil.ILContext+Manipulator cb) [0x00012] in <925d74c1e4e3467a888e7df55b8370c5>:0
at (wrapper dynamic-method) MonoMod.RuntimeDetour.ILHook+Context.DMD<MonoMod.RuntimeDetour.ILHook+Context::Refresh>(MonoMod.RuntimeDetour.ILHook/Context)
at (wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition.Trampoline<MonoMod.RuntimeDetour.ILHook+Context::Refresh>?1194592624(object)
at HarmonyLib.Internal.RuntimeFixes.StackTraceFixes.OnILChainRefresh (System.Object self) [0x00000] in <4a2409e6eb214388b8d6ab81d407350d>:0
at MonoMod.RuntimeDetour.ILHook.Apply () [0x00059] in <925d74c1e4e3467a888e7df55b8370c5>:0
at HarmonyLib.Public.Patching.ManagedMethodPatcher.DetourTo (System.Reflection.MethodBase replacement) [0x00047] in <4a2409e6eb214388b8d6ab81d407350d>:0
// there's more but it's just additional subsystems rethrowing
为什么当两个字段在同一类中彼此相邻时,其中一个有效而另一个不起作用:
yield return new CodeInstruction(OpCodes.Ldfld, operand: AccessTools.Field(typeof(Int32), name: "DifficultyModNS.OneVillagerChecks::frequency"));
yield return new CodeInstruction(OpCodes.Ldfld, operand: AccessTools.Field(typeof(Int32), name: "DifficultyModNS.OneVillagerChecks::startChecking"));
编辑:我删除了“不起作用”的else if,并且我发现在此函数退出后仍然发生异常。所以现在我想问题是,当名称应该存在时,为什么操作数的 NULL 返回给 Ldfld?
编辑2:我使用了错误的IL指令。Harmony AccessTools 库是获取 FieldInfo 的垃圾。这被替换为 .typeof(OneVillagerChecks).GetField("frequency")
答: 暂无答案
评论
AccessTools.Field
AccessTools.Field