using System; using System.Collections.Generic; using TechbloxModdingAPI.Events; namespace TechbloxModdingAPI.Utility { /// /// Wraps the event handler in a try-catch block to avoid propagating exceptions. /// /// The event arguments type public struct WrappedHandler { private EventHandler eventHandler; /// /// Store wrappers so we can unregister them properly /// private static Dictionary, EventHandler> wrappers = new Dictionary, EventHandler>(); public static WrappedHandler operator +(WrappedHandler original, EventHandler added) { EventHandler wrapped = (sender, e) => { try { added(sender, e); } catch (Exception e1) { EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler with arg type {typeof(T).Name} threw an exception", e1); Logging.LogWarning(wrappedException.ToString()); } }; wrappers.Add(added, wrapped); return new WrappedHandler { eventHandler = original.eventHandler + wrapped }; } public static WrappedHandler operator -(WrappedHandler original, EventHandler removed) { if (!wrappers.TryGetValue(removed, out var wrapped)) return original; wrappers.Remove(removed); return new WrappedHandler { eventHandler = original.eventHandler - wrapped }; } public void Invoke(object sender, T args) { eventHandler?.Invoke(sender, args); } } }