using System; using System.Linq; using Dalamud.Game; using Dalamud.Plugin.Services; using Serilog; using static Dalamud.Game.Framework; namespace Dalamud.Utility; /// /// Extensions for Events. /// internal static class EventHandlerExtensions { /// /// Replacement for Invoke() on EventHandlers to catch exceptions that stop event propagation in case /// of a thrown Exception inside of an invocation. /// /// The EventHandler in question. /// Default sender for Invoke equivalent. /// Default EventArgs for Invoke equivalent. public static void InvokeSafely(this EventHandler eh, object sender, EventArgs e) { if (eh == null) return; foreach (var handler in eh.GetInvocationList().Cast()) { HandleInvoke(() => handler(sender, e)); } } /// /// Replacement for Invoke() on generic EventHandlers to catch exceptions that stop event propagation in case /// of a thrown Exception inside of an invocation. /// /// The EventHandler in question. /// Default sender for Invoke equivalent. /// Default EventArgs for Invoke equivalent. /// Type of EventArgs. public static void InvokeSafely(this EventHandler eh, object sender, T e) { if (eh == null) return; foreach (var handler in eh.GetInvocationList().Cast>()) { HandleInvoke(() => handler(sender, e)); } } /// /// Replacement for Invoke() on event Actions to catch exceptions that stop event propagation in case /// of a thrown Exception inside of an invocation. /// /// The Action in question. public static void InvokeSafely(this Action act) { if (act == null) return; foreach (var action in act.GetInvocationList().Cast()) { HandleInvoke(action); } } /// /// Replacement for Invoke() on OnUpdateDelegate to catch exceptions that stop event propagation in case /// of a thrown Exception inside of an invocation. /// /// The OnUpdateDelegate in question. /// Framework to be passed on to OnUpdateDelegate. public static void InvokeSafely(this IFramework.OnUpdateDelegate updateDelegate, Framework framework) { if (updateDelegate == null) return; foreach (var action in updateDelegate.GetInvocationList().Cast()) { HandleInvoke(() => action(framework)); } } private static void HandleInvoke(Action act) { try { act(); } catch (Exception ex) { Log.Error(ex, "Exception during raise of {handler}", act.Method); } } }