Skip to content

Commit

Permalink
Merge pull request #132 from WalletConnect/refactor/event-overhaul
Browse files Browse the repository at this point in the history
Overhaul events to use EventHandler
  • Loading branch information
skibitsky authored Oct 26, 2023
2 parents 025e0e7 + 70343b8 commit 2dbfd51
Show file tree
Hide file tree
Showing 72 changed files with 920 additions and 2,104 deletions.
109 changes: 109 additions & 0 deletions Core Modules/WalletConnectSharp.Common/Events/EventHandlerMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
namespace WalletConnectSharp.Common.Events;

/// <summary>
/// A mapping of eventIds to EventHandler objects. This using a Dictionary as the backing datastore
/// </summary>
/// <typeparam name="TEventArgs">The type of EventHandler's argument to store</typeparam>
public class EventHandlerMap<TEventArgs> : IDisposable
{
private Dictionary<string, EventHandler<TEventArgs>> mapping = new();

private readonly object _mappingLock = new();

private EventHandler<TEventArgs> BeforeEventExecuted;

/// <summary>
/// Create a new EventHandlerMap with an initial EventHandler to append onto
/// </summary>
/// <param name="callbackBeforeExecuted">The initial EventHandler to use as the EventHandler.</param>
public EventHandlerMap(EventHandler<TEventArgs> callbackBeforeExecuted = null)
{
if (callbackBeforeExecuted == null)
{
callbackBeforeExecuted = CallbackBeforeExecuted;
}

this.BeforeEventExecuted = callbackBeforeExecuted;
}

private void CallbackBeforeExecuted(object sender, TEventArgs e)
{
}

/// <summary>
/// Get an EventHandler by its eventId. If the provided eventId does not exist, then the
/// initial EventHandler is returned and tracking begins
/// </summary>
/// <param name="eventId">The eventId of the EventHandler</param>
public EventHandler<TEventArgs> this[string eventId]
{
get
{
lock (_mappingLock)
{
mapping.TryAdd(eventId, BeforeEventExecuted);

return mapping[eventId];
}
}
set
{
lock (_mappingLock)
{
if (mapping.ContainsKey(eventId))
{
mapping.Remove(eventId);
}

mapping.Add(eventId, value);
}
}
}

public void ListenOnce(string eventId, EventHandler<TEventArgs> eventHandler)
{
EventHandler<TEventArgs> internalHandler = null;
internalHandler = (src, args) =>
{
this[eventId] -= internalHandler;
eventHandler(src, args);
};
this[eventId] += internalHandler;
}

/// <summary>
/// Check if a given eventId has any EventHandlers registered yet.
/// </summary>
/// <param name="eventId">The eventId to check for</param>
/// <returns>true if the eventId has any EventHandlers, false otherwise</returns>
public bool Contains(string eventId)
{
lock (_mappingLock)
{
return mapping.ContainsKey(eventId);
}
}

/// <summary>
/// Clear an eventId from the mapping
/// </summary>
/// <param name="eventId">The eventId to clear</param>
public void Clear(string eventId)
{
lock (_mappingLock)
{
if (mapping.ContainsKey(eventId))
{
mapping.Remove(eventId);
}
}
}

public void Dispose()
{
lock (_mappingLock)
{
mapping.Clear();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace WalletConnectSharp.Common.Events;

public class GenericEventHolder
{
private Dictionary<Type, object> dynamicTypeMapping = new();

public EventHandlerMap<T> OfType<T>()
{
Type t = typeof(T);

if (dynamicTypeMapping.TryGetValue(t, out var value))
return (EventHandlerMap<T>)value;

var mapping = new EventHandlerMap<T>();
dynamicTypeMapping.Add(t, mapping);

return mapping;
}
}
30 changes: 26 additions & 4 deletions Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;

namespace WalletConnectSharp.Common.Utils
Expand Down Expand Up @@ -108,5 +104,31 @@ public static bool SetEquals<T>(this IEnumerable<T> first, IEnumerable<T> second
return new HashSet<T>(second, comparer ?? EqualityComparer<T>.Default)
.SetEquals(first);
}

public static Action ListenOnce(this object eventSource, string eventName, EventHandler handler) {
var eventInfo = eventSource.GetType().GetEvent(eventName);
EventHandler internalHandler = null;
internalHandler = (src, args) => {
eventInfo.RemoveEventHandler(eventSource, internalHandler);
handler(src, args);
};
void RemoveListener()
{
eventInfo.RemoveEventHandler(eventSource, internalHandler);
}
eventInfo.AddEventHandler(eventSource, internalHandler);

return RemoveListener;
}

public static void ListenOnce<TEventArgs>(this object eventSource, string eventName, EventHandler<TEventArgs> handler) {
var eventInfo = eventSource.GetType().GetEvent(eventName);
EventHandler<TEventArgs> internalHandler = null;
internalHandler = (src, args) => {
eventInfo.RemoveEventHandler(eventSource, internalHandler);
handler(src, args);
};
eventInfo.AddEventHandler(eventSource, internalHandler);
}
}
}
22 changes: 22 additions & 0 deletions Core Modules/WalletConnectSharp.Common/Utils/RpcPayloadId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace WalletConnectSharp.Common.Utils;

/// <summary>
/// A static class that can generate random JSONRPC ids using the current time as a source of randomness
/// </summary>
public static class RpcPayloadId
{
private static readonly Random rng = new Random();
private static readonly DateTime UnixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Generate a new random JSON-RPC id. The clock is used as a source of randomness
/// </summary>
/// <returns>A random JSON-RPC id</returns>
public static long Generate()
{
var date = (long)((DateTime.UtcNow - UnixEpoch).TotalMilliseconds) * (10L * 10L * 10L);
var extra = (long)Math.Floor(rng.NextDouble() * (10.0 * 10.0 * 10.0));
return date + extra;
}
}
Loading

0 comments on commit 2dbfd51

Please sign in to comment.