com.wallstop-studios.dxmessaging 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.github/workflows/dotnet-tests.yml +3 -3
  2. package/.github/workflows/prettier-autofix.yml +0 -7
  3. package/.pre-commit-config.yaml +8 -5
  4. package/AGENTS.md +12 -12
  5. package/CONTRIBUTING.md +8 -2
  6. package/Docs/Comparisons.md +5 -5
  7. package/Docs/InterceptorsAndOrdering.md +1 -1
  8. package/Docs/Performance.md +13 -13
  9. package/Docs/QuickReference.md +1 -1
  10. package/Docs/Reference.md +5 -5
  11. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  12. package/Editor/CustomEditors/MessagingComponentEditor.cs +3 -0
  13. package/Editor/DxMessagingEditorInitializer.cs +58 -1
  14. package/Editor/DxMessagingMenu.cs +38 -0
  15. package/Editor/DxMessagingMenu.cs.meta +11 -0
  16. package/Editor/DxMessagingSceneBuildProcessor.cs +81 -0
  17. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -0
  18. package/Editor/Settings/DxMessagingSettings.cs +37 -6
  19. package/Editor/Settings/DxMessagingSettingsProvider.cs +45 -7
  20. package/README.md +1 -1
  21. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +52 -0
  22. package/Runtime/Core/DataStructure/CyclicBuffer.cs +16 -0
  23. package/Runtime/Core/Diagnostics/MessageEmissionData.cs +1 -1
  24. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +62 -0
  25. package/Runtime/Core/DxMessagingStaticState.cs +108 -0
  26. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -0
  27. package/Runtime/Core/Extensions/IListExtensions.cs +24 -0
  28. package/Runtime/Core/Extensions/MessageBusExtensions.cs +142 -0
  29. package/Runtime/Core/Helper/MessageCache.cs +16 -0
  30. package/Runtime/Core/Helper/MessageHelperIndexer.cs +77 -0
  31. package/Runtime/Core/InstanceId.cs +86 -0
  32. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs +31 -0
  33. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -0
  34. package/Runtime/Core/MessageBus/IMessageBus.cs +44 -16
  35. package/Runtime/Core/MessageBus/MessageBus.cs +167 -180
  36. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +44 -0
  37. package/Runtime/Core/MessageBus/MessagingRegistration.cs +60 -2
  38. package/Runtime/Core/MessageBus/RegistrationLog.cs +10 -0
  39. package/Runtime/Core/MessageHandler.cs +107 -6
  40. package/Runtime/Core/MessageRegistrationHandle.cs +59 -0
  41. package/Runtime/Core/MessageRegistrationToken.cs +18 -2
  42. package/Runtime/Core/Messages/ReflexiveMessage.cs +38 -0
  43. package/Runtime/Core/MessagingDebug.cs +16 -1
  44. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +4 -0
  45. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs +19 -0
  46. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -0
  47. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +4 -0
  48. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +17 -0
  49. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +8 -0
  50. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +12 -0
  51. package/Runtime/Unity/MessagingComponent.cs +93 -0
  52. package/Samples~/DI/README.md +13 -13
  53. package/Samples~/Mini Combat/README.md +15 -15
  54. package/Samples~/Mini Combat/Walkthrough.md +12 -12
  55. package/Samples~/UI Buttons + Inspector/README.md +4 -4
  56. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +4 -0
  57. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +4 -0
  58. package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -3
  59. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs +69 -0
  60. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs.meta +11 -0
  61. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +12 -31
  62. package/Tests/Runtime/Core/OrderingManyRegistrationsTests.cs +683 -0
  63. package/Tests/Runtime/Core/OrderingManyRegistrationsTests.cs.meta +11 -0
  64. package/package.json +1 -1
  65. package/scripts/fix-eol.js +38 -3
  66. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +0 -20
  67. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta +0 -7
@@ -32,6 +32,31 @@ namespace DxMessaging.Core.MessageBus
32
32
  public long version;
33
33
  public long lastSeenVersion = -1;
34
34
  public long lastSeenEmissionId;
35
+
36
+ /// <summary>
37
+ /// Clears all cached handler references and resets the version tracking metadata.
38
+ /// </summary>
39
+ public void Clear()
40
+ {
41
+ handlers.Clear();
42
+ order.Clear();
43
+ cache.Clear();
44
+ version = 0;
45
+ lastSeenVersion = -1;
46
+ lastSeenEmissionId = 0;
47
+ }
48
+ }
49
+
50
+ private sealed class InterceptorCache<TValue>
51
+ {
52
+ public readonly SortedList<int, List<TValue>> handlers = new();
53
+ public long lastSeenEmissionId;
54
+
55
+ public void Clear()
56
+ {
57
+ handlers.Clear();
58
+ lastSeenEmissionId = 0;
59
+ }
35
60
  }
36
61
 
37
62
  private sealed class HandlerCache
@@ -41,6 +66,18 @@ namespace DxMessaging.Core.MessageBus
41
66
  public long version;
42
67
  public long lastSeenVersion = -1;
43
68
  public long lastSeenEmissionId;
69
+
70
+ /// <summary>
71
+ /// Clears all cached handler references and resets the version tracking metadata.
72
+ /// </summary>
73
+ public void Clear()
74
+ {
75
+ handlers.Clear();
76
+ cache.Clear();
77
+ version = 0;
78
+ lastSeenVersion = -1;
79
+ lastSeenEmissionId = 0;
80
+ }
44
81
  }
45
82
 
46
83
  public int RegisteredTargeted
@@ -48,14 +85,11 @@ namespace DxMessaging.Core.MessageBus
48
85
  get
49
86
  {
50
87
  int count = 0;
51
- using MessageCache<
52
- Dictionary<InstanceId, HandlerCache<int, HandlerCache>>
53
- >.MessageCacheEnumerator enumeratorT = _targetedSinks.GetEnumerator();
54
- while (enumeratorT.MoveNext())
88
+ foreach (
89
+ Dictionary<InstanceId, HandlerCache<int, HandlerCache>> entry in _targetedSinks
90
+ )
55
91
  {
56
- Dictionary<InstanceId, HandlerCache<int, HandlerCache>> entry =
57
- enumeratorT.Current;
58
- count += entry.Count;
92
+ count += entry?.Count ?? 0;
59
93
  }
60
94
 
61
95
  return count;
@@ -69,14 +103,11 @@ namespace DxMessaging.Core.MessageBus
69
103
  get
70
104
  {
71
105
  int count = 0;
72
- using MessageCache<
73
- Dictionary<InstanceId, HandlerCache<int, HandlerCache>>
74
- >.MessageCacheEnumerator enumeratorB = _broadcastSinks.GetEnumerator();
75
- while (enumeratorB.MoveNext())
106
+ foreach (
107
+ Dictionary<InstanceId, HandlerCache<int, HandlerCache>> entry in _broadcastSinks
108
+ )
76
109
  {
77
- Dictionary<InstanceId, HandlerCache<int, HandlerCache>> entry =
78
- enumeratorB.Current;
79
- count += entry.Count;
110
+ count += entry?.Count ?? 0;
80
111
  }
81
112
 
82
113
  return count;
@@ -88,13 +119,9 @@ namespace DxMessaging.Core.MessageBus
88
119
  get
89
120
  {
90
121
  int count = 0;
91
- using MessageCache<
92
- HandlerCache<int, HandlerCache>
93
- >.MessageCacheEnumerator enumeratorU = _sinks.GetEnumerator();
94
- while (enumeratorU.MoveNext())
122
+ foreach (HandlerCache<int, HandlerCache> entry in _sinks)
95
123
  {
96
- HandlerCache<int, HandlerCache> entry = enumeratorU.Current;
97
- count += entry.handlers.Count;
124
+ count += entry?.handlers?.Count ?? 0;
98
125
  }
99
126
 
100
127
  return count;
@@ -150,12 +177,9 @@ namespace DxMessaging.Core.MessageBus
150
177
  private readonly HandlerCache _globalSinks = new();
151
178
 
152
179
  // Interceptors split by category to avoid mixing types
153
- private readonly MessageCache<HandlerCache<int, List<object>>> _untargetedInterceptsByType =
154
- new();
155
- private readonly MessageCache<HandlerCache<int, List<object>>> _targetedInterceptsByType =
156
- new();
157
- private readonly MessageCache<HandlerCache<int, List<object>>> _broadcastInterceptsByType =
158
- new();
180
+ private readonly MessageCache<InterceptorCache<object>> _untargetedInterceptsByType = new();
181
+ private readonly MessageCache<InterceptorCache<object>> _targetedInterceptsByType = new();
182
+ private readonly MessageCache<InterceptorCache<object>> _broadcastInterceptsByType = new();
159
183
  private readonly Dictionary<object, Dictionary<int, int>> _uniqueInterceptorsAndPriorities =
160
184
  new();
161
185
 
@@ -177,9 +201,46 @@ namespace DxMessaging.Core.MessageBus
177
201
  GlobalMessageBufferSize
178
202
  );
179
203
 
180
- private bool _diagnosticsMode = GlobalDiagnosticsMode;
204
+ private bool _diagnosticsMode = IMessageBus.ShouldEnableDiagnostics();
181
205
  private bool _loggedReflexiveWarning;
182
206
 
207
+ internal void ResetState()
208
+ {
209
+ _emissionId = 0;
210
+ _diagnosticsMode = IMessageBus.ShouldEnableDiagnostics();
211
+ _loggedReflexiveWarning = false;
212
+
213
+ _sinks.Clear();
214
+ _targetedSinks.Clear();
215
+ _broadcastSinks.Clear();
216
+ _postProcessingSinks.Clear();
217
+ _postProcessingTargetedSinks.Clear();
218
+ _postProcessingBroadcastSinks.Clear();
219
+ _postProcessingTargetedWithoutTargetingSinks.Clear();
220
+ _postProcessingBroadcastWithoutSourceSinks.Clear();
221
+ _globalSinks.Clear();
222
+
223
+ _untargetedInterceptsByType.Clear();
224
+ _targetedInterceptsByType.Clear();
225
+ _broadcastInterceptsByType.Clear();
226
+ _uniqueInterceptorsAndPriorities.Clear();
227
+ _broadcastMethodsByType.Clear();
228
+ _innerInterceptorsStack.Clear();
229
+ _methodCache.Clear();
230
+
231
+ #if UNITY_2021_3_OR_NEWER
232
+ _recipientCache.Clear();
233
+ _componentCache.Clear();
234
+ #endif
235
+
236
+ bool enabled = _log.Enabled;
237
+ _log.Clear();
238
+ _log.Enabled = enabled;
239
+ _emissionBuffer.Resize(GlobalMessageBufferSize);
240
+ _emissionBuffer.Clear();
241
+ }
242
+
243
+ /// <inheritdoc />
183
244
  public Action RegisterUntargeted<T>(MessageHandler messageHandler, int priority = 0)
184
245
  where T : IUntargetedMessage
185
246
  {
@@ -191,6 +252,7 @@ namespace DxMessaging.Core.MessageBus
191
252
  );
192
253
  }
193
254
 
255
+ /// <inheritdoc />
194
256
  public Action RegisterTargeted<T>(
195
257
  InstanceId target,
196
258
  MessageHandler messageHandler,
@@ -207,6 +269,7 @@ namespace DxMessaging.Core.MessageBus
207
269
  );
208
270
  }
209
271
 
272
+ /// <inheritdoc />
210
273
  public Action RegisterSourcedBroadcast<T>(
211
274
  InstanceId source,
212
275
  MessageHandler messageHandler,
@@ -223,6 +286,7 @@ namespace DxMessaging.Core.MessageBus
223
286
  );
224
287
  }
225
288
 
289
+ /// <inheritdoc />
226
290
  public Action RegisterSourcedBroadcastWithoutSource<T>(
227
291
  MessageHandler messageHandler,
228
292
  int priority = 0
@@ -237,6 +301,7 @@ namespace DxMessaging.Core.MessageBus
237
301
  );
238
302
  }
239
303
 
304
+ /// <inheritdoc />
240
305
  public Action RegisterTargetedWithoutTargeting<T>(
241
306
  MessageHandler messageHandler,
242
307
  int priority = 0
@@ -251,6 +316,7 @@ namespace DxMessaging.Core.MessageBus
251
316
  );
252
317
  }
253
318
 
319
+ /// <inheritdoc />
254
320
  public Action RegisterGlobalAcceptAll(MessageHandler messageHandler)
255
321
  {
256
322
  _globalSinks.version++;
@@ -303,35 +369,16 @@ namespace DxMessaging.Core.MessageBus
303
369
  };
304
370
  }
305
371
 
372
+ /// <inheritdoc />
306
373
  public Action RegisterUntargetedInterceptor<T>(
307
374
  UntargetedInterceptor<T> interceptor,
308
375
  int priority = 0
309
376
  )
310
377
  where T : IUntargetedMessage
311
378
  {
312
- HandlerCache<int, List<object>> prioritizedInterceptors =
379
+ InterceptorCache<object> prioritizedInterceptors =
313
380
  _untargetedInterceptsByType.GetOrAdd<T>();
314
381
 
315
- if (
316
- !prioritizedInterceptors.handlers.TryGetValue(
317
- priority,
318
- out List<object> interceptors
319
- )
320
- )
321
- {
322
- prioritizedInterceptors.version++;
323
- interceptors = new List<object>();
324
- prioritizedInterceptors.handlers[priority] = interceptors;
325
- // maintain sorted order
326
- List<int> order = prioritizedInterceptors.order;
327
- int idx = 0;
328
- while (idx < order.Count && order[idx] < priority)
329
- {
330
- idx++;
331
- }
332
- order.Insert(idx, priority);
333
- }
334
-
335
382
  if (
336
383
  !_uniqueInterceptorsAndPriorities.TryGetValue(
337
384
  interceptor,
@@ -343,6 +390,13 @@ namespace DxMessaging.Core.MessageBus
343
390
  _uniqueInterceptorsAndPriorities[interceptor] = priorityCount;
344
391
  }
345
392
 
393
+ List<object> interceptors;
394
+ if (!prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors))
395
+ {
396
+ interceptors = new List<object>();
397
+ prioritizedInterceptors.handlers.Add(priority, interceptors);
398
+ }
399
+
346
400
  if (!priorityCount.TryGetValue(priority, out int count))
347
401
  {
348
402
  count = 0;
@@ -406,20 +460,17 @@ namespace DxMessaging.Core.MessageBus
406
460
  {
407
461
  if (_untargetedInterceptsByType.TryGetValue<T>(out prioritizedInterceptors))
408
462
  {
409
- prioritizedInterceptors.version++;
410
463
  if (
411
- prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors)
464
+ prioritizedInterceptors.handlers.TryGetValue(
465
+ priority,
466
+ out List<object> interceptors
467
+ )
412
468
  )
413
469
  {
414
470
  complete = interceptors.Remove(interceptor);
415
471
  if (interceptors.Count == 0)
416
472
  {
417
473
  _ = prioritizedInterceptors.handlers.Remove(priority);
418
- int removeIdx = prioritizedInterceptors.order.IndexOf(priority);
419
- if (removeIdx >= 0)
420
- {
421
- prioritizedInterceptors.order.RemoveAt(removeIdx);
422
- }
423
474
  }
424
475
  }
425
476
  }
@@ -436,35 +487,16 @@ namespace DxMessaging.Core.MessageBus
436
487
  };
437
488
  }
438
489
 
490
+ /// <inheritdoc />
439
491
  public Action RegisterTargetedInterceptor<T>(
440
492
  TargetedInterceptor<T> interceptor,
441
493
  int priority = 0
442
494
  )
443
495
  where T : ITargetedMessage
444
496
  {
445
- HandlerCache<int, List<object>> prioritizedInterceptors =
497
+ InterceptorCache<object> prioritizedInterceptors =
446
498
  _targetedInterceptsByType.GetOrAdd<T>();
447
499
 
448
- if (
449
- !prioritizedInterceptors.handlers.TryGetValue(
450
- priority,
451
- out List<object> interceptors
452
- )
453
- )
454
- {
455
- prioritizedInterceptors.version++;
456
- interceptors = new List<object>();
457
- prioritizedInterceptors.handlers[priority] = interceptors;
458
- // maintain sorted order
459
- List<int> order = prioritizedInterceptors.order;
460
- int idx = 0;
461
- while (idx < order.Count && order[idx] < priority)
462
- {
463
- idx++;
464
- }
465
- order.Insert(idx, priority);
466
- }
467
-
468
500
  if (
469
501
  !_uniqueInterceptorsAndPriorities.TryGetValue(
470
502
  interceptor,
@@ -476,6 +508,13 @@ namespace DxMessaging.Core.MessageBus
476
508
  _uniqueInterceptorsAndPriorities[interceptor] = priorityCount;
477
509
  }
478
510
 
511
+ List<object> interceptors;
512
+ if (!prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors))
513
+ {
514
+ interceptors = new List<object>();
515
+ prioritizedInterceptors.handlers.Add(priority, interceptors);
516
+ }
517
+
479
518
  if (!priorityCount.TryGetValue(priority, out int count))
480
519
  {
481
520
  count = 0;
@@ -539,20 +578,17 @@ namespace DxMessaging.Core.MessageBus
539
578
  {
540
579
  if (_targetedInterceptsByType.TryGetValue<T>(out prioritizedInterceptors))
541
580
  {
542
- prioritizedInterceptors.version++;
543
581
  if (
544
- prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors)
582
+ prioritizedInterceptors.handlers.TryGetValue(
583
+ priority,
584
+ out List<object> interceptors
585
+ )
545
586
  )
546
587
  {
547
588
  complete = interceptors.Remove(interceptor);
548
589
  if (interceptors.Count == 0)
549
590
  {
550
591
  _ = prioritizedInterceptors.handlers.Remove(priority);
551
- int removeIdx = prioritizedInterceptors.order.IndexOf(priority);
552
- if (removeIdx >= 0)
553
- {
554
- prioritizedInterceptors.order.RemoveAt(removeIdx);
555
- }
556
592
  }
557
593
  }
558
594
  }
@@ -569,35 +605,16 @@ namespace DxMessaging.Core.MessageBus
569
605
  };
570
606
  }
571
607
 
608
+ /// <inheritdoc />
572
609
  public Action RegisterBroadcastInterceptor<T>(
573
610
  BroadcastInterceptor<T> interceptor,
574
611
  int priority = 0
575
612
  )
576
613
  where T : IBroadcastMessage
577
614
  {
578
- HandlerCache<int, List<object>> prioritizedInterceptors =
615
+ InterceptorCache<object> prioritizedInterceptors =
579
616
  _broadcastInterceptsByType.GetOrAdd<T>();
580
617
 
581
- if (
582
- !prioritizedInterceptors.handlers.TryGetValue(
583
- priority,
584
- out List<object> interceptors
585
- )
586
- )
587
- {
588
- prioritizedInterceptors.version++;
589
- interceptors = new List<object>();
590
- prioritizedInterceptors.handlers[priority] = interceptors;
591
- // maintain sorted order
592
- List<int> order = prioritizedInterceptors.order;
593
- int idx = 0;
594
- while (idx < order.Count && order[idx] < priority)
595
- {
596
- idx++;
597
- }
598
- order.Insert(idx, priority);
599
- }
600
-
601
618
  if (
602
619
  !_uniqueInterceptorsAndPriorities.TryGetValue(
603
620
  interceptor,
@@ -609,6 +626,13 @@ namespace DxMessaging.Core.MessageBus
609
626
  _uniqueInterceptorsAndPriorities[interceptor] = priorityCount;
610
627
  }
611
628
 
629
+ List<object> interceptors;
630
+ if (!prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors))
631
+ {
632
+ interceptors = new List<object>();
633
+ prioritizedInterceptors.handlers.Add(priority, interceptors);
634
+ }
635
+
612
636
  if (!priorityCount.TryGetValue(priority, out int count))
613
637
  {
614
638
  count = 0;
@@ -672,20 +696,17 @@ namespace DxMessaging.Core.MessageBus
672
696
  {
673
697
  if (_broadcastInterceptsByType.TryGetValue<T>(out prioritizedInterceptors))
674
698
  {
675
- prioritizedInterceptors.version++;
676
699
  if (
677
- prioritizedInterceptors.handlers.TryGetValue(priority, out interceptors)
700
+ prioritizedInterceptors.handlers.TryGetValue(
701
+ priority,
702
+ out List<object> interceptors
703
+ )
678
704
  )
679
705
  {
680
706
  complete = interceptors.Remove(interceptor);
681
707
  if (interceptors.Count == 0)
682
708
  {
683
709
  _ = prioritizedInterceptors.handlers.Remove(priority);
684
- int removeIdx = prioritizedInterceptors.order.IndexOf(priority);
685
- if (removeIdx >= 0)
686
- {
687
- prioritizedInterceptors.order.RemoveAt(removeIdx);
688
- }
689
710
  }
690
711
  }
691
712
  }
@@ -702,6 +723,7 @@ namespace DxMessaging.Core.MessageBus
702
723
  };
703
724
  }
704
725
 
726
+ /// <inheritdoc />
705
727
  public Action RegisterUntargetedPostProcessor<T>(
706
728
  MessageHandler messageHandler,
707
729
  int priority = 0
@@ -716,6 +738,7 @@ namespace DxMessaging.Core.MessageBus
716
738
  );
717
739
  }
718
740
 
741
+ /// <inheritdoc />
719
742
  public Action RegisterTargetedPostProcessor<T>(
720
743
  InstanceId target,
721
744
  MessageHandler messageHandler,
@@ -732,6 +755,7 @@ namespace DxMessaging.Core.MessageBus
732
755
  );
733
756
  }
734
757
 
758
+ /// <inheritdoc />
735
759
  public Action RegisterTargetedWithoutTargetingPostProcessor<T>(
736
760
  MessageHandler messageHandler,
737
761
  int priority = 0
@@ -746,6 +770,7 @@ namespace DxMessaging.Core.MessageBus
746
770
  );
747
771
  }
748
772
 
773
+ /// <inheritdoc />
749
774
  public Action RegisterBroadcastPostProcessor<T>(
750
775
  InstanceId source,
751
776
  MessageHandler messageHandler,
@@ -762,6 +787,7 @@ namespace DxMessaging.Core.MessageBus
762
787
  );
763
788
  }
764
789
 
790
+ /// <inheritdoc />
765
791
  public Action RegisterBroadcastWithoutSourcePostProcessor<T>(
766
792
  MessageHandler messageHandler,
767
793
  int priority = 0
@@ -778,6 +804,7 @@ namespace DxMessaging.Core.MessageBus
778
804
 
779
805
  // Legacy RegisterInterceptor removed in favor of split implementations above
780
806
 
807
+ /// <inheritdoc />
781
808
  public void UntypedUntargetedBroadcast(IUntargetedMessage typedMessage)
782
809
  {
783
810
  Type messageType = typedMessage.MessageType;
@@ -807,6 +834,7 @@ namespace DxMessaging.Core.MessageBus
807
834
  broadcast.Invoke(typedMessage);
808
835
  }
809
836
 
837
+ /// <inheritdoc />
810
838
  public void UntargetedBroadcast<TMessage>(ref TMessage typedMessage)
811
839
  where TMessage : IUntargetedMessage
812
840
  {
@@ -1010,6 +1038,7 @@ namespace DxMessaging.Core.MessageBus
1010
1038
  }
1011
1039
  }
1012
1040
 
1041
+ /// <inheritdoc />
1013
1042
  public void UntypedTargetedBroadcast(InstanceId target, ITargetedMessage typedMessage)
1014
1043
  {
1015
1044
  Type messageType = typedMessage.MessageType;
@@ -1039,6 +1068,7 @@ namespace DxMessaging.Core.MessageBus
1039
1068
  broadcast.Invoke(target, typedMessage);
1040
1069
  }
1041
1070
 
1071
+ /// <inheritdoc />
1042
1072
  public void TargetedBroadcast<TMessage>(ref InstanceId target, ref TMessage typedMessage)
1043
1073
  where TMessage : ITargetedMessage
1044
1074
  {
@@ -2047,6 +2077,7 @@ namespace DxMessaging.Core.MessageBus
2047
2077
  }
2048
2078
  }
2049
2079
 
2080
+ /// <inheritdoc />
2050
2081
  public void UntypedSourcedBroadcast(InstanceId source, IBroadcastMessage typedMessage)
2051
2082
  {
2052
2083
  Type messageType = typedMessage.MessageType;
@@ -2079,6 +2110,7 @@ namespace DxMessaging.Core.MessageBus
2079
2110
  broadcast.Invoke(source, typedMessage);
2080
2111
  }
2081
2112
 
2113
+ /// <inheritdoc />
2082
2114
  public void SourcedBroadcast<TMessage>(ref InstanceId source, ref TMessage typedMessage)
2083
2115
  where TMessage : IBroadcastMessage
2084
2116
  {
@@ -2939,39 +2971,24 @@ namespace DxMessaging.Core.MessageBus
2939
2971
  }
2940
2972
 
2941
2973
  private bool TryGetUntargetedInterceptorCaches<TMessage>(
2942
- out List<KeyValuePair<int, List<object>>> interceptorStack,
2974
+ out SortedList<int, List<object>> interceptorHandlers,
2943
2975
  out List<object> interceptorObjects
2944
2976
  )
2945
2977
  where TMessage : IUntargetedMessage
2946
2978
  {
2947
2979
  if (
2948
2980
  !_untargetedInterceptsByType.TryGetValue<TMessage>(
2949
- out HandlerCache<int, List<object>> interceptors
2981
+ out InterceptorCache<object> interceptors
2950
2982
  )
2951
2983
  || interceptors.handlers.Count == 0
2952
2984
  )
2953
2985
  {
2954
- interceptorStack = default;
2986
+ interceptorHandlers = default;
2955
2987
  interceptorObjects = default;
2956
2988
  return false;
2957
2989
  }
2958
2990
 
2959
- interceptorStack = interceptors.cache;
2960
- if (interceptors.version != interceptors.lastSeenVersion)
2961
- {
2962
- interceptorStack.Clear();
2963
- List<int> keys = interceptors.order;
2964
- for (int i = 0; i < keys.Count; ++i)
2965
- {
2966
- int key = keys[i];
2967
- if (interceptors.handlers.TryGetValue(key, out List<object> values))
2968
- {
2969
- interceptorStack.Add(new KeyValuePair<int, List<object>>(key, values));
2970
- }
2971
- }
2972
-
2973
- interceptors.lastSeenVersion = interceptors.version;
2974
- }
2991
+ interceptorHandlers = interceptors.handlers;
2975
2992
 
2976
2993
  if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
2977
2994
  {
@@ -2982,39 +2999,24 @@ namespace DxMessaging.Core.MessageBus
2982
2999
  }
2983
3000
 
2984
3001
  private bool TryGetTargetedInterceptorCaches<TMessage>(
2985
- out List<KeyValuePair<int, List<object>>> interceptorStack,
3002
+ out SortedList<int, List<object>> interceptorHandlers,
2986
3003
  out List<object> interceptorObjects
2987
3004
  )
2988
3005
  where TMessage : ITargetedMessage
2989
3006
  {
2990
3007
  if (
2991
3008
  !_targetedInterceptsByType.TryGetValue<TMessage>(
2992
- out HandlerCache<int, List<object>> interceptors
3009
+ out InterceptorCache<object> interceptors
2993
3010
  )
2994
3011
  || interceptors.handlers.Count == 0
2995
3012
  )
2996
3013
  {
2997
- interceptorStack = default;
3014
+ interceptorHandlers = default;
2998
3015
  interceptorObjects = default;
2999
3016
  return false;
3000
3017
  }
3001
3018
 
3002
- interceptorStack = interceptors.cache;
3003
- if (interceptors.version != interceptors.lastSeenVersion)
3004
- {
3005
- interceptorStack.Clear();
3006
- List<int> keys = interceptors.order;
3007
- for (int i = 0; i < keys.Count; ++i)
3008
- {
3009
- int key = keys[i];
3010
- if (interceptors.handlers.TryGetValue(key, out List<object> values))
3011
- {
3012
- interceptorStack.Add(new KeyValuePair<int, List<object>>(key, values));
3013
- }
3014
- }
3015
-
3016
- interceptors.lastSeenVersion = interceptors.version;
3017
- }
3019
+ interceptorHandlers = interceptors.handlers;
3018
3020
 
3019
3021
  if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
3020
3022
  {
@@ -3025,39 +3027,24 @@ namespace DxMessaging.Core.MessageBus
3025
3027
  }
3026
3028
 
3027
3029
  private bool TryGetBroadcastInterceptorCaches<TMessage>(
3028
- out List<KeyValuePair<int, List<object>>> interceptorStack,
3030
+ out SortedList<int, List<object>> interceptorHandlers,
3029
3031
  out List<object> interceptorObjects
3030
3032
  )
3031
3033
  where TMessage : IBroadcastMessage
3032
3034
  {
3033
3035
  if (
3034
3036
  !_broadcastInterceptsByType.TryGetValue<TMessage>(
3035
- out HandlerCache<int, List<object>> interceptors
3037
+ out InterceptorCache<object> interceptors
3036
3038
  )
3037
3039
  || interceptors.handlers.Count == 0
3038
3040
  )
3039
3041
  {
3040
- interceptorStack = default;
3042
+ interceptorHandlers = default;
3041
3043
  interceptorObjects = default;
3042
3044
  return false;
3043
3045
  }
3044
3046
 
3045
- interceptorStack = interceptors.cache;
3046
- if (interceptors.version != interceptors.lastSeenVersion)
3047
- {
3048
- interceptorStack.Clear();
3049
- List<int> keys = interceptors.order;
3050
- for (int i = 0; i < keys.Count; ++i)
3051
- {
3052
- int key = keys[i];
3053
- if (interceptors.handlers.TryGetValue(key, out List<object> values))
3054
- {
3055
- interceptorStack.Add(new KeyValuePair<int, List<object>>(key, values));
3056
- }
3057
- }
3058
-
3059
- interceptors.lastSeenVersion = interceptors.version;
3060
- }
3047
+ interceptorHandlers = interceptors.handlers;
3061
3048
 
3062
3049
  if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
3063
3050
  {
@@ -3072,7 +3059,7 @@ namespace DxMessaging.Core.MessageBus
3072
3059
  {
3073
3060
  if (
3074
3061
  !TryGetUntargetedInterceptorCaches<T>(
3075
- out List<KeyValuePair<int, List<object>>> interceptorStack,
3062
+ out SortedList<int, List<object>> interceptorHandlers,
3076
3063
  out List<object> interceptorObjects
3077
3064
  )
3078
3065
  )
@@ -3082,11 +3069,11 @@ namespace DxMessaging.Core.MessageBus
3082
3069
 
3083
3070
  try
3084
3071
  {
3085
- for (int s = 0; s < interceptorStack.Count; ++s)
3072
+ IList<List<object>> prioritizedInterceptors = interceptorHandlers.Values;
3073
+ for (int s = 0; s < prioritizedInterceptors.Count; ++s)
3086
3074
  {
3087
- KeyValuePair<int, List<object>> entry = interceptorStack[s];
3088
3075
  interceptorObjects.Clear();
3089
- List<object> interceptors = entry.Value;
3076
+ List<object> interceptors = prioritizedInterceptors[s];
3090
3077
  interceptorObjects.AddRange(interceptors);
3091
3078
 
3092
3079
  for (int i = 0; i < interceptorObjects.Count; ++i)
@@ -3114,7 +3101,7 @@ namespace DxMessaging.Core.MessageBus
3114
3101
  {
3115
3102
  if (
3116
3103
  !TryGetTargetedInterceptorCaches<T>(
3117
- out List<KeyValuePair<int, List<object>>> interceptorStack,
3104
+ out SortedList<int, List<object>> interceptorHandlers,
3118
3105
  out List<object> interceptorObjects
3119
3106
  )
3120
3107
  )
@@ -3124,11 +3111,11 @@ namespace DxMessaging.Core.MessageBus
3124
3111
 
3125
3112
  try
3126
3113
  {
3127
- for (int s = 0; s < interceptorStack.Count; ++s)
3114
+ IList<List<object>> prioritizedInterceptors = interceptorHandlers.Values;
3115
+ for (int s = 0; s < prioritizedInterceptors.Count; ++s)
3128
3116
  {
3129
- KeyValuePair<int, List<object>> entry = interceptorStack[s];
3130
3117
  interceptorObjects.Clear();
3131
- List<object> interceptors = entry.Value;
3118
+ List<object> interceptors = prioritizedInterceptors[s];
3132
3119
  interceptorObjects.AddRange(interceptors);
3133
3120
 
3134
3121
  for (int i = 0; i < interceptorObjects.Count; ++i)
@@ -3156,7 +3143,7 @@ namespace DxMessaging.Core.MessageBus
3156
3143
  {
3157
3144
  if (
3158
3145
  !TryGetBroadcastInterceptorCaches<T>(
3159
- out List<KeyValuePair<int, List<object>>> interceptorStack,
3146
+ out SortedList<int, List<object>> interceptorHandlers,
3160
3147
  out List<object> interceptorObjects
3161
3148
  )
3162
3149
  )
@@ -3166,11 +3153,11 @@ namespace DxMessaging.Core.MessageBus
3166
3153
 
3167
3154
  try
3168
3155
  {
3169
- for (int s = 0; s < interceptorStack.Count; ++s)
3156
+ IList<List<object>> prioritizedInterceptors = interceptorHandlers.Values;
3157
+ for (int s = 0; s < prioritizedInterceptors.Count; ++s)
3170
3158
  {
3171
- KeyValuePair<int, List<object>> entry = interceptorStack[s];
3172
3159
  interceptorObjects.Clear();
3173
- List<object> interceptors = entry.Value;
3160
+ List<object> interceptors = prioritizedInterceptors[s];
3174
3161
  interceptorObjects.AddRange(interceptors);
3175
3162
 
3176
3163
  for (int i = 0; i < interceptorObjects.Count; ++i)