perf: no wrapper
This commit is contained in:
4 files changed
+33
-113
No files matched your search
+18
-36
@@ -26,16 +26,6 @@ namespace ShrinkEventBus
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void EnsureAutoManagerInitialized() => EventAutoRegHelper.EnsureInitialized();
|
private static void EnsureAutoManagerInitialized() => EventAutoRegHelper.EnsureInitialized();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static void RegisterEvent<TEvent>(Action<TEvent> handler, string methodName, Type declaringType,
|
|
||||||
EventPriority priority = EventPriority.NORMAL, bool receiveCanceled = false) where TEvent : EventBase
|
|
||||||
{
|
|
||||||
var methodInfo = declaringType.GetMethod(methodName,
|
|
||||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
|
||||||
RegisterEventInternal(typeof(TEvent), handler, priority, 0, receiveCanceled,
|
|
||||||
$"Manual Sync Handler (Priority: {priority})", methodInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void RegisterEvent<TEvent>(Func<TEvent, UniTask> handler, int priority = 0)
|
public static void RegisterEvent<TEvent>(Func<TEvent, UniTask> handler, int priority = 0)
|
||||||
where TEvent : EventBase
|
where TEvent : EventBase
|
||||||
@@ -184,11 +174,21 @@ namespace ShrinkEventBus
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool TryPrepareHandler<TEvent>(TEvent eventArgs, EventHandlerInfo handlerInfo)
|
||||||
|
where TEvent : EventBase
|
||||||
|
{
|
||||||
|
eventArgs.CurrentHandler = handlerInfo;
|
||||||
|
eventArgs.SetPhase(handlerInfo.Priority);
|
||||||
|
if (eventArgs.IsCancelable && eventArgs.IsCanceled && !handlerInfo.ReceiveCanceled)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static async UniTask<bool> TriggerEventAsync<TEvent>(TEvent eventArgs) where TEvent : EventBase
|
public static async UniTask<bool> TriggerEventAsync<TEvent>(TEvent eventArgs) where TEvent : EventBase
|
||||||
{
|
{
|
||||||
EnsureAutoManagerInitialized();
|
EnsureAutoManagerInitialized();
|
||||||
|
|
||||||
var collection = EventCache<TEvent>.List;
|
var collection = EventCache<TEvent>.List;
|
||||||
if (collection == null) return false;
|
if (collection == null) return false;
|
||||||
|
|
||||||
@@ -202,10 +202,7 @@ namespace ShrinkEventBus
|
|||||||
for (var i = 0; i < handlers.Length; i++)
|
for (var i = 0; i < handlers.Length; i++)
|
||||||
{
|
{
|
||||||
var handlerInfo = handlers[i];
|
var handlerInfo = handlers[i];
|
||||||
eventArgs.CurrentHandler = handlerInfo;
|
if (!TryPrepareHandler(eventArgs, handlerInfo)) continue;
|
||||||
eventArgs.SetPhase(handlerInfo.Priority);
|
|
||||||
|
|
||||||
if (eventArgs is { IsCancelable: true, IsCanceled: true } && !handlerInfo.ReceiveCanceled) continue;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -223,8 +220,7 @@ namespace ShrinkEventBus
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogException(ex);
|
Debug.LogException(ex);
|
||||||
Debug.LogError(
|
Debug.LogError($"[EventBus] Async Handler Exception: {ex.Message}");
|
||||||
$"[EventBus] {typeof(TEvent).Name} Async Handler {handlerInfo.DisplayDeclaringType.Name}.{handlerInfo.DisplayMethodName} Exception: {ex.Message}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +232,6 @@ namespace ShrinkEventBus
|
|||||||
public static bool TriggerEvent<TEvent>(TEvent eventArgs) where TEvent : EventBase
|
public static bool TriggerEvent<TEvent>(TEvent eventArgs) where TEvent : EventBase
|
||||||
{
|
{
|
||||||
EnsureAutoManagerInitialized();
|
EnsureAutoManagerInitialized();
|
||||||
|
|
||||||
var collection = EventCache<TEvent>.List;
|
var collection = EventCache<TEvent>.List;
|
||||||
if (collection == null) return false;
|
if (collection == null) return false;
|
||||||
|
|
||||||
@@ -250,10 +245,7 @@ namespace ShrinkEventBus
|
|||||||
for (var i = 0; i < handlers.Length; i++)
|
for (var i = 0; i < handlers.Length; i++)
|
||||||
{
|
{
|
||||||
var handlerInfo = handlers[i];
|
var handlerInfo = handlers[i];
|
||||||
eventArgs.CurrentHandler = handlerInfo;
|
if (!TryPrepareHandler(eventArgs, handlerInfo)) continue;
|
||||||
eventArgs.SetPhase(handlerInfo.Priority);
|
|
||||||
|
|
||||||
if (eventArgs is { IsCancelable: true, IsCanceled: true } && !handlerInfo.ReceiveCanceled) continue;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -272,8 +264,7 @@ namespace ShrinkEventBus
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogException(ex);
|
Debug.LogException(ex);
|
||||||
Debug.LogError(
|
Debug.LogError($"[EventBus] Sync Handler Exception: {ex.Message}");
|
||||||
$"[EventBus] {typeof(TEvent).Name} Sync Handler {handlerInfo.DisplayDeclaringType.Name}.{handlerInfo.DisplayMethodName} Exception: {ex.Message}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,19 +302,13 @@ namespace ShrinkEventBus
|
|||||||
{
|
{
|
||||||
var method = trace.GetFrame(i)?.GetMethod();
|
var method = trace.GetFrame(i)?.GetMethod();
|
||||||
var declaringType = method?.DeclaringType;
|
var declaringType = method?.DeclaringType;
|
||||||
|
|
||||||
if (declaringType == null) continue;
|
if (declaringType == null) continue;
|
||||||
if (declaringType == typeof(EventBus) ||
|
if (declaringType == typeof(EventBus) || declaringType.DeclaringType == typeof(EventBus)) continue;
|
||||||
declaringType.DeclaringType == typeof(EventBus)) continue;
|
|
||||||
var ns = declaringType.Namespace ?? "";
|
var ns = declaringType.Namespace ?? "";
|
||||||
if (ns.StartsWith("System") || ns.StartsWith("Cysharp") || ns.StartsWith("UnityEngine"))
|
if (ns.StartsWith("System") || ns.StartsWith("Cysharp") || ns.StartsWith("UnityEngine")) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
var className = declaringType.Name;
|
var className = declaringType.Name;
|
||||||
var methodName = method.Name;
|
var methodName = method.Name;
|
||||||
|
if (declaringType.DeclaringType != null && className.StartsWith("<") && className.Contains(">"))
|
||||||
if (declaringType.DeclaringType != null && className.StartsWith("<") &&
|
|
||||||
className.Contains(">"))
|
|
||||||
{
|
{
|
||||||
className = declaringType.DeclaringType.Name;
|
className = declaringType.DeclaringType.Name;
|
||||||
var startIndex = declaringType.Name.IndexOf('<') + 1;
|
var startIndex = declaringType.Name.IndexOf('<') + 1;
|
||||||
@@ -337,7 +322,6 @@ namespace ShrinkEventBus
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// ignored
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return senderInfo;
|
return senderInfo;
|
||||||
@@ -370,9 +354,7 @@ namespace ShrinkEventBus
|
|||||||
{
|
{
|
||||||
if (target == null) return;
|
if (target == null) return;
|
||||||
if (IsInstanceRegistered(target)) return;
|
if (IsInstanceRegistered(target)) return;
|
||||||
|
|
||||||
EventBusRegHelper.RegisterEventHandlers(target);
|
EventBusRegHelper.RegisterEventHandlers(target);
|
||||||
|
|
||||||
lock (InstanceLock)
|
lock (InstanceLock)
|
||||||
{
|
{
|
||||||
if (!RegisteredInstances.Add(target)) return;
|
if (!RegisteredInstances.Add(target)) return;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -54,17 +53,13 @@ namespace ShrinkEventBus
|
|||||||
foreach (var method in methods)
|
foreach (var method in methods)
|
||||||
{
|
{
|
||||||
if (target != null && method.IsStatic) continue;
|
if (target != null && method.IsStatic) continue;
|
||||||
|
|
||||||
var attributes = method.GetCustomAttributes(typeof(EventSubscribeAttribute), false);
|
var attributes = method.GetCustomAttributes(typeof(EventSubscribeAttribute), false);
|
||||||
if (attributes.Length == 0) continue;
|
if (attributes.Length == 0) continue;
|
||||||
|
|
||||||
var subscribeAttr = (EventSubscribeAttribute)attributes[0];
|
var subscribeAttr = (EventSubscribeAttribute)attributes[0];
|
||||||
var parameters = method.GetParameters();
|
var parameters = method.GetParameters();
|
||||||
|
|
||||||
if (parameters.Length != 1) continue;
|
if (parameters.Length != 1) continue;
|
||||||
var parameterType = parameters[0].ParameterType;
|
var parameterType = parameters[0].ParameterType;
|
||||||
if (!typeof(EventBase).IsAssignableFrom(parameterType)) continue;
|
if (!typeof(EventBase).IsAssignableFrom(parameterType)) continue;
|
||||||
|
|
||||||
ProcessMethodRegistration(target, method, subscribeAttr, parameterType);
|
ProcessMethodRegistration(target, method, subscribeAttr, parameterType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,17 +82,6 @@ namespace ShrinkEventBus
|
|||||||
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
|
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
|
||||||
$"{scope} {typeName}.{method.Name} (UniTask)", method);
|
$"{scope} {typeName}.{method.Name} (UniTask)", method);
|
||||||
}
|
}
|
||||||
else if (method.ReturnType == typeof(Task))
|
|
||||||
{
|
|
||||||
var funcType = typeof(Func<,>).MakeGenericType(parameterType, typeof(Task));
|
|
||||||
var handlerDelegate = target == null
|
|
||||||
? Delegate.CreateDelegate(funcType, method)
|
|
||||||
: Delegate.CreateDelegate(funcType, target, method);
|
|
||||||
var wrappedHandler = WrapTaskHandlerWithMethodInfo(parameterType, handlerDelegate, method);
|
|
||||||
EventBus.RegisterEventInternal(parameterType, wrappedHandler, subscribeAttr.Priority,
|
|
||||||
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
|
|
||||||
$"{scope} {typeName}.{method.Name} (Task->UniTask)", method);
|
|
||||||
}
|
|
||||||
else if (method.ReturnType == typeof(void))
|
else if (method.ReturnType == typeof(void))
|
||||||
{
|
{
|
||||||
var actionType = typeof(Action<>).MakeGenericType(parameterType);
|
var actionType = typeof(Action<>).MakeGenericType(parameterType);
|
||||||
@@ -108,6 +92,11 @@ namespace ShrinkEventBus
|
|||||||
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
|
subscribeAttr.NumericPriority, subscribeAttr.ReceiveCanceled,
|
||||||
$"{scope} {typeName}.{method.Name} (Sync)", method);
|
$"{scope} {typeName}.{method.Name} (Sync)", method);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning(
|
||||||
|
$"[EventBus] Registration failed: {typeName}.{method.Name} return type must be void or UniTask.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -116,47 +105,5 @@ namespace ShrinkEventBus
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Delegate WrapTaskHandlerWithMethodInfo(Type eventType, Delegate taskHandler,
|
|
||||||
MethodInfo originalMethod)
|
|
||||||
{
|
|
||||||
var method = typeof(EventBusRegHelper)
|
|
||||||
.GetMethod(nameof(WrapTaskActionWithMethodInfo), BindingFlags.NonPublic | BindingFlags.Static)
|
|
||||||
?.MakeGenericMethod(eventType);
|
|
||||||
return (Delegate)method.Invoke(null, new object[] { taskHandler, originalMethod })!;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Func<T, UniTask> WrapTaskActionWithMethodInfo<T>(Delegate actionDelegate,
|
|
||||||
MethodInfo originalMethod)
|
|
||||||
{
|
|
||||||
var typedAction = (Func<T, Task>)actionDelegate;
|
|
||||||
var wrapper = new MethodInfoPreservingTaskWrapper<T>(typedAction, originalMethod);
|
|
||||||
return wrapper.ExecuteAsync;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MethodInfoPreservingTaskWrapper<T>
|
|
||||||
{
|
|
||||||
private readonly Func<T, Task> _originalAction;
|
|
||||||
public readonly MethodInfo OriginalMethod;
|
|
||||||
|
|
||||||
public MethodInfoPreservingTaskWrapper(Func<T, Task> originalAction, MethodInfo originalMethod)
|
|
||||||
{
|
|
||||||
_originalAction = originalAction;
|
|
||||||
OriginalMethod = originalMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask ExecuteAsync(T arg)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _originalAction(arg);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.LogException(ex);
|
|
||||||
Debug.LogError($"[EventBus] Task {OriginalMethod.Name}: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
|
#pragma warning disable CS8632 // 只能在 "#nullable" 注释上下文内的代码中使用可为 null 的引用类型的注释。
|
||||||
|
|
||||||
|
|
||||||
namespace ShrinkEventBus
|
namespace ShrinkEventBus
|
||||||
{
|
{
|
||||||
|
public interface IMethodWrapper
|
||||||
|
{
|
||||||
|
MethodInfo OriginalMethod { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public class EventHandlerInfo
|
public class EventHandlerInfo
|
||||||
{
|
{
|
||||||
public Delegate Handler { get; }
|
public Delegate Handler { get; }
|
||||||
@@ -49,24 +54,9 @@ namespace ShrinkEventBus
|
|||||||
|
|
||||||
private static MethodInfo? ExtractOriginalMethodFromWrapper(Delegate handler)
|
private static MethodInfo? ExtractOriginalMethodFromWrapper(Delegate handler)
|
||||||
{
|
{
|
||||||
if (handler.Target == null) return null;
|
if (handler.Target is IMethodWrapper wrapper)
|
||||||
|
|
||||||
var targetType = handler.Target.GetType();
|
|
||||||
if (!targetType.Name.Contains("MethodInfoPreserving")) return null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var field = targetType.GetField("OriginalMethod",
|
return wrapper.OriginalMethod;
|
||||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
if (field != null) return field.GetValue(handler.Target) as MethodInfo;
|
|
||||||
|
|
||||||
var prop = targetType.GetProperty("OriginalMethod",
|
|
||||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
if (prop != null) return prop.GetValue(handler.Target) as MethodInfo;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace ShrinkEventBus
|
|||||||
{
|
{
|
||||||
private static readonly Stack<T> Pool = new(32);
|
private static readonly Stack<T> Pool = new(32);
|
||||||
private static readonly object Lock = new();
|
private static readonly object Lock = new();
|
||||||
|
private static readonly Action<EventBase> CachedReleaseAction = e => Release((T)e);
|
||||||
|
|
||||||
public static T Get()
|
public static T Get()
|
||||||
{
|
{
|
||||||
@@ -21,7 +22,7 @@ namespace ShrinkEventBus
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newEvt = new T();
|
var newEvt = new T();
|
||||||
newEvt.ReleaseAction = e => Release((T)e);
|
newEvt.ReleaseAction = CachedReleaseAction;
|
||||||
return newEvt;
|
return newEvt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user