diff --git a/Harmony/Internal/CodeTranspiler.cs b/Harmony/Internal/CodeTranspiler.cs index 8f0d31ad..a59030c1 100644 --- a/Harmony/Internal/CodeTranspiler.cs +++ b/Harmony/Internal/CodeTranspiler.cs @@ -191,11 +191,16 @@ internal static IEnumerable ConvertToOurInstructions(IEnumerable instructions, T } } + static bool IsCodeInstructionsParameter(Type type) + { + return type.IsGenericType && type.GetGenericTypeDefinition().Name.StartsWith("IEnumerable", StringComparison.Ordinal); + } + internal static IEnumerable ConvertToGeneralInstructions(MethodInfo transpiler, IEnumerable enumerable, out Dictionary> unassignedValues) { var type = transpiler.GetParameters() .Select(p => p.ParameterType) - .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition().Name.StartsWith("IEnumerable", StringComparison.Ordinal)); + .FirstOrDefault(t => IsCodeInstructionsParameter(t)); return ConvertInstructionsAndUnassignedValues(type, enumerable, out unassignedValues); } @@ -208,7 +213,7 @@ internal static List GetTranspilerCallParameters(ILGenerator generator, parameter.Add(generator); else if (type.IsAssignableFrom(typeof(MethodBase))) parameter.Add(method); - else + else if (IsCodeInstructionsParameter(type)) parameter.Add(instructions); }); return parameter; diff --git a/Harmony/Internal/MethodCopier.cs b/Harmony/Internal/MethodCopier.cs index 2914b02d..69a528ce 100644 --- a/Harmony/Internal/MethodCopier.cs +++ b/Harmony/Internal/MethodCopier.cs @@ -67,13 +67,18 @@ internal MethodBodyReader(MethodBase method, ILGenerator generator) var body = method.GetMethodBody(); if (body == null) - throw new ArgumentException($"Method {method.FullDescription()} has no body"); - - var bytes = body.GetILAsByteArray(); - if (bytes == null) - throw new ArgumentException($"Can not get IL bytes of method {method.FullDescription()}"); - ilBytes = new ByteBuffer(bytes); - ilInstructions = new List((bytes.Length + 1) / 2); + { + ilBytes = new ByteBuffer(new byte[0]); + ilInstructions = new List(); + } + else + { + var bytes = body.GetILAsByteArray(); + if (bytes == null) + throw new ArgumentException("Can not get IL bytes of method " + method.FullDescription()); + ilBytes = new ByteBuffer(bytes); + ilInstructions = new List((bytes.Length + 1) / 2); + } var type = method.DeclaringType; @@ -93,8 +98,8 @@ internal MethodBodyReader(MethodBase method, ILGenerator generator) this_parameter = new ThisParameter(method); parameters = method.GetParameters(); - localVariables = body.LocalVariables?.ToList() ?? new List(); - exceptions = body.ExceptionHandlingClauses; + localVariables = body?.LocalVariables?.ToList() ?? new List(); + exceptions = body?.ExceptionHandlingClauses ?? new List(); } internal void ReadInstructions() diff --git a/Harmony/Internal/MethodPatcher.cs b/Harmony/Internal/MethodPatcher.cs index 94f181e1..50f046b7 100644 --- a/Harmony/Internal/MethodPatcher.cs +++ b/Harmony/Internal/MethodPatcher.cs @@ -480,6 +480,9 @@ static bool AddPrefixes(ILGenerator il, MethodBase original, List pr var canHaveJump = false; prefixes.ForEach(fix => { + if (original.GetMethodBody() == null) + throw new Exception("Methods without body cannot have prefixes. Use a transpiler instead."); + EmitCallParameter(il, original, fix, variables, false); Emitter.Emit(il, OpCodes.Call, fix); @@ -500,6 +503,9 @@ static void AddPostfixes(ILGenerator il, MethodBase original, List p .Where(fix => passthroughPatches == (fix.ReturnType != typeof(void))) .Do(fix => { + if (original.GetMethodBody() == null) + throw new Exception("Methods without body cannot have postfixes. Use a transpiler instead."); + EmitCallParameter(il, original, fix, variables, true); Emitter.Emit(il, OpCodes.Call, fix); @@ -524,6 +530,9 @@ static bool AddFinalizers(ILGenerator il, MethodBase original, List finalizers .Do(fix => { + if (original.GetMethodBody() == null) + throw new Exception("Methods without body cannot have finalizers. Use a transpiler instead."); + if (catchExceptions) Emitter.MarkBlockBefore(il, new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock), out var label);