Skip to content

Commit

Permalink
Merge pull request #157 from WalletConnect/fix/listenonce-breaks-aot
Browse files Browse the repository at this point in the history
fix: ListenOnce extension breaks AOT
  • Loading branch information
skibitsky authored Nov 15, 2023
2 parents 60de2c8 + 0e00b86 commit 9002ec5
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 171 deletions.
54 changes: 54 additions & 0 deletions Core Modules/WalletConnectSharp.Common/Utils/EventUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
namespace WalletConnectSharp.Common.Utils;

public class EventUtils
{
/// <summary>
/// Invoke the given event handler once and then unsubscribe it.
/// Use with abstract events. Otherwise, use the extension method as it is more efficient.
/// </summary>
/// <example>
/// <code>
/// EventUtils.ListenOnce((_, _) => WCLogger.Log("Resubscribed")),
/// h => this.Subscriber.Resubscribed += h,
/// h => this.Subscriber.Resubscribed -= h
/// );
/// </code>
/// </example>
public static Action ListenOnce(
EventHandler handler,
Action<EventHandler> subscribe,
Action<EventHandler> unsubscribe)
{
EventHandler internalHandler = null;
internalHandler = (sender, args) =>
{
unsubscribe(internalHandler);
handler(sender, args);
};

subscribe(internalHandler);

return () => unsubscribe(internalHandler);
}

/// <summary>
/// Invoke the given event handler once and then unsubscribe it.
/// Use with abstract events. Otherwise, use the extension method as it is more efficient.
/// </summary>
public static Action ListenOnce<TEventArgs>(
EventHandler<TEventArgs> handler,
Action<EventHandler<TEventArgs>> subscribe,
Action<EventHandler<TEventArgs>> unsubscribe)
{
EventHandler<TEventArgs> internalHandler = null;
internalHandler = (sender, args) =>
{
unsubscribe(internalHandler);
handler(sender, args);
};

subscribe(internalHandler);

return () => unsubscribe(internalHandler);
}
}
88 changes: 58 additions & 30 deletions Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class Extensions
/// <param name="o">The object to check</param>
/// <returns>Returns true if the object has a numeric type</returns>
public static bool IsNumericType(this object o)
{
{
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Byte:
Expand All @@ -29,7 +29,7 @@ public static bool IsNumericType(this object o)
return false;
}
}

/// <summary>
/// Add a query parameter to the given source string
/// </summary>
Expand Down Expand Up @@ -58,77 +58,105 @@ public static string AddQueryParam(
+ "=" + HttpUtility.UrlEncode(value);
}

public static async Task<T> WithTimeout<T>(this Task<T> task, int timeout = 1000, string message = "Timeout of %t exceeded")
public static async Task<T> WithTimeout<T>(this Task<T> task, int timeout = 1000,
string message = "Timeout of %t exceeded")
{
var resultT = await Task.WhenAny(task, Task.Delay(timeout));
if (resultT != task)
{
throw new TimeoutException(message.Replace("%t", timeout.ToString()));
}

return ((Task<T>) resultT).Result;
return ((Task<T>)resultT).Result;
}

public static async Task WithTimeout(this Task task, int timeout = 1000, string message = "Timeout of %t exceeded")

public static async Task WithTimeout(this Task task, int timeout = 1000,
string message = "Timeout of %t exceeded")
{
var resultT = await Task.WhenAny(task, Task.Delay(timeout));
if (resultT != task)
{
throw new TimeoutException(message.Replace("%t", timeout.ToString()));
}
}

public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout, string message = "Timeout of %t exceeded")

public static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout,
string message = "Timeout of %t exceeded")
{
var resultT = await Task.WhenAny(task, Task.Delay(timeout));
if (resultT != task)
{
throw new TimeoutException(message.Replace("%t", timeout.ToString()));
}

return ((Task<T>) resultT).Result;
return ((Task<T>)resultT).Result;
}

public static async Task WithTimeout(this Task task, TimeSpan timeout, string message = "Timeout of %t exceeded")

public static async Task WithTimeout(this Task task, TimeSpan timeout,
string message = "Timeout of %t exceeded")
{
var resultT = await Task.WhenAny(task, Task.Delay(timeout));
if (resultT != task)
{
throw new TimeoutException(message.Replace("%t", timeout.ToString()));
}
}

public static bool SetEquals<T>(this IEnumerable<T> first, IEnumerable<T> second,
IEqualityComparer<T> comparer)
{
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);

public static Action ListenOnce(this EventHandler eventHandler, EventHandler handler)
{
EventHandler internalHandler = null;
internalHandler = (src, args) => {
eventInfo.RemoveEventHandler(eventSource, internalHandler);
handler(src, args);
};
void RemoveListener()
internalHandler = (sender, args) =>
{
eventInfo.RemoveEventHandler(eventSource, internalHandler);
}
eventInfo.AddEventHandler(eventSource, internalHandler);
eventHandler -= internalHandler;
handler(sender, args);
};

eventHandler += internalHandler;

return RemoveListener;
return () =>
{
try
{
eventHandler -= internalHandler;
}
catch (Exception e)

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used

Check warning on line 129 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used
{
// ignored
}
};
}

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

eventHandler += internalHandler;

return () =>
{
try
{
eventHandler -= internalHandler;
}
catch (Exception e)

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (unit-tests)

The variable 'e' is declared but never used

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used

Check warning on line 155 in Core Modules/WalletConnectSharp.Common/Utils/Extensions.cs

View workflow job for this annotation

GitHub Actions / build (integration-tests)

The variable 'e' is declared but never used
{
// ignored
}
};
eventInfo.AddEventHandler(eventSource, internalHandler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ private async Task<WebsocketClient> Register(string url)
TaskCompletionSource<WebsocketClient> registeringTask =
new TaskCompletionSource<WebsocketClient>(TaskCreationOptions.None);

this.ListenOnce<Exception>(nameof(RegisterErrored), (sender, args) =>
RegisterErrored.ListenOnce((sender, args) =>
{
registeringTask.SetException(args);
});

this.ListenOnce<WebsocketClient>(nameof(Opened), (sender, args) =>
Opened.ListenOnce((sender, args) =>
{
registeringTask.SetResult(args);
registeringTask.SetResult((WebsocketClient)args);
});

await registeringTask.Task;
Expand Down
Loading

0 comments on commit 9002ec5

Please sign in to comment.