Skip to content

Commit 4f01e19

Browse files
committed
* EventingWrapper and AsyncEventingWrapper improvements and cleanups
1 parent 0f4dfbb commit 4f01e19

File tree

2 files changed

+94
-63
lines changed

2 files changed

+94
-63
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using RabbitMQ.Client.Events;
5+
6+
namespace RabbitMQ.Client.Impl
7+
{
8+
#nullable enable
9+
internal struct AsyncEventingWrapper<T>
10+
{
11+
private event AsyncEventHandler<T>? _event;
12+
private Delegate[]? _handlers;
13+
private string? _context;
14+
private Func<Exception, string, Task>? _onException;
15+
16+
public readonly bool IsEmpty => _event is null;
17+
18+
public AsyncEventingWrapper(string context, Func<Exception, string, Task> onException)
19+
{
20+
_event = null;
21+
_handlers = null;
22+
_context = context;
23+
_onException = onException;
24+
}
25+
26+
public void AddHandler(AsyncEventHandler<T>? handler)
27+
{
28+
_event += handler;
29+
_handlers = null;
30+
}
31+
32+
public void RemoveHandler(AsyncEventHandler<T>? handler)
33+
{
34+
_event -= handler;
35+
_handlers = null;
36+
}
37+
38+
// Do not make this function async! (This type is a struct that gets copied at the start of an async method => empty _handlers is copied)
39+
public Task InvokeAsync(object sender, T parameter)
40+
{
41+
Delegate[]? handlers = _handlers;
42+
if (handlers is null)
43+
{
44+
handlers = _event?.GetInvocationList();
45+
if (handlers is null)
46+
{
47+
return Task.CompletedTask;
48+
}
49+
50+
_handlers = handlers;
51+
}
52+
53+
return InternalInvoke(handlers, sender, parameter);
54+
}
55+
56+
private readonly async Task InternalInvoke(Delegate[] handlers, object sender, T parameter)
57+
{
58+
foreach (AsyncEventHandler<T> action in handlers.Cast<AsyncEventHandler<T>>())
59+
{
60+
try
61+
{
62+
await action(sender, parameter)
63+
.ConfigureAwait(false);
64+
}
65+
catch (Exception exception)
66+
{
67+
if (_onException != null)
68+
{
69+
await _onException(exception, _context!)
70+
.ConfigureAwait(false);
71+
}
72+
else
73+
{
74+
throw;
75+
}
76+
}
77+
}
78+
}
79+
80+
public void Takeover(in AsyncEventingWrapper<T> other)
81+
{
82+
_event = other._event;
83+
_handlers = other._handlers;
84+
_context = other._context;
85+
_onException = other._onException;
86+
}
87+
}
88+
}
Lines changed: 6 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
2-
using System.Threading.Tasks;
3-
using RabbitMQ.Client.Events;
2+
using System.Linq;
43

54
namespace RabbitMQ.Client.Impl
65
{
@@ -12,7 +11,7 @@ internal struct EventingWrapper<T>
1211
private string? _context;
1312
private Action<Exception, string>? _onExceptionAction;
1413

15-
public bool IsEmpty => _event is null;
14+
public readonly bool IsEmpty => _event is null;
1615

1716
public EventingWrapper(string context, Action<Exception, string> onExceptionAction)
1817
{
@@ -42,7 +41,7 @@ public void ClearHandlers()
4241

4342
public void Invoke(object sender, T parameter)
4443
{
45-
var handlers = _handlers;
44+
Delegate[]? handlers = _handlers;
4645
if (handlers is null)
4746
{
4847
handlers = _event?.GetInvocationList();
@@ -53,15 +52,16 @@ public void Invoke(object sender, T parameter)
5352

5453
_handlers = handlers;
5554
}
56-
foreach (EventHandler<T> action in handlers)
55+
56+
foreach (EventHandler<T> action in handlers.Cast<EventHandler<T>>())
5757
{
5858
try
5959
{
6060
action(sender, parameter);
6161
}
6262
catch (Exception exception)
6363
{
64-
var onException = _onExceptionAction;
64+
Action<Exception, string>? onException = _onExceptionAction;
6565
if (onException != null)
6666
{
6767
onException(exception, _context!);
@@ -82,61 +82,4 @@ public void Takeover(in EventingWrapper<T> other)
8282
_onExceptionAction = other._onExceptionAction;
8383
}
8484
}
85-
86-
internal struct AsyncEventingWrapper<T>
87-
{
88-
private event AsyncEventHandler<T>? _event;
89-
private Delegate[]? _handlers;
90-
91-
public bool IsEmpty => _event is null;
92-
93-
public void AddHandler(AsyncEventHandler<T>? handler)
94-
{
95-
_event += handler;
96-
_handlers = null;
97-
}
98-
99-
public void RemoveHandler(AsyncEventHandler<T>? handler)
100-
{
101-
_event -= handler;
102-
_handlers = null;
103-
}
104-
105-
// Do not make this function async! (This type is a struct that gets copied at the start of an async method => empty _handlers is copied)
106-
public Task InvokeAsync(object sender, T parameter)
107-
{
108-
var handlers = _handlers;
109-
if (handlers is null)
110-
{
111-
handlers = _event?.GetInvocationList();
112-
if (handlers is null)
113-
{
114-
return Task.CompletedTask;
115-
}
116-
117-
_handlers = handlers;
118-
}
119-
120-
if (handlers.Length == 1)
121-
{
122-
return ((AsyncEventHandler<T>)handlers[0])(sender, parameter);
123-
}
124-
return InternalInvoke(handlers, sender, parameter);
125-
}
126-
127-
private static async Task InternalInvoke(Delegate[] handlers, object sender, T parameter)
128-
{
129-
foreach (AsyncEventHandler<T> action in handlers)
130-
{
131-
await action(sender, parameter)
132-
.ConfigureAwait(false);
133-
}
134-
}
135-
136-
public void Takeover(in AsyncEventingWrapper<T> other)
137-
{
138-
_event = other._event;
139-
_handlers = other._handlers;
140-
}
141-
}
14285
}

0 commit comments

Comments
 (0)