mirror of
https://github.com/pardeike/Harmony
synced 2026-06-08 16:40:38 +00:00
84 lines
2.1 KiB
C#
84 lines
2.1 KiB
C#
namespace Execution_With
|
|
{
|
|
using System;
|
|
|
|
#pragma warning disable CS9113
|
|
public class Code
|
|
{
|
|
// <example>
|
|
static R ReplacementMethod(T optionalThisArgument /*, ... arguments ... */ )
|
|
{
|
|
R result = default;
|
|
var finalized = false;
|
|
Exception ex = null;
|
|
|
|
// All this code is generated dynamically, which means that
|
|
// Harmony can build it depending on
|
|
//
|
|
// - if there are any finalizers (otherwise, skip try-catch)
|
|
//
|
|
// - re-throwing can be dynamic too depending on if at least
|
|
// one finalizer returns a non-void result
|
|
|
|
try
|
|
{
|
|
result = Original(/* ... arguments ... */);
|
|
|
|
// finalizers get all the arguments a prefix could get too
|
|
// plus one new one: "Exception __exception"
|
|
// they SHOULD NOT edit the passed exception but instead
|
|
// signal to Harmony that they change it by returning it
|
|
|
|
// here finalizers are called without try-catch so they are
|
|
// allowed to throw exceptions. note, that it is perfectly
|
|
// fine to get null passed into the exception argument
|
|
|
|
SimpleFinalizer(ref result);
|
|
ex = EditFinalizer(ex, ref result);
|
|
finalized = true;
|
|
|
|
if (ex is not null) throw ex;
|
|
return result;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
ex = e;
|
|
|
|
// finalizers will get another chance here, so they are
|
|
// guaranteed to run even if their first invocation threw
|
|
// an exception
|
|
|
|
if (!finalized)
|
|
{
|
|
try { SimpleFinalizer(ref result); } catch { }
|
|
try { ex = EditFinalizer(ex, ref result); } catch { }
|
|
}
|
|
|
|
if (allVoid)
|
|
{
|
|
// alternative 1: all finalizers are returning void
|
|
throw;
|
|
}
|
|
else
|
|
{
|
|
// alternative 2: at least one non-void finalizer
|
|
if (ex is not null) throw ex;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// given the following signatures:
|
|
public static R Original() => new("original");
|
|
public static void SimpleFinalizer(ref R result) { }
|
|
public static Exception EditFinalizer(Exception ex, ref R result) => ex;
|
|
// </example>
|
|
|
|
public class R(string s) { }
|
|
public class T { }
|
|
public static bool allVoid;
|
|
}
|
|
#pragma warning restore CS9113
|
|
}
|