using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text.Json; using Microsoft.JSInterop; namespace AntDesign.JsInterop { public class DomEventService { private ConcurrentDictionary> _domEventListeners = new ConcurrentDictionary>(); private readonly IJSRuntime _jsRuntime; public DomEventService(IJSRuntime jsRuntime) { _jsRuntime = jsRuntime; } private void AddEventListenerToFirstChildInternal(object dom, string eventName, Action callback) { if (!_domEventListeners.ContainsKey(FormatKey(dom, eventName))) { _jsRuntime.InvokeAsync(JSInteropConstants.AddDomEventListenerToFirstChild, dom, eventName, DotNetObjectReference.Create(new Invoker((p) => { callback?.Invoke(p); }))); } } public void AddEventListener(object dom, string eventName, Action callback, bool exclusive = true) { AddEventListener(dom, eventName, callback, exclusive); } public void AddEventListener(object dom, string eventName, Action callback, bool exclusive = true) { if (exclusive) { _jsRuntime.InvokeAsync(JSInteropConstants.AddDomEventListener, dom, eventName, DotNetObjectReference.Create(new Invoker((p) => { callback(p); }))); } else { string key = FormatKey(dom, eventName); if (!_domEventListeners.ContainsKey(key)) { _domEventListeners[key] = new List(); _jsRuntime.InvokeAsync(JSInteropConstants.AddDomEventListener, dom, eventName, DotNetObjectReference.Create(new Invoker((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 callback) { AddEventListenerToFirstChildInternal(dom, eventName, (e) => { JsonElement jsonElement = JsonDocument.Parse(e).RootElement; callback(jsonElement); }); } public void AddEventListenerToFirstChild(object dom, string eventName, Action callback) { AddEventListenerToFirstChildInternal(dom, eventName, (e) => { T obj = JsonSerializer.Deserialize(e); callback(obj); }); } private static string FormatKey(object dom, string eventName) => $"{dom}-{eventName}"; public void RemoveEventListerner(object dom, string eventName, Action 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); } } } } public class Invoker { private Action _action; public Invoker(Action invoker) { this._action = invoker; } [JSInvokable] public void Invoke(T param) { _action.Invoke(param); } } }