Skip to content

Commit dca93c5

Browse files
authored
Merge pull request #19 from fretje/unsubscribeweak
Fix bug where RemoveWeak would sometimes remove too much
2 parents ac2ab33 + ad60625 commit dca93c5

3 files changed

Lines changed: 48 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
- Pipelines now fully written in github actions
77
- Updated dependencies
88
- Added documentation comments to `ICourier`, `CourierInjector` and `CourierOptions`
9-
- Use Invoke iso DynamicInvoke for better performance
9+
- Use Invoke iso DynamicInvoke for better performance
10+
- Fix bug where RemoveWeak would sometimes remove too many handlers
1011

1112
# 6.0.0
1213
- Update MediatR to version 12

MediatR.Courier.Tests/WeakReferenceTests.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,31 @@ public async Task UnSubscribedAsyncActionNotInvoked()
3636
Assert.Equal(1, handler.ReceivedMessageCount);
3737
}
3838

39+
[Fact]
40+
public async Task UnSubscribedAsyncActionNotInvokedButOthersAre()
41+
{
42+
var mediatRCourier = new MediatRCourier(new());
43+
44+
var handler = new Handler(new(), new());
45+
var handler2 = new Handler(new(), new());
46+
47+
mediatRCourier.SubscribeWeak<TestNotification>(handler.NotificationAction);
48+
mediatRCourier.SubscribeWeak<TestNotification>(handler.NotificationAction2);
49+
mediatRCourier.SubscribeWeak<TestNotification>(handler2.NotificationAction);
50+
mediatRCourier.SubscribeWeak<TestNotification>(handler2.NotificationAction2);
51+
52+
await mediatRCourier.Handle(new TestNotification(), CancellationToken.None);
53+
54+
mediatRCourier.UnSubscribe<TestNotification>(handler.NotificationAction);
55+
56+
await mediatRCourier.Handle(new TestNotification(), CancellationToken.None);
57+
58+
Assert.Equal(1, handler.ReceivedMessageCount);
59+
Assert.Equal(2, handler.ReceivedMessageCount2);
60+
Assert.Equal(2, handler2.ReceivedMessageCount);
61+
Assert.Equal(2, handler2.ReceivedMessageCount2);
62+
}
63+
3964
[Fact]
4065
[System.Diagnostics.CodeAnalysis.SuppressMessage("Critical Code Smell", "S1215:\"GC.Collect\" should not be called", Justification = "We want to test behavior around GC collection")]
4166
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0079:Remove unnecessary suppression", Justification = "False positive")]
@@ -71,8 +96,13 @@ private sealed class Counter
7196
private sealed class Handler
7297
{
7398
private readonly Counter _counter;
99+
private readonly Counter? _counter2;
74100

75-
public Handler(Counter counter) => _counter = counter;
101+
public Handler(Counter counter, Counter? counter2 = null)
102+
{
103+
_counter = counter;
104+
_counter2 = counter2;
105+
}
76106

77107
#pragma warning disable S1172 // Unused method parameters should be removed
78108
public async Task NotificationAction(TestNotification _, CancellationToken cancellationToken)
@@ -83,6 +113,18 @@ public async Task NotificationAction(TestNotification _, CancellationToken cance
83113
await Task.Delay(TimeSpan.FromMilliseconds(1), cancellationToken);
84114
}
85115

116+
#pragma warning disable S1172 // Unused method parameters should be removed
117+
public async Task NotificationAction2(TestNotification _, CancellationToken cancellationToken)
118+
#pragma warning restore S1172 // Unused method parameters should be removed
119+
{
120+
if (_counter2 is null) return;
121+
122+
_counter2.ReceivedMessageCount++;
123+
124+
await Task.Delay(TimeSpan.FromMilliseconds(1), cancellationToken).ConfigureAwait(false);
125+
}
126+
86127
public int ReceivedMessageCount => _counter.ReceivedMessageCount;
128+
public int? ReceivedMessageCount2 => _counter2?.ReceivedMessageCount;
87129
}
88130
}

MediatR.Courier/MediatRCourier.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ private void RemoveWeak(Delegate handler, Type notificationType)
158158

159159
var remainingSubscribers = new ConcurrentBag<(WeakReference<object> target, MethodInfo methodInfo, bool needsToken)>
160160
(
161-
subscribers.Where(subscriber => !subscriber.target.TryGetTarget(out var weakHandler) && weakHandler != handler.Target)
161+
subscribers.Where(subscriber =>
162+
(subscriber.target.TryGetTarget(out var weakHandler) && weakHandler != handler.Target)
163+
|| subscriber.methodInfo != handler.Method)
162164
);
163165

164166
_weakActions.TryRemove(notificationType, out _);

0 commit comments

Comments
 (0)