rewrite HarmonyMethod to allow null (#711)

This commit is contained in:
Jesse Plamondon-Willard 2020-05-21 23:29:23 -04:00
parent f52370f6fa
commit db0a46cb68
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
3 changed files with 58 additions and 2 deletions

View File

@ -137,7 +137,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework
/// <summary>Get whether a method definition matches the signature expected by a method reference.</summary>
/// <param name="definition">The method definition.</param>
/// <param name="reference">The method reference.</param>
public static bool HasMatchingSignature(MethodInfo definition, MethodReference reference)
public static bool HasMatchingSignature(MethodBase definition, MethodReference reference)
{
//
// duplicated by HasMatchingSignature(MethodDefinition, MethodReference) below
@ -166,7 +166,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework
public static bool HasMatchingSignature(MethodDefinition definition, MethodReference reference)
{
//
// duplicated by HasMatchingSignature(MethodInfo, MethodReference) above
// duplicated by HasMatchingSignature(MethodBase, MethodReference) above
//
// same name
@ -191,6 +191,13 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework
/// <param name="reference">The method reference.</param>
public static bool HasMatchingSignature(Type type, MethodReference reference)
{
if (reference.Name == ".ctor")
{
return type
.GetConstructors(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Any(method => RewriteHelper.HasMatchingSignature(method, reference));
}
return type
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Any(method => RewriteHelper.HasMatchingSignature(method, reference));

View File

@ -0,0 +1,45 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using HarmonyLib;
namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
{
/// <summary>Maps Harmony 1.x <see cref="HarmonyMethod"/> methods to Harmony 2.x to avoid breaking older mods.</summary>
/// <remarks>This is public to support SMAPI rewriting and should not be referenced directly by mods.</remarks>
[SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Used via assembly rewriting")]
[SuppressMessage("ReSharper", "CS1591", Justification = "Documentation not needed for facade classes.")]
public class HarmonyMethodFacade : HarmonyMethod
{
/*********
** Public methods
*********/
public HarmonyMethodFacade(MethodInfo method)
{
this.ImportMethodImpl(method);
}
public HarmonyMethodFacade(Type type, string name, Type[] parameters = null)
{
this.ImportMethodImpl(AccessTools.Method(type, name, parameters));
}
/*********
** Private methods
*********/
/// <summary>Import a method directly using the internal HarmonyMethod code.</summary>
/// <param name="methodInfo">The method to import.</param>
private void ImportMethodImpl(MethodInfo methodInfo)
{
// A null method is no longer allowed in the constructor with Harmony 2.0, but the
// internal code still handles null fine. For backwards compatibility, this bypasses
// the new restriction when the mod hasn't been updated for Harmony 2.0 yet.
MethodInfo importMethod = typeof(HarmonyMethod).GetMethod("ImportMethod", BindingFlags.Instance | BindingFlags.NonPublic);
if (importMethod == null)
throw new InvalidOperationException("Can't find 'HarmonyMethod.ImportMethod' method");
importMethod.Invoke(this, new object[] { methodInfo });
}
}
}

View File

@ -92,6 +92,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
toType = typeof(AccessToolsFacade);
break;
case "HarmonyLib.HarmonyMethod":
toType = typeof(HarmonyMethodFacade);
break;
default:
return false;
}