Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Harmony/Internal/PatchTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,16 @@ internal static MethodBase GetOriginalMethod(this HarmonyMethod attr)
case MethodType.Enumerator:
if (attr.methodName is null)
return null;
var method = AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes);
return AccessTools.EnumeratorMoveNext(method);
var enumMethod = AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes);
return AccessTools.EnumeratorMoveNext(enumMethod);

#if NET45_OR_GREATER
case MethodType.Async:
if (attr.methodName is null)
return null;
var asyncMethod = AccessTools.DeclaredMethod(attr.declaringType, attr.methodName, attr.argumentTypes);
return AccessTools.AsyncMoveNext(asyncMethod);
#endif
}
}
catch (AmbiguousMatchException ex)
Expand Down
8 changes: 6 additions & 2 deletions Harmony/Public/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ public enum MethodType
Constructor,
/// <summary>This is a static constructor</summary>
StaticConstructor,
/// <summary>This targets the MoveNext method of the enumerator result</summary>
Enumerator
/// <summary>This targets the MoveNext method of the enumerator result, that actually contains the method's implementation</summary>
Enumerator,
#if NET45_OR_GREATER
/// <summary>This targets the MoveNext method of the async state machine, that actually contains the method's implementation</summary>
Async
#endif
}

/// <summary>Specifies the type of argument</summary>
Expand Down
36 changes: 34 additions & 2 deletions Harmony/Tools/AccessTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.Threading;

namespace HarmonyLib
Expand Down Expand Up @@ -466,9 +467,9 @@ public static MethodInfo Method(string typeColonName, Type[] parameters = null,
return Method(info.type, info.name, parameters, generics);
}

/// <summary>Gets the <see cref="IEnumerator.MoveNext" /> method of an enumerator method</summary>
/// <summary>Gets the <see cref="IEnumerator.MoveNext"/> method of an enumerator method</summary>
/// <param name="method">Enumerator method that creates the enumerator <see cref="IEnumerator" /></param>
/// <returns>The internal <see cref="IEnumerator.MoveNext" /> method of the enumerator or <b>null</b> if no valid enumerator is detected</returns>
/// <returns>The internal <see cref="IEnumerator.MoveNext"/> method of the enumerator or <b>null</b> if no valid enumerator is detected</returns>
public static MethodInfo EnumeratorMoveNext(MethodBase method)
{
if (method is null)
Expand Down Expand Up @@ -498,6 +499,37 @@ public static MethodInfo EnumeratorMoveNext(MethodBase method)
return Method(type, nameof(IEnumerator.MoveNext));
}

#if NET45_OR_GREATER
/// <summary>Gets the <see cref="IAsyncStateMachine.MoveNext"/> method of an async method's state machine</summary>
/// <param name="method">Async method that creates the state machine internally</param>
/// <returns>The internal <see cref="IAsyncStateMachine.MoveNext"/> method of the async state machine or <b>null</b> if no valid async method is detected</returns>
public static MethodInfo AsyncMoveNext(MethodBase method)
{
if (method is null)
{
FileLog.Debug("AccessTools.AsyncMoveNext: method is null");
return null;
}

var asyncAttribute = method.GetCustomAttribute<AsyncStateMachineAttribute>();
if (asyncAttribute is null)
{
FileLog.Debug($"AccessTools.AsyncMoveNext: Could not find AsyncStateMachine for {method.FullDescription()}");
return null;
}

var asyncStateMachineType = asyncAttribute.StateMachineType;
var asyncMethodBody = DeclaredMethod(asyncStateMachineType, nameof(IAsyncStateMachine.MoveNext));
if (asyncMethodBody is null)
{
FileLog.Debug($"AccessTools.AsyncMoveNext: Could not find async method body for {method.FullDescription()}");
return null;
}

return asyncMethodBody;
}
#endif

/// <summary>Gets the names of all method that are declared in a type</summary>
/// <param name="type">The declaring class/type</param>
/// <returns>A list of method names</returns>
Expand Down