|
- using System;
- using System.Collections.Generic;
- using TechbloxModdingAPI.Events;
-
- namespace TechbloxModdingAPI.Utility
- {
- /// <summary>
- /// Wraps the event handler in a try-catch block to avoid propagating exceptions.
- /// </summary>
- /// <typeparam name="T">The event arguments type</typeparam>
- public struct WrappedHandler<T>
- {
- private EventHandler<T> eventHandler;
-
- /// <summary>
- /// Store wrappers so we can unregister them properly
- /// </summary>
- private static Dictionary<EventHandler<T>, EventHandler<T>> wrappers =
- new Dictionary<EventHandler<T>, EventHandler<T>>();
-
- public static WrappedHandler<T> operator +(WrappedHandler<T> original, EventHandler<T> added)
- {
- EventHandler<T> 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());
- }
- };
- if (wrappers.ContainsKey(added))
- {
- original.eventHandler -= wrapped;
- wrappers.Remove(added);
- }
-
- wrappers.Add(added, wrapped);
- return new WrappedHandler<T> { eventHandler = original.eventHandler + wrapped };
- }
-
- public static WrappedHandler<T> operator -(WrappedHandler<T> original, EventHandler<T> removed)
- {
- if (!wrappers.TryGetValue(removed, out var wrapped)) return original;
- wrappers.Remove(removed);
- return new WrappedHandler<T> { eventHandler = original.eventHandler - wrapped };
- }
-
- public void Invoke(object sender, T args)
- {
- eventHandler?.Invoke(sender, args);
- }
- }
- }
|