ant-design-blazor/components/core/JsInterop/DomEventService.cs

115 lines
3.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Concurrent;
2019-12-16 18:48:03 +08:00
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
2019-12-16 18:48:03 +08:00
using Microsoft.JSInterop;
namespace AntDesign.JsInterop
2019-12-16 18:48:03 +08:00
{
public class DomEventService
{
private ConcurrentDictionary<string, List<DomEventSubscription>> _domEventListeners = new ConcurrentDictionary<string, List<DomEventSubscription>>();
2019-12-16 18:48:03 +08:00
private readonly IJSRuntime _jsRuntime;
public DomEventService(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
private void AddEventListenerToFirstChildInternal<T>(object dom, string eventName, Action<T> callback)
{
if (!_domEventListeners.ContainsKey(FormatKey(dom, eventName)))
{
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListenerToFirstChild, dom, eventName, DotNetObjectReference.Create(new Invoker<T>((p) =>
{
callback?.Invoke(p);
})));
}
}
public void AddEventListener(object dom, string eventName, Action<JsonElement> callback, bool exclusive = true)
{
AddEventListener<JsonElement>(dom, eventName, callback, exclusive);
}
public void AddEventListener<T>(object dom, string eventName, Action<T> callback, bool exclusive = true)
{
if (exclusive)
{
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListener, dom, eventName, DotNetObjectReference.Create(new Invoker<T>((p) =>
{
callback(p);
})));
}
else
{
string key = FormatKey(dom, eventName);
if (!_domEventListeners.ContainsKey(key))
{
_domEventListeners[key] = new List<DomEventSubscription>();
_jsRuntime.InvokeAsync<string>(JSInteropConstants.AddDomEventListener, dom, eventName, DotNetObjectReference.Create(new Invoker<T>((p) =>
{
foreach (var subscription in _domEventListeners[key])
{
subscription.Delegate.DynamicInvoke(p);
}
})));
}
_domEventListeners[key].Add(new DomEventSubscription(callback));
}
}
public void AddEventListenerToFirstChild(object dom, string eventName, Action<JsonElement> callback)
{
AddEventListenerToFirstChildInternal<string>(dom, eventName, (e) =>
{
JsonElement jsonElement = JsonDocument.Parse(e).RootElement;
callback(jsonElement);
});
}
public void AddEventListenerToFirstChild<T>(object dom, string eventName, Action<T> callback)
{
AddEventListenerToFirstChildInternal<string>(dom, eventName, (e) =>
{
T obj = JsonSerializer.Deserialize<T>(e);
callback(obj);
});
}
private static string FormatKey(object dom, string eventName) => $"{dom}-{eventName}";
public void RemoveEventListerner<T>(object dom, string eventName, Action<T> callback)
{
string key = FormatKey(dom, eventName);
if (_domEventListeners.ContainsKey(key))
{
var subscription = _domEventListeners[key].SingleOrDefault(s => s.Delegate == (Delegate)callback);
if (subscription != null)
{
_domEventListeners[key].Remove(subscription);
}
}
}
2019-12-16 18:48:03 +08:00
}
2020-03-11 16:40:07 +08:00
public class Invoker<T>
2019-12-16 18:48:03 +08:00
{
private Action<T> _action;
2019-12-16 18:48:03 +08:00
2020-03-11 16:40:07 +08:00
public Invoker(Action<T> invoker)
2019-12-16 18:48:03 +08:00
{
this._action = invoker;
2019-12-16 18:48:03 +08:00
}
[JSInvokable]
2020-03-11 16:40:07 +08:00
public void Invoke(T param)
2019-12-16 18:48:03 +08:00
{
_action.Invoke(param);
2019-12-16 18:48:03 +08:00
}
}
}