A stable modding interface between Techblox and mods https://mod.exmods.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
1.9KB

  1. using System;
  2. using System.Collections.Generic;
  3. using TechbloxModdingAPI.Events;
  4. namespace TechbloxModdingAPI.Utility
  5. {
  6. /// <summary>
  7. /// Wraps the event handler in a try-catch block to avoid propagating exceptions.
  8. /// </summary>
  9. /// <typeparam name="T">The event arguments type</typeparam>
  10. public struct WrappedHandler<T>
  11. {
  12. private EventHandler<T> eventHandler;
  13. /// <summary>
  14. /// Store wrappers so we can unregister them properly
  15. /// </summary>
  16. private static Dictionary<EventHandler<T>, EventHandler<T>> wrappers =
  17. new Dictionary<EventHandler<T>, EventHandler<T>>();
  18. public static WrappedHandler<T> operator +(WrappedHandler<T> original, EventHandler<T> added)
  19. {
  20. EventHandler<T> wrapped = (sender, e) =>
  21. {
  22. try
  23. {
  24. added(sender, e);
  25. }
  26. catch (Exception e1)
  27. {
  28. EventRuntimeException wrappedException =
  29. new EventRuntimeException($"EventHandler with arg type {typeof(T).Name} threw an exception",
  30. e1);
  31. Logging.LogWarning(wrappedException.ToString());
  32. }
  33. };
  34. wrappers.Add(added, wrapped);
  35. return new WrappedHandler<T> { eventHandler = original.eventHandler + wrapped };
  36. }
  37. public static WrappedHandler<T> operator -(WrappedHandler<T> original, EventHandler<T> removed)
  38. {
  39. if (!wrappers.TryGetValue(removed, out var wrapped)) return original;
  40. wrappers.Remove(removed);
  41. return new WrappedHandler<T> { eventHandler = original.eventHandler - wrapped };
  42. }
  43. public void Invoke(object sender, T args)
  44. {
  45. eventHandler?.Invoke(sender, args);
  46. }
  47. }
  48. }