|
|
|
@ -60,8 +60,7 @@ namespace Avalonia.Utilities |
|
|
|
private static class SubscriptionTypeStorage<TArgs, TSubscriber> |
|
|
|
where TArgs : EventArgs where TSubscriber : class |
|
|
|
{ |
|
|
|
public static readonly ConditionalWeakTable<object, SubscriptionDic<TArgs, TSubscriber>> Subscribers |
|
|
|
= new ConditionalWeakTable<object, SubscriptionDic<TArgs, TSubscriber>>(); |
|
|
|
public static readonly ConditionalWeakTable<object, SubscriptionDic<TArgs, TSubscriber>> Subscribers = new(); |
|
|
|
} |
|
|
|
|
|
|
|
private class SubscriptionDic<T, TSubscriber> : Dictionary<string, Subscription<T, TSubscriber>> |
|
|
|
@ -69,8 +68,7 @@ namespace Avalonia.Utilities |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
private static readonly Dictionary<Type, Dictionary<string, EventInfo>> Accessors |
|
|
|
= new Dictionary<Type, Dictionary<string, EventInfo>>(); |
|
|
|
private static readonly Dictionary<Type, Dictionary<string, EventInfo>> s_accessors = new(); |
|
|
|
|
|
|
|
private class Subscription<T, TSubscriber> where T : EventArgs where TSubscriber : class |
|
|
|
{ |
|
|
|
@ -81,18 +79,17 @@ namespace Avalonia.Utilities |
|
|
|
private readonly Delegate _delegate; |
|
|
|
|
|
|
|
private Descriptor[] _data = new Descriptor[2]; |
|
|
|
private int _count = 0; |
|
|
|
private int _count; |
|
|
|
|
|
|
|
delegate void CallerDelegate(TSubscriber s, object sender, T args); |
|
|
|
|
|
|
|
struct Descriptor |
|
|
|
private delegate void CallerDelegate(TSubscriber s, object? sender, T args); |
|
|
|
|
|
|
|
private struct Descriptor |
|
|
|
{ |
|
|
|
public WeakReference<TSubscriber> Subscriber; |
|
|
|
public CallerDelegate Caller; |
|
|
|
public WeakReference<TSubscriber>? Subscriber; |
|
|
|
public CallerDelegate? Caller; |
|
|
|
} |
|
|
|
|
|
|
|
private static Dictionary<MethodInfo, CallerDelegate> s_Callers = |
|
|
|
new Dictionary<MethodInfo, CallerDelegate>(); |
|
|
|
private static readonly Dictionary<MethodInfo, CallerDelegate> s_callers = new(); |
|
|
|
|
|
|
|
public Subscription(SubscriptionDic<T, TSubscriber> sdic, |
|
|
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type targetType, |
|
|
|
@ -101,8 +98,8 @@ namespace Avalonia.Utilities |
|
|
|
_sdic = sdic; |
|
|
|
_target = target; |
|
|
|
_eventName = eventName; |
|
|
|
if (!Accessors.TryGetValue(targetType, out var evDic)) |
|
|
|
Accessors[targetType] = evDic = new Dictionary<string, EventInfo>(); |
|
|
|
if (!s_accessors.TryGetValue(targetType, out var evDic)) |
|
|
|
s_accessors[targetType] = evDic = new Dictionary<string, EventInfo>(); |
|
|
|
|
|
|
|
if (evDic.TryGetValue(eventName, out var info)) |
|
|
|
{ |
|
|
|
@ -123,12 +120,12 @@ namespace Avalonia.Utilities |
|
|
|
|
|
|
|
var del = new Action<object, T>(OnEvent); |
|
|
|
_delegate = del.GetMethodInfo().CreateDelegate(_info.EventHandlerType!, del.Target); |
|
|
|
_info.AddMethod!.Invoke(target, new[] { _delegate }); |
|
|
|
_info.AddMethod!.Invoke(target, new object?[] { _delegate }); |
|
|
|
} |
|
|
|
|
|
|
|
void Destroy() |
|
|
|
private void Destroy() |
|
|
|
{ |
|
|
|
_info.RemoveMethod!.Invoke(_target, new[] { _delegate }); |
|
|
|
_info.RemoveMethod!.Invoke(_target, new object?[] { _delegate }); |
|
|
|
_sdic.Remove(_eventName); |
|
|
|
} |
|
|
|
|
|
|
|
@ -146,8 +143,8 @@ namespace Avalonia.Utilities |
|
|
|
MethodInfo method = s.Method; |
|
|
|
|
|
|
|
var subscriber = (TSubscriber)s.Target!; |
|
|
|
if (!s_Callers.TryGetValue(method, out var caller)) |
|
|
|
s_Callers[method] = caller = |
|
|
|
if (!s_callers.TryGetValue(method, out var caller)) |
|
|
|
s_callers[method] = caller = |
|
|
|
(CallerDelegate)Delegate.CreateDelegate(typeof(CallerDelegate), null, method); |
|
|
|
_data[_count] = new Descriptor |
|
|
|
{ |
|
|
|
@ -178,7 +175,7 @@ namespace Avalonia.Utilities |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void Compact(bool preventDestroy = false) |
|
|
|
private void Compact(bool preventDestroy = false) |
|
|
|
{ |
|
|
|
int empty = -1; |
|
|
|
for (int c = 0; c < _count; c++) |
|
|
|
@ -206,15 +203,15 @@ namespace Avalonia.Utilities |
|
|
|
Destroy(); |
|
|
|
} |
|
|
|
|
|
|
|
void OnEvent(object sender, T eventArgs) |
|
|
|
private void OnEvent(object? sender, T eventArgs) |
|
|
|
{ |
|
|
|
var needCompact = false; |
|
|
|
for(var c=0; c<_count; c++) |
|
|
|
for (var c = 0; c < _count; c++) |
|
|
|
{ |
|
|
|
var r = _data[c].Subscriber; |
|
|
|
var r = _data[c].Subscriber!; |
|
|
|
if (r.TryGetTarget(out var sub)) |
|
|
|
{ |
|
|
|
_data[c].Caller(sub, sender, eventArgs); |
|
|
|
_data[c].Caller!(sub, sender, eventArgs); |
|
|
|
} |
|
|
|
else |
|
|
|
needCompact = true; |
|
|
|
|