Last active
March 19, 2021 09:00
-
-
Save pardeike/d75d609b842d793b0e4e938d86ed8e27 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
public static class Program { | |
public static void Main() { | |
Console.WriteLine(DynamicHarmonyWrapper()); | |
} | |
public static string DynamicHarmonyWrapper() { | |
string result = default; | |
bool finalized = false; | |
Exception ex = null; | |
try { | |
result = Original(); | |
// 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 != 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 { } | |
} | |
// All this code is generated dynamically, which means that Harmony | |
// can build it depending on | |
// - if there are any finalizers (if not, skip overall try-catch logic) | |
// - re-throwing can be dynamic too: | |
// | |
// alternative 1: for when all finalizers are returning void: | |
throw; | |
// alternative 2: for when at least one finalizer has a non-void return | |
if (ex != null) throw ex; | |
// make compiler happy (can probably be skipped in IL) | |
return result; | |
} | |
} | |
public static String Original() { return "original"; } | |
public static void SimpleFinalizer(ref string result) { } | |
public static Exception EditFinalizer(Exception ex, ref string result) { return ex; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment