Tagging interface for event handlers
Support events in the TorchAPI Static registry, non-static registration methods. Support unregister by assembly.
This commit is contained in:
@@ -1,10 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Torch.Managers.EventManager
|
namespace Torch.API.Managers.Event
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attribute indicating that a method should be invoked when the event occurs.
|
/// Attribute indicating that a method should be invoked when the event occurs.
|
@@ -1,10 +1,4 @@
|
|||||||
using System;
|
namespace Torch.API.Managers.Event
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Torch.Managers.EventManager
|
|
||||||
{
|
{
|
||||||
public interface IEvent
|
public interface IEvent
|
||||||
{
|
{
|
9
Torch.API/Managers/Event/IEventHandler.cs
Normal file
9
Torch.API/Managers/Event/IEventHandler.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Torch.API.Managers.Event
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface used to tag an event handler. This does <b>not</b> register it with the event manager.
|
||||||
|
/// </summary>
|
||||||
|
public interface IEventHandler
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
27
Torch.API/Managers/Event/IEventManager.cs
Normal file
27
Torch.API/Managers/Event/IEventManager.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Torch.API.Managers.Event
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manager class responsible for registration of event handlers.
|
||||||
|
/// </summary>
|
||||||
|
public interface IEventManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Registers all event handler methods contained in the given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">Instance to register</param>
|
||||||
|
/// <returns><b>true</b> if added, <b>false</b> otherwise</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
bool RegisterHandler(IEventHandler handler);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unregisters all event handler methods contained in the given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">Instance to unregister</param>
|
||||||
|
/// <returns><b>true</b> if removed, <b>false</b> otherwise</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
bool UnregisterHandler(IEventHandler handler);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using Torch.API.Managers.Event;
|
||||||
|
using Torch.Managers.EventManager;
|
||||||
|
|
||||||
namespace Torch.Managers.EventManager
|
namespace Torch.Managers.Event
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an ordered list of callbacks.
|
/// Represents an ordered list of callbacks.
|
||||||
@@ -49,7 +48,7 @@ namespace Torch.Managers.EventManager
|
|||||||
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void AddHandler(MethodInfo method, object instance)
|
public void AddHandler(MethodInfo method, IEventHandler instance)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -64,7 +63,7 @@ namespace Torch.Managers.EventManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public int RemoveHandlers(object instance)
|
public int RemoveHandlers(IEventHandler instance)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
@@ -3,23 +3,21 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using Torch.API;
|
using Torch.API;
|
||||||
using Torch.API.Managers;
|
using Torch.API.Managers.Event;
|
||||||
using VRage.Game.ModAPI;
|
using Torch.Managers.EventManager;
|
||||||
|
|
||||||
namespace Torch.Managers.EventManager
|
namespace Torch.Managers.Event
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Manager class responsible for managing registration and dispatching of events.
|
/// Manager class responsible for managing registration and dispatching of events.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class EventManager : Manager
|
public class EventManager : Manager, IEventManager
|
||||||
{
|
{
|
||||||
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private static Dictionary<Type, IEventList> _eventLists = new Dictionary<Type, IEventList>();
|
private static readonly Dictionary<Type, IEventList> _eventLists = new Dictionary<Type, IEventList>();
|
||||||
|
|
||||||
static EventManager()
|
static EventManager()
|
||||||
{
|
{
|
||||||
@@ -41,11 +39,7 @@ namespace Torch.Managers.EventManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Finds all event handlers in the given type, and its base types
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exploreType">Type to explore</param>
|
|
||||||
/// <returns>All event handlers</returns>
|
|
||||||
private static IEnumerable<MethodInfo> EventHandlers(Type exploreType)
|
private static IEnumerable<MethodInfo> EventHandlers(Type exploreType)
|
||||||
{
|
{
|
||||||
IEnumerable<MethodInfo> enumerable = exploreType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
IEnumerable<MethodInfo> enumerable = exploreType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
|
||||||
@@ -62,11 +56,8 @@ namespace Torch.Managers.EventManager
|
|||||||
return exploreType.BaseType != null ? enumerable.Concat(EventHandlers(exploreType.BaseType)) : enumerable;
|
return exploreType.BaseType != null ? enumerable.Concat(EventHandlers(exploreType.BaseType)) : enumerable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Registers all handlers the given instance owns.
|
private static void RegisterHandlerInternal(IEventHandler instance)
|
||||||
/// </summary>
|
|
||||||
/// <param name="instance">Instance to register handlers from</param>
|
|
||||||
private static void RegisterHandler(object instance)
|
|
||||||
{
|
{
|
||||||
foreach (MethodInfo handler in EventHandlers(instance.GetType()))
|
foreach (MethodInfo handler in EventHandlers(instance.GetType()))
|
||||||
{
|
{
|
||||||
@@ -96,15 +87,86 @@ namespace Torch.Managers.EventManager
|
|||||||
/// Unregisters all handlers owned by the given instance
|
/// Unregisters all handlers owned by the given instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">Instance</param>
|
/// <param name="instance">Instance</param>
|
||||||
private static void UnregisterHandlers(object instance)
|
private static void UnregisterHandlerInternal(IEventHandler instance)
|
||||||
{
|
{
|
||||||
foreach (IEventList list in _eventLists.Values)
|
foreach (IEventList list in _eventLists.Values)
|
||||||
list.RemoveHandlers(instance);
|
list.RemoveHandlers(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Dictionary<Assembly, HashSet<IEventHandler>> _registeredHandlers = new Dictionary<Assembly, HashSet<IEventHandler>>();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public EventManager(ITorchBase torchInstance) : base(torchInstance)
|
public EventManager(ITorchBase torchInstance) : base(torchInstance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers all event handler methods contained in the given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">Instance to register</param>
|
||||||
|
/// <returns><b>true</b> if added, <b>false</b> otherwise</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public bool RegisterHandler(IEventHandler handler)
|
||||||
|
{
|
||||||
|
Assembly caller = Assembly.GetCallingAssembly();
|
||||||
|
lock (_registeredHandlers)
|
||||||
|
{
|
||||||
|
if (!_registeredHandlers.TryGetValue(caller, out HashSet<IEventHandler> handlers))
|
||||||
|
_registeredHandlers.Add(caller, handlers = new HashSet<IEventHandler>());
|
||||||
|
if (handlers.Add(handler))
|
||||||
|
{
|
||||||
|
RegisterHandlerInternal(handler);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unregisters all event handler methods contained in the given instance
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">Instance to unregister</param>
|
||||||
|
/// <returns><b>true</b> if removed, <b>false</b> otherwise</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
public bool UnregisterHandler(IEventHandler handler)
|
||||||
|
{
|
||||||
|
Assembly caller = Assembly.GetCallingAssembly();
|
||||||
|
lock (_registeredHandlers)
|
||||||
|
{
|
||||||
|
if (!_registeredHandlers.TryGetValue(caller, out HashSet<IEventHandler> handlers))
|
||||||
|
return false;
|
||||||
|
if (handlers.Remove(handler))
|
||||||
|
{
|
||||||
|
UnregisterHandlerInternal(handler);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unregisters all handlers owned by the given assembly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asm">Assembly to unregister</param>
|
||||||
|
/// <param name="callback">Optional callback invoked for every registered handler in the assembly. Ignored if null</param>
|
||||||
|
/// <returns>the number of handlers that were unregistered</returns>
|
||||||
|
internal int UnregisterAllHandlers(Assembly asm, Func<IEventHandler> callback = null)
|
||||||
|
{
|
||||||
|
lock (_registeredHandlers)
|
||||||
|
{
|
||||||
|
if (!_registeredHandlers.TryGetValue(asm, out HashSet<IEventHandler> handlers))
|
||||||
|
return 0;
|
||||||
|
foreach (IEventHandler k in handlers)
|
||||||
|
{
|
||||||
|
callback?.Invoke();
|
||||||
|
UnregisterHandlerInternal(k);
|
||||||
|
}
|
||||||
|
int count = handlers.Count;
|
||||||
|
handlers.Clear();
|
||||||
|
_registeredHandlers.Remove(asm);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -6,6 +6,8 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Sandbox.Game.Entities;
|
using Sandbox.Game.Entities;
|
||||||
using Sandbox.Game.Entities.Blocks;
|
using Sandbox.Game.Entities.Blocks;
|
||||||
|
using Torch.API.Managers.Event;
|
||||||
|
using Torch.Managers.Event;
|
||||||
using Torch.Managers.PatchManager;
|
using Torch.Managers.PatchManager;
|
||||||
using Torch.Utils;
|
using Torch.Utils;
|
||||||
|
|
@@ -1,11 +1,7 @@
|
|||||||
using System;
|
using System.Reflection;
|
||||||
using System.Collections.Generic;
|
using Torch.API.Managers.Event;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Torch.Managers.EventManager
|
namespace Torch.Managers.Event
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the interface for adding and removing from an ordered list of callbacks.
|
/// Represents the interface for adding and removing from an ordered list of callbacks.
|
||||||
@@ -17,13 +13,13 @@ namespace Torch.Managers.EventManager
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="method">Handler method</param>
|
/// <param name="method">Handler method</param>
|
||||||
/// <param name="instance">Instance to invoke the handler on</param>
|
/// <param name="instance">Instance to invoke the handler on</param>
|
||||||
void AddHandler(MethodInfo method, object instance);
|
void AddHandler(MethodInfo method, IEventHandler instance);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes all event handlers invoked on the given instance.
|
/// Removes all event handlers invoked on the given instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="instance">Instance to remove event handlers for</param>
|
/// <param name="instance">Instance to remove event handlers for</param>
|
||||||
/// <returns>The number of event handlers removed</returns>
|
/// <returns>The number of event handlers removed</returns>
|
||||||
int RemoveHandlers(object instance);
|
int RemoveHandlers(IEventHandler instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user