com.wallstop-studios.dxmessaging 2.0.0-rc12 → 2.0.0-rc13

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 (106) hide show
  1. package/.gitattributes +63 -63
  2. package/.github/workflows/npm-publish.yml +66 -0
  3. package/CHANGELOG.md.meta +7 -7
  4. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +33 -33
  5. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +33 -33
  6. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +33 -33
  7. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +71 -71
  8. package/Editor/Analyzers.meta +8 -8
  9. package/Editor/SetupCscRsp.cs +162 -162
  10. package/Editor/SetupCscRsp.cs.meta +2 -2
  11. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +17 -17
  12. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
  13. package/Editor.meta +8 -8
  14. package/LICENSE.md +6 -6
  15. package/LICENSE.md.meta +7 -7
  16. package/README.md +387 -364
  17. package/README.md.meta +7 -7
  18. package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs +7 -7
  19. package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs.meta +2 -2
  20. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +7 -7
  21. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +2 -2
  22. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +7 -7
  23. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +2 -2
  24. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +7 -7
  25. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +2 -2
  26. package/Runtime/Core/Attributes.meta +2 -2
  27. package/Runtime/Core/Extensions/MessageExtensions.cs +342 -342
  28. package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
  29. package/Runtime/Core/Extensions.meta +8 -8
  30. package/Runtime/Core/IMessage.cs +12 -12
  31. package/Runtime/Core/IMessage.cs.meta +11 -11
  32. package/Runtime/Core/InstanceId.cs +149 -149
  33. package/Runtime/Core/InstanceId.cs.meta +11 -11
  34. package/Runtime/Core/MessageBus/IMessageBus.cs +309 -309
  35. package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
  36. package/Runtime/Core/MessageBus/MessageBus.cs +2243 -2084
  37. package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
  38. package/Runtime/Core/MessageBus/MessagingRegistration.cs +105 -105
  39. package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
  40. package/Runtime/Core/MessageBus/RegistrationLog.cs +111 -111
  41. package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
  42. package/Runtime/Core/MessageBus.meta +8 -8
  43. package/Runtime/Core/MessageHandler.cs +2778 -2759
  44. package/Runtime/Core/MessageHandler.cs.meta +11 -11
  45. package/Runtime/Core/MessageRegistrationHandle.cs +110 -110
  46. package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
  47. package/Runtime/Core/MessageRegistrationToken.cs +1234 -1234
  48. package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
  49. package/Runtime/Core/Messages/IBroadcastMessage.cs +27 -27
  50. package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
  51. package/Runtime/Core/Messages/ITargetedMessage.cs +27 -27
  52. package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
  53. package/Runtime/Core/Messages/IUntargetedMessage.cs +27 -27
  54. package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
  55. package/Runtime/Core/Messages.meta +8 -8
  56. package/Runtime/Core/MessagingDebug.cs +70 -70
  57. package/Runtime/Core/MessagingDebug.cs.meta +11 -11
  58. package/Runtime/Core.meta +8 -8
  59. package/Runtime/Unity/MessageAwareComponent.cs +77 -77
  60. package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
  61. package/Runtime/Unity/MessagingComponent.cs +99 -99
  62. package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
  63. package/Runtime/Unity.meta +8 -8
  64. package/Runtime/WallstopStudios.DxMessaging.asmdef +15 -15
  65. package/Runtime.meta +8 -8
  66. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs +92 -92
  67. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs.meta +11 -11
  68. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs +94 -94
  69. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs.meta +2 -2
  70. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs +94 -94
  71. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs.meta +2 -2
  72. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs +94 -94
  73. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs.meta +2 -2
  74. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +21 -21
  75. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
  76. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
  77. package/SourceGenerators.meta +8 -8
  78. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +373 -310
  79. package/Tests/Runtime/Benchmarks/PerformanceTests.cs.meta +11 -11
  80. package/Tests/Runtime/Benchmarks.meta +8 -8
  81. package/Tests/Runtime/Core/BroadcastTests.cs +899 -899
  82. package/Tests/Runtime/Core/GlobalAcceptAllTests.cs +190 -190
  83. package/Tests/Runtime/Core/GlobalAcceptAllTests.cs.meta +11 -11
  84. package/Tests/Runtime/Core/MessagingTestBase.cs +185 -185
  85. package/Tests/Runtime/Core/MessagingTestBase.cs.meta +11 -11
  86. package/Tests/Runtime/Core/NominalTests.cs +1740 -1740
  87. package/Tests/Runtime/Core/PostProcessorTests.cs +1236 -1236
  88. package/Tests/Runtime/Core/PostProcessorTests.cs.meta +11 -11
  89. package/Tests/Runtime/Core/RegistrationTests.cs +1266 -1266
  90. package/Tests/Runtime/Core/RegistrationTests.cs.meta +11 -11
  91. package/Tests/Runtime/Core/TargetedTests.cs +888 -888
  92. package/Tests/Runtime/Core/TargetedTests.cs.meta +11 -11
  93. package/Tests/Runtime/Core/UntargetedTests.cs +272 -272
  94. package/Tests/Runtime/Core/UntargetedTests.cs.meta +11 -11
  95. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +9 -9
  96. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs.meta +11 -11
  97. package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +186 -186
  98. package/Tests/Runtime/Scripts/Messages/ComplexTargetedMessage.cs +30 -30
  99. package/Tests/Runtime/Scripts/Messages/SimpleBroadcastMessage.cs +8 -8
  100. package/Tests/Runtime/Scripts/Messages/SimpleTargetedMessage.cs +8 -8
  101. package/Tests/Runtime/Scripts/Messages/SimpleUntargetedMessage.cs +8 -8
  102. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta +7 -7
  103. package/Tests.meta +8 -8
  104. package/Third Party Notices.md.meta +7 -7
  105. package/package.json +36 -36
  106. package/package.json.meta +7 -7
@@ -1,2084 +1,2243 @@
1
- namespace DxMessaging.Core.MessageBus
2
- {
3
- using System;
4
- using System.Collections.Generic;
5
- using System.Linq;
6
- using System.Reflection;
7
- using Messages;
8
- using static IMessageBus;
9
-
10
- /// <summary>
11
- /// Instanced MessageBus for use cases where you want distinct islands of MessageBuses.
12
- /// </summary>
13
- public sealed class MessageBus : IMessageBus
14
- {
15
- public int RegisteredTargeted => _targetedSinks.Select(kvp => kvp.Value.Count).Sum();
16
- public int RegisteredBroadcast => _broadcastSinks.Select(kvp => kvp.Value.Count).Sum();
17
- public int RegisteredUntargeted => _sinks.Select(kvp => kvp.Value.Count).Sum();
18
-
19
- private static readonly Type MessageBusType = typeof(MessageBus);
20
-
21
- // For use with re-broadcasting to generic methods
22
- private static readonly object[] ReflectionMethodArgumentsCache = new object[2];
23
-
24
- private const BindingFlags ReflectionHelperBindingFlags =
25
- BindingFlags.Static | BindingFlags.NonPublic;
26
-
27
- private delegate void FastUntargetedBroadcast<T>(ref T message)
28
- where T : IUntargetedMessage;
29
- private delegate void FastTargetedBroadcast<T>(ref InstanceId target, ref T message)
30
- where T : ITargetedMessage;
31
- private delegate void FastSourcedBroadcast<T>(ref InstanceId target, ref T message)
32
- where T : IBroadcastMessage;
33
-
34
- public RegistrationLog Log => _log;
35
-
36
- private readonly Dictionary<Type, SortedList<int, SortedList<MessageHandler, int>>> _sinks =
37
- new();
38
- private readonly Dictionary<
39
- Type,
40
- Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
41
- > _targetedSinks = new();
42
-
43
- private readonly Dictionary<
44
- Type,
45
- Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
46
- > _broadcastSinks = new();
47
- private readonly Dictionary<
48
- Type,
49
- SortedList<int, SortedList<MessageHandler, int>>
50
- > _postProcessingSinks = new();
51
- private readonly Dictionary<
52
- Type,
53
- Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
54
- > _postProcessingTargetedSinks = new();
55
- private readonly Dictionary<
56
- Type,
57
- Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
58
- > _postProcessingBroadcastSinks = new();
59
- private readonly Dictionary<
60
- Type,
61
- SortedList<int, SortedList<MessageHandler, int>>
62
- > _postProcessingTargetedWithoutTargetingSinks = new();
63
- private readonly Dictionary<
64
- Type,
65
- SortedList<int, SortedList<MessageHandler, int>>
66
- > _postProcessingBroadcastWithoutSourceSinks = new();
67
- private readonly SortedList<MessageHandler, int> _globalSinks = new();
68
- private readonly Dictionary<Type, SortedList<int, List<object>>> _interceptsByType = new();
69
- private readonly Dictionary<object, Dictionary<int, int>> _uniqueInterceptorsAndPriorities =
70
- new();
71
-
72
- private readonly Dictionary<Type, object> _broadcastMethodsByType = new();
73
-
74
- private readonly RegistrationLog _log = new();
75
-
76
- // These are used so we aren't allocating as much every time we send messages
77
- private readonly Stack<List<MessageHandler>> _messageHandlers = new();
78
- private readonly Stack<
79
- List<KeyValuePair<int, SortedList<MessageHandler, int>>>
80
- > _sortedHandlers = new();
81
- private readonly Stack<List<List<object>>> _interceptors = new();
82
- private readonly Stack<List<object>> _innerInterceptorsStack = new();
83
-
84
- public Action RegisterUntargeted<T>(MessageHandler messageHandler, int priority = 0)
85
- where T : IUntargetedMessage
86
- {
87
- return InternalRegisterUntargeted<T>(
88
- messageHandler,
89
- _sinks,
90
- RegistrationMethod.Untargeted,
91
- priority
92
- );
93
- }
94
-
95
- public Action RegisterTargeted<T>(
96
- InstanceId target,
97
- MessageHandler messageHandler,
98
- int priority = 0
99
- )
100
- where T : ITargetedMessage
101
- {
102
- return InternalRegisterWithContext<T>(
103
- target,
104
- messageHandler,
105
- _targetedSinks,
106
- RegistrationMethod.Targeted,
107
- priority
108
- );
109
- }
110
-
111
- public Action RegisterSourcedBroadcast<T>(
112
- InstanceId source,
113
- MessageHandler messageHandler,
114
- int priority = 0
115
- )
116
- where T : IBroadcastMessage
117
- {
118
- return InternalRegisterWithContext<T>(
119
- source,
120
- messageHandler,
121
- _broadcastSinks,
122
- RegistrationMethod.Broadcast,
123
- priority
124
- );
125
- }
126
-
127
- public Action RegisterSourcedBroadcastWithoutSource<T>(
128
- MessageHandler messageHandler,
129
- int priority = 0
130
- )
131
- where T : IBroadcastMessage
132
- {
133
- return InternalRegisterUntargeted<T>(
134
- messageHandler,
135
- _sinks,
136
- RegistrationMethod.BroadcastWithoutSource,
137
- priority
138
- );
139
- }
140
-
141
- public Action RegisterTargetedWithoutTargeting<T>(
142
- MessageHandler messageHandler,
143
- int priority = 0
144
- )
145
- where T : ITargetedMessage
146
- {
147
- return InternalRegisterUntargeted<T>(
148
- messageHandler,
149
- _sinks,
150
- RegistrationMethod.TargetedWithoutTargeting,
151
- priority
152
- );
153
- }
154
-
155
- public Action RegisterGlobalAcceptAll(MessageHandler messageHandler)
156
- {
157
- int count = _globalSinks.GetValueOrDefault(messageHandler, 0);
158
-
159
- Type type = typeof(IMessage);
160
- _globalSinks[messageHandler] = count + 1;
161
- _log.Log(
162
- new MessagingRegistration(
163
- messageHandler.owner,
164
- type,
165
- RegistrationType.Register,
166
- RegistrationMethod.GlobalAcceptAll
167
- )
168
- );
169
-
170
- return () =>
171
- {
172
- _log.Log(
173
- new MessagingRegistration(
174
- messageHandler.owner,
175
- type,
176
- RegistrationType.Deregister,
177
- RegistrationMethod.GlobalAcceptAll
178
- )
179
- );
180
- if (!_globalSinks.TryGetValue(messageHandler, out count))
181
- {
182
- MessagingDebug.Log(
183
- LogLevel.Error,
184
- "Received over-deregistration of GlobalAcceptAll for MessageHandler {0}. Check to make sure you're not calling (de)registration multiple times.",
185
- messageHandler
186
- );
187
- return;
188
- }
189
-
190
- if (count <= 1)
191
- {
192
- _ = _globalSinks.Remove(messageHandler);
193
- }
194
- else
195
- {
196
- _globalSinks[messageHandler] = count - 1;
197
- }
198
- };
199
- }
200
-
201
- public Action RegisterUntargetedInterceptor<T>(
202
- UntargetedInterceptor<T> interceptor,
203
- int priority = 0
204
- )
205
- where T : IUntargetedMessage
206
- {
207
- return RegisterInterceptor<T>(interceptor, priority);
208
- }
209
-
210
- public Action RegisterTargetedInterceptor<T>(
211
- TargetedInterceptor<T> interceptor,
212
- int priority = 0
213
- )
214
- where T : ITargetedMessage
215
- {
216
- return RegisterInterceptor<T>(interceptor, priority);
217
- }
218
-
219
- public Action RegisterBroadcastInterceptor<T>(
220
- BroadcastInterceptor<T> interceptor,
221
- int priority = 0
222
- )
223
- where T : IBroadcastMessage
224
- {
225
- return RegisterInterceptor<T>(interceptor, priority);
226
- }
227
-
228
- public Action RegisterUntargetedPostProcessor<T>(
229
- MessageHandler messageHandler,
230
- int priority = 0
231
- )
232
- where T : IUntargetedMessage
233
- {
234
- return InternalRegisterUntargeted<T>(
235
- messageHandler,
236
- _postProcessingSinks,
237
- RegistrationMethod.UntargetedPostProcessor,
238
- priority
239
- );
240
- }
241
-
242
- public Action RegisterTargetedPostProcessor<T>(
243
- InstanceId target,
244
- MessageHandler messageHandler,
245
- int priority = 0
246
- )
247
- where T : ITargetedMessage
248
- {
249
- return InternalRegisterWithContext<T>(
250
- target,
251
- messageHandler,
252
- _postProcessingTargetedSinks,
253
- RegistrationMethod.TargetedPostProcessor,
254
- priority
255
- );
256
- }
257
-
258
- public Action RegisterTargetedWithoutTargetingPostProcessor<T>(
259
- MessageHandler messageHandler,
260
- int priority = 0
261
- )
262
- where T : ITargetedMessage
263
- {
264
- return InternalRegisterUntargeted<T>(
265
- messageHandler,
266
- _postProcessingTargetedWithoutTargetingSinks,
267
- RegistrationMethod.TargetedWithoutTargetingPostProcessor,
268
- priority
269
- );
270
- }
271
-
272
- public Action RegisterBroadcastPostProcessor<T>(
273
- InstanceId source,
274
- MessageHandler messageHandler,
275
- int priority = 0
276
- )
277
- where T : IBroadcastMessage
278
- {
279
- return InternalRegisterWithContext<T>(
280
- source,
281
- messageHandler,
282
- _postProcessingBroadcastSinks,
283
- RegistrationMethod.BroadcastPostProcessor,
284
- priority
285
- );
286
- }
287
-
288
- public Action RegisterBroadcastWithoutSourcePostProcessor<T>(
289
- MessageHandler messageHandler,
290
- int priority = 0
291
- )
292
- where T : IBroadcastMessage
293
- {
294
- return InternalRegisterUntargeted<T>(
295
- messageHandler,
296
- _postProcessingBroadcastWithoutSourceSinks,
297
- RegistrationMethod.BroadcastWithoutSourcePostProcessor,
298
- priority
299
- );
300
- }
301
-
302
- private Action RegisterInterceptor<T>(object interceptor, int priority)
303
- where T : IMessage
304
- {
305
- Type type = typeof(T);
306
- if (
307
- !_interceptsByType.TryGetValue(
308
- type,
309
- out SortedList<int, List<object>> prioritizedInterceptors
310
- )
311
- )
312
- {
313
- prioritizedInterceptors = new SortedList<int, List<object>>();
314
- _interceptsByType[type] = prioritizedInterceptors;
315
- }
316
-
317
- if (!prioritizedInterceptors.TryGetValue(priority, out List<object> interceptors))
318
- {
319
- interceptors = new List<object>();
320
- prioritizedInterceptors[priority] = interceptors;
321
- }
322
-
323
- if (
324
- !_uniqueInterceptorsAndPriorities.TryGetValue(
325
- interceptor,
326
- out Dictionary<int, int> priorityCount
327
- )
328
- )
329
- {
330
- priorityCount = new Dictionary<int, int>();
331
- _uniqueInterceptorsAndPriorities[interceptor] = priorityCount;
332
- }
333
-
334
- if (!priorityCount.TryGetValue(priority, out int count))
335
- {
336
- count = 0;
337
- interceptors.Add(interceptor);
338
- }
339
-
340
- priorityCount[priority] = count + 1;
341
-
342
- _log.Log(
343
- new MessagingRegistration(
344
- InstanceId.EmptyId,
345
- type,
346
- RegistrationType.Register,
347
- RegistrationMethod.Interceptor
348
- )
349
- );
350
-
351
- return () =>
352
- {
353
- _log.Log(
354
- new MessagingRegistration(
355
- InstanceId.EmptyId,
356
- type,
357
- RegistrationType.Deregister,
358
- RegistrationMethod.Interceptor
359
- )
360
- );
361
- bool removed = false;
362
- if (_uniqueInterceptorsAndPriorities.TryGetValue(interceptor, out priorityCount))
363
- {
364
- if (priorityCount.TryGetValue(priority, out count))
365
- {
366
- if (1 < count)
367
- {
368
- priorityCount[priority] = count - 1;
369
- }
370
- else
371
- {
372
- removed = true;
373
- _ = priorityCount.Remove(priority);
374
- }
375
- }
376
-
377
- if (priorityCount.Count <= 0)
378
- {
379
- _uniqueInterceptorsAndPriorities.Remove(interceptor);
380
- }
381
- }
382
- else
383
- {
384
- MessagingDebug.Log(
385
- LogLevel.Error,
386
- "Received over-deregistration of Interceptor {0}. Check to make sure you're not calling (de)registration multiple times.",
387
- interceptor
388
- );
389
- }
390
-
391
- bool complete = false;
392
- if (removed)
393
- {
394
- if (
395
- _interceptsByType.TryGetValue(type, out prioritizedInterceptors)
396
- && prioritizedInterceptors.TryGetValue(priority, out interceptors)
397
- )
398
- {
399
- complete = interceptors.Remove(interceptor);
400
- }
401
-
402
- if (!complete)
403
- {
404
- MessagingDebug.Log(
405
- LogLevel.Error,
406
- "Received over-deregistration of Interceptor {0}. Check to make sure you're not calling (de)registration multiple times.",
407
- interceptor
408
- );
409
- }
410
- }
411
- };
412
- }
413
-
414
- public void UntypedUntargetedBroadcast(IUntargetedMessage typedMessage)
415
- {
416
- Type messageType = typedMessage.MessageType;
417
- if (!_broadcastMethodsByType.TryGetValue(messageType, out object untargetedMethod))
418
- {
419
- // ReSharper disable once PossibleNullReferenceException
420
- MethodInfo broadcastMethod = MessageBusType
421
- .GetMethod(nameof(UntargetedBroadcast))
422
- .MakeGenericMethod(messageType);
423
- // ReSharper disable once PossibleNullReferenceException
424
- MethodInfo helperMethod = MessageBusType
425
- .GetMethod(
426
- nameof(UntargetedBroadcastReflectionHelper),
427
- ReflectionHelperBindingFlags
428
- )
429
- .MakeGenericMethod(messageType);
430
-
431
- ReflectionMethodArgumentsCache[0] = this;
432
- ReflectionMethodArgumentsCache[1] = broadcastMethod;
433
- untargetedMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
434
- _broadcastMethodsByType[messageType] = untargetedMethod;
435
- }
436
-
437
- Action<IUntargetedMessage> broadcast = (Action<IUntargetedMessage>)untargetedMethod;
438
- broadcast.Invoke(typedMessage);
439
- }
440
-
441
- public void UntargetedBroadcast<TMessage>(ref TMessage typedMessage)
442
- where TMessage : IUntargetedMessage
443
- {
444
- Type type = typeof(TMessage);
445
- if (!RunUntargetedInterceptors(type, ref typedMessage))
446
- {
447
- return;
448
- }
449
-
450
- if (0 < _globalSinks.Count)
451
- {
452
- IUntargetedMessage untargetedMessage = typedMessage;
453
- BroadcastGlobalUntargeted(ref untargetedMessage);
454
- }
455
-
456
- bool foundAnyHandlers = InternalUntargetedBroadcast(ref typedMessage, type);
457
-
458
- if (
459
- _postProcessingSinks.TryGetValue(
460
- type,
461
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
462
- )
463
- && 0 < sortedHandlers.Count
464
- )
465
- {
466
- foundAnyHandlers = true;
467
- if (sortedHandlers.Count == 1)
468
- {
469
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
470
- sortedHandlers.First();
471
- RunUntargetedPostProcessing(ref typedMessage, entry.Key, entry.Value);
472
- }
473
- else
474
- {
475
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
476
- GetOrAddMessageHandlerStack(sortedHandlers);
477
- try
478
- {
479
- foreach (
480
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
481
- )
482
- {
483
- RunUntargetedPostProcessing(ref typedMessage, entry.Key, entry.Value);
484
- }
485
- }
486
- finally
487
- {
488
- _sortedHandlers.Push(handlerList);
489
- }
490
- }
491
- }
492
-
493
- if (!foundAnyHandlers)
494
- {
495
- MessagingDebug.Log(
496
- LogLevel.Info,
497
- "Could not find a matching untargeted broadcast handler for Message: {0}.",
498
- typedMessage
499
- );
500
- }
501
- }
502
-
503
- private void RunUntargetedPostProcessing<TMessage>(
504
- ref TMessage typedMessage,
505
- int priority,
506
- SortedList<MessageHandler, int> handlers
507
- )
508
- where TMessage : IUntargetedMessage
509
- {
510
- switch (handlers.Count)
511
- {
512
- case <= 0:
513
- {
514
- return;
515
- }
516
- case 1:
517
- {
518
- MessageHandler handler = handlers.Keys.First();
519
- handler.HandleUntargetedPostProcessing(ref typedMessage, this, priority);
520
- return;
521
- }
522
- default:
523
- {
524
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
525
- handlers.Keys
526
- );
527
- try
528
- {
529
- foreach (MessageHandler handler in messageHandlers)
530
- {
531
- handler.HandleUntargetedPostProcessing(
532
- ref typedMessage,
533
- this,
534
- priority
535
- );
536
- }
537
- }
538
- finally
539
- {
540
- _messageHandlers.Push(messageHandlers);
541
- }
542
-
543
- break;
544
- }
545
- }
546
- }
547
-
548
- public void UntypedTargetedBroadcast(InstanceId target, ITargetedMessage typedMessage)
549
- {
550
- Type messageType = typedMessage.MessageType;
551
- if (!_broadcastMethodsByType.TryGetValue(messageType, out object targetedMethod))
552
- {
553
- // ReSharper disable once PossibleNullReferenceException
554
- MethodInfo broadcastMethod = MessageBusType
555
- .GetMethod(nameof(TargetedBroadcast))
556
- .MakeGenericMethod(messageType);
557
- // ReSharper disable once PossibleNullReferenceException
558
- MethodInfo helperMethod = MessageBusType
559
- .GetMethod(
560
- nameof(TargetedBroadcastReflectionHelper),
561
- ReflectionHelperBindingFlags
562
- )
563
- .MakeGenericMethod(messageType);
564
-
565
- ReflectionMethodArgumentsCache[0] = this;
566
- ReflectionMethodArgumentsCache[1] = broadcastMethod;
567
- targetedMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
568
- _broadcastMethodsByType[messageType] = targetedMethod;
569
- }
570
-
571
- Action<InstanceId, ITargetedMessage> broadcast =
572
- (Action<InstanceId, ITargetedMessage>)targetedMethod;
573
- broadcast.Invoke(target, typedMessage);
574
- }
575
-
576
- public void TargetedBroadcast<TMessage>(ref InstanceId target, ref TMessage typedMessage)
577
- where TMessage : ITargetedMessage
578
- {
579
- Type type = typeof(TMessage);
580
- if (!RunTargetedInterceptors(type, ref typedMessage, ref target))
581
- {
582
- return;
583
- }
584
-
585
- if (0 < _globalSinks.Count)
586
- {
587
- ITargetedMessage targetedMessage = typedMessage;
588
- BroadcastGlobalTargeted(ref target, ref targetedMessage);
589
- }
590
-
591
- bool foundAnyHandlers = false;
592
- if (
593
- _targetedSinks.TryGetValue(
594
- type,
595
- out Dictionary<
596
- InstanceId,
597
- SortedList<int, SortedList<MessageHandler, int>>
598
- > targetedHandlers
599
- )
600
- && targetedHandlers.TryGetValue(
601
- target,
602
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
603
- )
604
- && 0 < sortedHandlers.Count
605
- )
606
- {
607
- foundAnyHandlers = true;
608
- if (sortedHandlers.Count == 1)
609
- {
610
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
611
- sortedHandlers.First();
612
- RunTargetedBroadcast(ref target, ref typedMessage, entry.Key, entry.Value);
613
- }
614
- else
615
- {
616
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
617
- GetOrAddMessageHandlerStack(sortedHandlers);
618
- try
619
- {
620
- foreach (
621
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
622
- )
623
- {
624
- RunTargetedBroadcast(
625
- ref target,
626
- ref typedMessage,
627
- entry.Key,
628
- entry.Value
629
- );
630
- }
631
- }
632
- finally
633
- {
634
- _sortedHandlers.Push(handlerList);
635
- }
636
- }
637
- }
638
-
639
- _ = InternalTargetedWithoutTargetingBroadcast(ref target, ref typedMessage, type);
640
-
641
- if (
642
- _postProcessingTargetedSinks.TryGetValue(type, out targetedHandlers)
643
- && targetedHandlers.TryGetValue(target, out sortedHandlers)
644
- && 0 < sortedHandlers.Count
645
- )
646
- {
647
- foundAnyHandlers = true;
648
- if (sortedHandlers.Count == 1)
649
- {
650
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
651
- sortedHandlers.First();
652
- RunTargetedPostProcessing(ref target, ref typedMessage, entry.Key, entry.Value);
653
- }
654
- else
655
- {
656
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
657
- GetOrAddMessageHandlerStack(sortedHandlers);
658
- try
659
- {
660
- foreach (
661
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
662
- )
663
- {
664
- RunTargetedPostProcessing(
665
- ref target,
666
- ref typedMessage,
667
- entry.Key,
668
- entry.Value
669
- );
670
- }
671
- }
672
- finally
673
- {
674
- _sortedHandlers.Push(handlerList);
675
- }
676
- }
677
- }
678
-
679
- if (
680
- _postProcessingTargetedWithoutTargetingSinks.TryGetValue(type, out sortedHandlers)
681
- && 0 < sortedHandlers.Count
682
- )
683
- {
684
- if (sortedHandlers.Count == 1)
685
- {
686
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
687
- sortedHandlers.First();
688
- RunTargetedWithoutTargetingPostProcessing(
689
- ref target,
690
- ref typedMessage,
691
- entry.Key,
692
- entry.Value
693
- );
694
- }
695
- else
696
- {
697
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
698
- GetOrAddMessageHandlerStack(sortedHandlers);
699
- try
700
- {
701
- foreach (
702
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
703
- )
704
- {
705
- RunTargetedWithoutTargetingPostProcessing(
706
- ref target,
707
- ref typedMessage,
708
- entry.Key,
709
- entry.Value
710
- );
711
- }
712
- }
713
- finally
714
- {
715
- _sortedHandlers.Push(handlerList);
716
- }
717
- }
718
- }
719
-
720
- if (!foundAnyHandlers)
721
- {
722
- MessagingDebug.Log(
723
- LogLevel.Info,
724
- "Could not find a matching targeted broadcast handler for Id: {0}, Message: {1}.",
725
- target,
726
- typedMessage
727
- );
728
- }
729
- }
730
-
731
- private void RunTargetedWithoutTargetingPostProcessing<TMessage>(
732
- ref InstanceId target,
733
- ref TMessage typedMessage,
734
- int priority,
735
- SortedList<MessageHandler, int> handlers
736
- )
737
- where TMessage : ITargetedMessage
738
- {
739
- switch (handlers.Count)
740
- {
741
- case <= 0:
742
- {
743
- return;
744
- }
745
- case 1:
746
- {
747
- MessageHandler handler = handlers.Keys.First();
748
- handler.HandleTargetedWithoutTargetingPostProcessing(
749
- ref target,
750
- ref typedMessage,
751
- this,
752
- priority
753
- );
754
- return;
755
- }
756
- default:
757
- {
758
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
759
- handlers.Keys
760
- );
761
- try
762
- {
763
- foreach (MessageHandler handler in messageHandlers)
764
- {
765
- handler.HandleTargetedWithoutTargetingPostProcessing(
766
- ref target,
767
- ref typedMessage,
768
- this,
769
- priority
770
- );
771
- }
772
- }
773
- finally
774
- {
775
- _messageHandlers.Push(messageHandlers);
776
- }
777
-
778
- break;
779
- }
780
- }
781
- }
782
-
783
- private void RunTargetedPostProcessing<TMessage>(
784
- ref InstanceId target,
785
- ref TMessage typedMessage,
786
- int priority,
787
- SortedList<MessageHandler, int> handlers
788
- )
789
- where TMessage : ITargetedMessage
790
- {
791
- switch (handlers.Count)
792
- {
793
- case <= 0:
794
- {
795
- return;
796
- }
797
- case 1:
798
- {
799
- MessageHandler handler = handlers.Keys.First();
800
- handler.HandleTargetedPostProcessing(
801
- ref target,
802
- ref typedMessage,
803
- this,
804
- priority
805
- );
806
- return;
807
- }
808
- default:
809
- {
810
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
811
- handlers.Keys
812
- );
813
- try
814
- {
815
- foreach (MessageHandler handler in messageHandlers)
816
- {
817
- handler.HandleTargetedPostProcessing(
818
- ref target,
819
- ref typedMessage,
820
- this,
821
- priority
822
- );
823
- }
824
- }
825
- finally
826
- {
827
- _messageHandlers.Push(messageHandlers);
828
- }
829
-
830
- break;
831
- }
832
- }
833
- }
834
-
835
- private void RunTargetedBroadcast<TMessage>(
836
- ref InstanceId target,
837
- ref TMessage typedMessage,
838
- int priority,
839
- SortedList<MessageHandler, int> handlers
840
- )
841
- where TMessage : ITargetedMessage
842
- {
843
- switch (handlers.Count)
844
- {
845
- case <= 0:
846
- {
847
- return;
848
- }
849
- case 1:
850
- {
851
- MessageHandler handler = handlers.Keys.First();
852
- handler.HandleTargeted(ref target, ref typedMessage, this, priority);
853
- return;
854
- }
855
- default:
856
- {
857
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
858
- handlers.Keys
859
- );
860
- try
861
- {
862
- foreach (MessageHandler handler in messageHandlers)
863
- {
864
- handler.HandleTargeted(ref target, ref typedMessage, this, priority);
865
- }
866
- }
867
- finally
868
- {
869
- _messageHandlers.Push(messageHandlers);
870
- }
871
-
872
- break;
873
- }
874
- }
875
- }
876
-
877
- public void UntypedSourcedBroadcast(InstanceId source, IBroadcastMessage typedMessage)
878
- {
879
- Type messageType = typedMessage.MessageType;
880
- if (
881
- !_broadcastMethodsByType.TryGetValue(messageType, out object sourcedBroadcastMethod)
882
- )
883
- {
884
- // ReSharper disable once PossibleNullReferenceException
885
- MethodInfo broadcastMethod = MessageBusType
886
- .GetMethod(nameof(SourcedBroadcast))
887
- .MakeGenericMethod(messageType);
888
- // ReSharper disable once PossibleNullReferenceException
889
- MethodInfo helperMethod = MessageBusType
890
- .GetMethod(
891
- nameof(SourcedBroadcastReflectionHelper),
892
- ReflectionHelperBindingFlags
893
- )
894
- .MakeGenericMethod(messageType);
895
-
896
- ReflectionMethodArgumentsCache[0] = this;
897
- ReflectionMethodArgumentsCache[1] = broadcastMethod;
898
- sourcedBroadcastMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
899
-
900
- _broadcastMethodsByType[messageType] = sourcedBroadcastMethod;
901
- }
902
-
903
- Action<InstanceId, IBroadcastMessage> broadcast =
904
- (Action<InstanceId, IBroadcastMessage>)sourcedBroadcastMethod;
905
- broadcast.Invoke(source, typedMessage);
906
- }
907
-
908
- public void SourcedBroadcast<TMessage>(ref InstanceId source, ref TMessage typedMessage)
909
- where TMessage : IBroadcastMessage
910
- {
911
- Type type = typeof(TMessage);
912
- if (!RunBroadcastInterceptors(type, ref typedMessage, ref source))
913
- {
914
- return;
915
- }
916
-
917
- if (0 < _globalSinks.Count)
918
- {
919
- IBroadcastMessage broadcastMessage = typedMessage;
920
- BroadcastGlobalSourcedBroadcast(ref source, ref broadcastMessage);
921
- }
922
-
923
- bool foundAnyHandlers = false;
924
- if (
925
- _broadcastSinks.TryGetValue(
926
- type,
927
- out Dictionary<
928
- InstanceId,
929
- SortedList<int, SortedList<MessageHandler, int>>
930
- > broadcastHandlers
931
- )
932
- && broadcastHandlers.TryGetValue(
933
- source,
934
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
935
- )
936
- && 0 < sortedHandlers.Count
937
- )
938
- {
939
- foundAnyHandlers = true;
940
- if (sortedHandlers.Count == 1)
941
- {
942
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
943
- sortedHandlers.First();
944
- RunBroadcast(ref source, ref typedMessage, entry.Key, entry.Value);
945
- }
946
- else
947
- {
948
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
949
- GetOrAddMessageHandlerStack(sortedHandlers);
950
- try
951
- {
952
- foreach (
953
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
954
- )
955
- {
956
- RunBroadcast(ref source, ref typedMessage, entry.Key, entry.Value);
957
- }
958
- }
959
- finally
960
- {
961
- _sortedHandlers.Push(handlerList);
962
- }
963
- }
964
- }
965
-
966
- _ = InternalBroadcastWithoutSource(ref source, ref typedMessage, type);
967
-
968
- if (
969
- _postProcessingBroadcastSinks.TryGetValue(type, out broadcastHandlers)
970
- && broadcastHandlers.TryGetValue(source, out sortedHandlers)
971
- && 0 < sortedHandlers.Count
972
- )
973
- {
974
- foundAnyHandlers = true;
975
- if (sortedHandlers.Count == 1)
976
- {
977
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
978
- sortedHandlers.First();
979
- RunBroadcastPostProcessing(
980
- ref source,
981
- ref typedMessage,
982
- entry.Key,
983
- entry.Value
984
- );
985
- }
986
- else
987
- {
988
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
989
- GetOrAddMessageHandlerStack(sortedHandlers);
990
- try
991
- {
992
- foreach (
993
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
994
- )
995
- {
996
- RunBroadcastPostProcessing(
997
- ref source,
998
- ref typedMessage,
999
- entry.Key,
1000
- entry.Value
1001
- );
1002
- }
1003
- }
1004
- finally
1005
- {
1006
- _sortedHandlers.Push(handlerList);
1007
- }
1008
- }
1009
- }
1010
-
1011
- if (
1012
- _postProcessingBroadcastWithoutSourceSinks.TryGetValue(type, out sortedHandlers)
1013
- && 0 < sortedHandlers.Count
1014
- )
1015
- {
1016
- if (sortedHandlers.Count == 1)
1017
- {
1018
- KeyValuePair<int, SortedList<MessageHandler, int>> entry =
1019
- sortedHandlers.First();
1020
- RunBroadcastWithoutSourcePostProcessing(
1021
- ref source,
1022
- ref typedMessage,
1023
- entry.Key,
1024
- entry.Value
1025
- );
1026
- }
1027
- else
1028
- {
1029
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1030
- GetOrAddMessageHandlerStack(sortedHandlers);
1031
- try
1032
- {
1033
- foreach (
1034
- KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
1035
- )
1036
- {
1037
- RunBroadcastWithoutSourcePostProcessing(
1038
- ref source,
1039
- ref typedMessage,
1040
- entry.Key,
1041
- entry.Value
1042
- );
1043
- }
1044
- }
1045
- finally
1046
- {
1047
- _sortedHandlers.Push(handlerList);
1048
- }
1049
- }
1050
- }
1051
-
1052
- if (!foundAnyHandlers)
1053
- {
1054
- MessagingDebug.Log(
1055
- LogLevel.Info,
1056
- "Could not find a matching sourced broadcast handler for Id: {0}, Message: {1}.",
1057
- source,
1058
- typedMessage
1059
- );
1060
- }
1061
- }
1062
-
1063
- private void RunBroadcastWithoutSourcePostProcessing<TMessage>(
1064
- ref InstanceId source,
1065
- ref TMessage typedMessage,
1066
- int priority,
1067
- SortedList<MessageHandler, int> handlers
1068
- )
1069
- where TMessage : IBroadcastMessage
1070
- {
1071
- switch (handlers.Count)
1072
- {
1073
- case <= 0:
1074
- {
1075
- return;
1076
- }
1077
- case 1:
1078
- {
1079
- MessageHandler handler = handlers.Keys.First();
1080
- handler.HandleSourcedBroadcastWithoutSourcePostProcessing(
1081
- ref source,
1082
- ref typedMessage,
1083
- this,
1084
- priority
1085
- );
1086
- return;
1087
- }
1088
- default:
1089
- {
1090
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1091
- handlers.Keys
1092
- );
1093
- try
1094
- {
1095
- foreach (MessageHandler handler in messageHandlers)
1096
- {
1097
- handler.HandleSourcedBroadcastWithoutSourcePostProcessing(
1098
- ref source,
1099
- ref typedMessage,
1100
- this,
1101
- priority
1102
- );
1103
- }
1104
- }
1105
- finally
1106
- {
1107
- _messageHandlers.Push(messageHandlers);
1108
- }
1109
-
1110
- break;
1111
- }
1112
- }
1113
- }
1114
-
1115
- private void RunBroadcastPostProcessing<TMessage>(
1116
- ref InstanceId source,
1117
- ref TMessage typedMessage,
1118
- int priority,
1119
- SortedList<MessageHandler, int> handlers
1120
- )
1121
- where TMessage : IBroadcastMessage
1122
- {
1123
- switch (handlers.Count)
1124
- {
1125
- case <= 0:
1126
- {
1127
- return;
1128
- }
1129
- case 1:
1130
- {
1131
- MessageHandler handler = handlers.Keys.First();
1132
- handler.HandleSourcedBroadcastPostProcessing(
1133
- ref source,
1134
- ref typedMessage,
1135
- this,
1136
- priority
1137
- );
1138
- return;
1139
- }
1140
- default:
1141
- {
1142
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1143
- handlers.Keys
1144
- );
1145
- try
1146
- {
1147
- foreach (MessageHandler handler in messageHandlers)
1148
- {
1149
- handler.HandleSourcedBroadcastPostProcessing(
1150
- ref source,
1151
- ref typedMessage,
1152
- this,
1153
- priority
1154
- );
1155
- }
1156
- }
1157
- finally
1158
- {
1159
- _messageHandlers.Push(messageHandlers);
1160
- }
1161
-
1162
- break;
1163
- }
1164
- }
1165
- }
1166
-
1167
- private void RunBroadcast<TMessage>(
1168
- ref InstanceId source,
1169
- ref TMessage typedMessage,
1170
- int priority,
1171
- SortedList<MessageHandler, int> handlers
1172
- )
1173
- where TMessage : IBroadcastMessage
1174
- {
1175
- switch (handlers.Count)
1176
- {
1177
- case <= 0:
1178
- {
1179
- return;
1180
- }
1181
- case 1:
1182
- {
1183
- MessageHandler handler = handlers.Keys.First();
1184
- handler.HandleSourcedBroadcast(ref source, ref typedMessage, this, priority);
1185
- return;
1186
- }
1187
- default:
1188
- {
1189
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1190
- handlers.Keys
1191
- );
1192
- try
1193
- {
1194
- foreach (MessageHandler handler in messageHandlers)
1195
- {
1196
- handler.HandleSourcedBroadcast(
1197
- ref source,
1198
- ref typedMessage,
1199
- this,
1200
- priority
1201
- );
1202
- }
1203
- }
1204
- finally
1205
- {
1206
- _messageHandlers.Push(messageHandlers);
1207
- }
1208
-
1209
- break;
1210
- }
1211
- }
1212
- }
1213
-
1214
- private void BroadcastGlobalUntargeted(ref IUntargetedMessage message)
1215
- {
1216
- switch (_globalSinks.Count)
1217
- {
1218
- case <= 0:
1219
- {
1220
- return;
1221
- }
1222
- case 1:
1223
- {
1224
- MessageHandler handler = _globalSinks.Keys.First();
1225
- handler.HandleGlobalUntargetedMessage(ref message, this);
1226
- return;
1227
- }
1228
- default:
1229
- {
1230
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1231
- _globalSinks.Keys
1232
- );
1233
- try
1234
- {
1235
- foreach (MessageHandler handler in messageHandlers)
1236
- {
1237
- handler.HandleGlobalUntargetedMessage(ref message, this);
1238
- }
1239
- }
1240
- finally
1241
- {
1242
- _messageHandlers.Push(messageHandlers);
1243
- }
1244
-
1245
- break;
1246
- }
1247
- }
1248
- }
1249
-
1250
- private void BroadcastGlobalTargeted(ref InstanceId target, ref ITargetedMessage message)
1251
- {
1252
- switch (_globalSinks.Count)
1253
- {
1254
- case <= 0:
1255
- {
1256
- return;
1257
- }
1258
- case 1:
1259
- {
1260
- MessageHandler handler = _globalSinks.Keys.First();
1261
- handler.HandleGlobalTargetedMessage(ref target, ref message, this);
1262
- return;
1263
- }
1264
- default:
1265
- {
1266
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1267
- _globalSinks.Keys
1268
- );
1269
- try
1270
- {
1271
- foreach (MessageHandler handler in messageHandlers)
1272
- {
1273
- handler.HandleGlobalTargetedMessage(ref target, ref message, this);
1274
- }
1275
- }
1276
- finally
1277
- {
1278
- _messageHandlers.Push(messageHandlers);
1279
- }
1280
-
1281
- break;
1282
- }
1283
- }
1284
- }
1285
-
1286
- private void BroadcastGlobalSourcedBroadcast(
1287
- ref InstanceId source,
1288
- ref IBroadcastMessage message
1289
- )
1290
- {
1291
- switch (_globalSinks.Count)
1292
- {
1293
- case <= 0:
1294
- {
1295
- return;
1296
- }
1297
- case 1:
1298
- {
1299
- MessageHandler handler = _globalSinks.Keys.First();
1300
- handler.HandleGlobalSourcedBroadcastMessage(ref source, ref message, this);
1301
- return;
1302
- }
1303
- default:
1304
- {
1305
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1306
- _globalSinks.Keys
1307
- );
1308
- try
1309
- {
1310
- foreach (MessageHandler handler in messageHandlers)
1311
- {
1312
- handler.HandleGlobalSourcedBroadcastMessage(
1313
- ref source,
1314
- ref message,
1315
- this
1316
- );
1317
- }
1318
- }
1319
- finally
1320
- {
1321
- _messageHandlers.Push(messageHandlers);
1322
- }
1323
-
1324
- break;
1325
- }
1326
- }
1327
- }
1328
-
1329
- private bool TryGetInterceptorCaches(
1330
- Type type,
1331
- out List<List<object>> interceptorStack,
1332
- out List<object> interceptorObjects
1333
- )
1334
- {
1335
- if (
1336
- !_interceptsByType.TryGetValue(type, out SortedList<int, List<object>> interceptors)
1337
- || interceptors.Count <= 0
1338
- )
1339
- {
1340
- interceptorStack = default;
1341
- interceptorObjects = default;
1342
- return false;
1343
- }
1344
-
1345
- if (!_interceptors.TryPop(out interceptorStack))
1346
- {
1347
- interceptorStack = new List<List<object>>(interceptors.Values);
1348
- }
1349
- else
1350
- {
1351
- interceptorStack.Clear();
1352
- interceptorStack.AddRange(interceptors.Values);
1353
- }
1354
-
1355
- if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
1356
- {
1357
- interceptorObjects = new List<object>();
1358
- }
1359
-
1360
- return true;
1361
- }
1362
-
1363
- private bool RunUntargetedInterceptors<T>(Type type, ref T message)
1364
- where T : IUntargetedMessage
1365
- {
1366
- if (
1367
- !TryGetInterceptorCaches(
1368
- type,
1369
- out List<List<object>> interceptorStack,
1370
- out List<object> interceptorObjects
1371
- )
1372
- )
1373
- {
1374
- return true;
1375
- }
1376
-
1377
- try
1378
- {
1379
- foreach (List<object> stack in interceptorStack)
1380
- {
1381
- interceptorObjects.Clear();
1382
- interceptorObjects.AddRange(stack);
1383
-
1384
- foreach (object transformer in interceptorObjects)
1385
- {
1386
- if (transformer is not UntargetedInterceptor<T> typedTransformer)
1387
- {
1388
- continue;
1389
- }
1390
-
1391
- if (!typedTransformer(ref message))
1392
- {
1393
- return false;
1394
- }
1395
- }
1396
- }
1397
- }
1398
- finally
1399
- {
1400
- _interceptors.Push(interceptorStack);
1401
- _innerInterceptorsStack.Push(interceptorObjects);
1402
- }
1403
-
1404
- return true;
1405
- }
1406
-
1407
- private bool RunTargetedInterceptors<T>(Type type, ref T message, ref InstanceId target)
1408
- where T : ITargetedMessage
1409
- {
1410
- if (
1411
- !TryGetInterceptorCaches(
1412
- type,
1413
- out List<List<object>> interceptorStack,
1414
- out List<object> interceptorObjects
1415
- )
1416
- )
1417
- {
1418
- return true;
1419
- }
1420
-
1421
- try
1422
- {
1423
- foreach (List<object> stack in interceptorStack)
1424
- {
1425
- interceptorObjects.Clear();
1426
- interceptorObjects.AddRange(stack);
1427
-
1428
- foreach (object transformer in interceptorObjects)
1429
- {
1430
- if (transformer is not TargetedInterceptor<T> typedTransformer)
1431
- {
1432
- continue;
1433
- }
1434
-
1435
- if (!typedTransformer(ref target, ref message))
1436
- {
1437
- return false;
1438
- }
1439
- }
1440
- }
1441
- }
1442
- finally
1443
- {
1444
- _interceptors.Push(interceptorStack);
1445
- _innerInterceptorsStack.Push(interceptorObjects);
1446
- }
1447
-
1448
- return true;
1449
- }
1450
-
1451
- private bool RunBroadcastInterceptors<T>(Type type, ref T message, ref InstanceId source)
1452
- where T : IBroadcastMessage
1453
- {
1454
- if (
1455
- !TryGetInterceptorCaches(
1456
- type,
1457
- out List<List<object>> interceptorStack,
1458
- out List<object> interceptorObjects
1459
- )
1460
- )
1461
- {
1462
- return true;
1463
- }
1464
-
1465
- try
1466
- {
1467
- foreach (List<object> stack in interceptorStack)
1468
- {
1469
- interceptorObjects.Clear();
1470
- interceptorObjects.AddRange(stack);
1471
-
1472
- foreach (object transformer in interceptorObjects)
1473
- {
1474
- if (transformer is not BroadcastInterceptor<T> typedTransformer)
1475
- {
1476
- continue;
1477
- }
1478
-
1479
- if (!typedTransformer(ref source, ref message))
1480
- {
1481
- return false;
1482
- }
1483
- }
1484
- }
1485
- }
1486
- finally
1487
- {
1488
- _interceptors.Push(interceptorStack);
1489
- _innerInterceptorsStack.Push(interceptorObjects);
1490
- }
1491
-
1492
- return true;
1493
- }
1494
-
1495
- private bool InternalUntargetedBroadcast<TMessage>(ref TMessage message, Type type)
1496
- where TMessage : IMessage
1497
- {
1498
- if (
1499
- !_sinks.TryGetValue(
1500
- type,
1501
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1502
- )
1503
- || sortedHandlers.Count <= 0
1504
- )
1505
- {
1506
- return false;
1507
- }
1508
-
1509
- if (sortedHandlers.Count == 1)
1510
- {
1511
- KeyValuePair<int, SortedList<MessageHandler, int>> entry = sortedHandlers.First();
1512
- RunUntargetedBroadcast(ref message, entry.Key, entry.Value);
1513
- return true;
1514
- }
1515
-
1516
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1517
- GetOrAddMessageHandlerStack(sortedHandlers);
1518
- try
1519
- {
1520
- foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1521
- {
1522
- RunUntargetedBroadcast(ref message, entry.Key, entry.Value);
1523
- }
1524
- }
1525
- finally
1526
- {
1527
- _sortedHandlers.Push(handlerList);
1528
- }
1529
-
1530
- return true;
1531
- }
1532
-
1533
- private void RunUntargetedBroadcast<TMessage>(
1534
- ref TMessage message,
1535
- int priority,
1536
- SortedList<MessageHandler, int> handlers
1537
- )
1538
- where TMessage : IMessage
1539
- {
1540
- switch (handlers.Count)
1541
- {
1542
- case <= 0:
1543
- {
1544
- return;
1545
- }
1546
- case 1:
1547
- {
1548
- MessageHandler handler = handlers.Keys.First();
1549
- handler.HandleUntargetedMessage(ref message, this, priority);
1550
- return;
1551
- }
1552
- default:
1553
- {
1554
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1555
- handlers.Keys
1556
- );
1557
- try
1558
- {
1559
- foreach (MessageHandler handler in messageHandlers)
1560
- {
1561
- handler.HandleUntargetedMessage(ref message, this, priority);
1562
- }
1563
- }
1564
- finally
1565
- {
1566
- _messageHandlers.Push(messageHandlers);
1567
- }
1568
-
1569
- break;
1570
- }
1571
- }
1572
- }
1573
-
1574
- private bool InternalTargetedWithoutTargetingBroadcast<TMessage>(
1575
- ref InstanceId target,
1576
- ref TMessage message,
1577
- Type type
1578
- )
1579
- where TMessage : ITargetedMessage
1580
- {
1581
- if (
1582
- !_sinks.TryGetValue(
1583
- type,
1584
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1585
- )
1586
- || sortedHandlers.Count <= 0
1587
- )
1588
- {
1589
- return false;
1590
- }
1591
-
1592
- if (sortedHandlers.Count == 1)
1593
- {
1594
- KeyValuePair<int, SortedList<MessageHandler, int>> entry = sortedHandlers.First();
1595
- RunTargetedWithoutTargeting(ref target, ref message, entry.Key, entry.Value);
1596
- return true;
1597
- }
1598
-
1599
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1600
- GetOrAddMessageHandlerStack(sortedHandlers);
1601
- try
1602
- {
1603
- foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1604
- {
1605
- RunTargetedWithoutTargeting(ref target, ref message, entry.Key, entry.Value);
1606
- }
1607
- }
1608
- finally
1609
- {
1610
- _sortedHandlers.Push(handlerList);
1611
- }
1612
-
1613
- return true;
1614
- }
1615
-
1616
- private void RunTargetedWithoutTargeting<TMessage>(
1617
- ref InstanceId target,
1618
- ref TMessage message,
1619
- int priority,
1620
- SortedList<MessageHandler, int> handlers
1621
- )
1622
- where TMessage : ITargetedMessage
1623
- {
1624
- switch (handlers.Count)
1625
- {
1626
- case <= 0:
1627
- {
1628
- return;
1629
- }
1630
- case 1:
1631
- {
1632
- MessageHandler handler = handlers.Keys.First();
1633
- handler.HandleTargetedWithoutTargeting(ref target, ref message, this, priority);
1634
- return;
1635
- }
1636
- default:
1637
- {
1638
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1639
- handlers.Keys
1640
- );
1641
- try
1642
- {
1643
- foreach (MessageHandler handler in messageHandlers)
1644
- {
1645
- handler.HandleTargetedWithoutTargeting(
1646
- ref target,
1647
- ref message,
1648
- this,
1649
- priority
1650
- );
1651
- }
1652
- }
1653
- finally
1654
- {
1655
- _messageHandlers.Push(messageHandlers);
1656
- }
1657
-
1658
- break;
1659
- }
1660
- }
1661
- }
1662
-
1663
- private bool InternalBroadcastWithoutSource<TMessage>(
1664
- ref InstanceId source,
1665
- ref TMessage message,
1666
- Type type
1667
- )
1668
- where TMessage : IBroadcastMessage
1669
- {
1670
- if (
1671
- !_sinks.TryGetValue(
1672
- type,
1673
- out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1674
- )
1675
- || sortedHandlers.Count <= 0
1676
- )
1677
- {
1678
- return false;
1679
- }
1680
-
1681
- if (sortedHandlers.Count == 1)
1682
- {
1683
- KeyValuePair<int, SortedList<MessageHandler, int>> entry = sortedHandlers.First();
1684
- RunBroadcastWithoutSource(ref source, ref message, entry.Key, entry.Value);
1685
- return true;
1686
- }
1687
-
1688
- List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1689
- GetOrAddMessageHandlerStack(sortedHandlers);
1690
- try
1691
- {
1692
- foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1693
- {
1694
- RunBroadcastWithoutSource(ref source, ref message, entry.Key, entry.Value);
1695
- }
1696
- }
1697
- finally
1698
- {
1699
- _sortedHandlers.Push(handlerList);
1700
- }
1701
-
1702
- return true;
1703
- }
1704
-
1705
- private void RunBroadcastWithoutSource<TMessage>(
1706
- ref InstanceId source,
1707
- ref TMessage message,
1708
- int priority,
1709
- SortedList<MessageHandler, int> handlers
1710
- )
1711
- where TMessage : IBroadcastMessage
1712
- {
1713
- switch (handlers.Count)
1714
- {
1715
- case <= 0:
1716
- {
1717
- return;
1718
- }
1719
- case 1:
1720
- {
1721
- MessageHandler handler = handlers.Keys.First();
1722
- handler.HandleSourcedBroadcastWithoutSource(
1723
- ref source,
1724
- ref message,
1725
- this,
1726
- priority
1727
- );
1728
- return;
1729
- }
1730
- default:
1731
- {
1732
- List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1733
- handlers.Keys
1734
- );
1735
- try
1736
- {
1737
- foreach (MessageHandler handler in messageHandlers)
1738
- {
1739
- handler.HandleSourcedBroadcastWithoutSource(
1740
- ref source,
1741
- ref message,
1742
- this,
1743
- priority
1744
- );
1745
- }
1746
- }
1747
- finally
1748
- {
1749
- _messageHandlers.Push(messageHandlers);
1750
- }
1751
-
1752
- break;
1753
- }
1754
- }
1755
- }
1756
-
1757
- private Action InternalRegisterUntargeted<T>(
1758
- MessageHandler messageHandler,
1759
- Dictionary<Type, SortedList<int, SortedList<MessageHandler, int>>> sinks,
1760
- RegistrationMethod registrationMethod,
1761
- int priority
1762
- )
1763
- where T : IMessage
1764
- {
1765
- if (messageHandler == null)
1766
- {
1767
- throw new ArgumentNullException(nameof(messageHandler));
1768
- }
1769
-
1770
- InstanceId handlerOwnerId = messageHandler.owner;
1771
- Type type = typeof(T);
1772
-
1773
- if (
1774
- !sinks.TryGetValue(
1775
- type,
1776
- out SortedList<int, SortedList<MessageHandler, int>> handlers
1777
- )
1778
- )
1779
- {
1780
- handlers = new SortedList<int, SortedList<MessageHandler, int>>();
1781
- sinks[type] = handlers;
1782
- }
1783
-
1784
- if (!handlers.TryGetValue(priority, out SortedList<MessageHandler, int> handler))
1785
- {
1786
- handler = new SortedList<MessageHandler, int>();
1787
- handlers[priority] = handler;
1788
- }
1789
-
1790
- int count = handler.GetValueOrDefault(messageHandler, 0);
1791
-
1792
- handler[messageHandler] = count + 1;
1793
- _log.Log(
1794
- new MessagingRegistration(
1795
- handlerOwnerId,
1796
- type,
1797
- RegistrationType.Register,
1798
- registrationMethod
1799
- )
1800
- );
1801
-
1802
- return () =>
1803
- {
1804
- _log.Log(
1805
- new MessagingRegistration(
1806
- handlerOwnerId,
1807
- type,
1808
- RegistrationType.Deregister,
1809
- registrationMethod
1810
- )
1811
- );
1812
- if (
1813
- !sinks.TryGetValue(type, out handlers)
1814
- || !handlers.TryGetValue(priority, out handler)
1815
- || !handler.TryGetValue(messageHandler, out count)
1816
- )
1817
- {
1818
- MessagingDebug.Log(
1819
- LogLevel.Error,
1820
- "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1821
- type,
1822
- messageHandler
1823
- );
1824
- return;
1825
- }
1826
-
1827
- if (count <= 1)
1828
- {
1829
- bool complete = handler.Remove(messageHandler);
1830
-
1831
- if (handler.Count <= 0)
1832
- {
1833
- _ = handlers.Remove(priority);
1834
- }
1835
-
1836
- if (handlers.Count <= 0)
1837
- {
1838
- _ = sinks.Remove(type);
1839
- }
1840
-
1841
- if (!complete)
1842
- {
1843
- MessagingDebug.Log(
1844
- LogLevel.Error,
1845
- "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1846
- type,
1847
- messageHandler
1848
- );
1849
- }
1850
- }
1851
- else
1852
- {
1853
- handler[messageHandler] = count - 1;
1854
- }
1855
- };
1856
- }
1857
-
1858
- private Action InternalRegisterWithContext<T>(
1859
- InstanceId context,
1860
- MessageHandler messageHandler,
1861
- Dictionary<
1862
- Type,
1863
- Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
1864
- > sinks,
1865
- RegistrationMethod registrationMethod,
1866
- int priority
1867
- )
1868
- {
1869
- if (messageHandler == null)
1870
- {
1871
- throw new ArgumentNullException(nameof(messageHandler));
1872
- }
1873
-
1874
- Type type = typeof(T);
1875
- if (
1876
- !sinks.TryGetValue(
1877
- type,
1878
- out Dictionary<
1879
- InstanceId,
1880
- SortedList<int, SortedList<MessageHandler, int>>
1881
- > broadcastHandlers
1882
- )
1883
- )
1884
- {
1885
- broadcastHandlers =
1886
- new Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>();
1887
- sinks[type] = broadcastHandlers;
1888
- }
1889
-
1890
- if (
1891
- !broadcastHandlers.TryGetValue(
1892
- context,
1893
- out SortedList<int, SortedList<MessageHandler, int>> handlers
1894
- )
1895
- )
1896
- {
1897
- handlers = new SortedList<int, SortedList<MessageHandler, int>>();
1898
- broadcastHandlers[context] = handlers;
1899
- }
1900
-
1901
- if (!handlers.TryGetValue(priority, out SortedList<MessageHandler, int> handler))
1902
- {
1903
- handler = new SortedList<MessageHandler, int>();
1904
- handlers[priority] = handler;
1905
- }
1906
-
1907
- int count = handler.GetValueOrDefault(messageHandler, 0);
1908
-
1909
- handler[messageHandler] = count + 1;
1910
- _log.Log(
1911
- new MessagingRegistration(
1912
- context,
1913
- type,
1914
- RegistrationType.Register,
1915
- registrationMethod
1916
- )
1917
- );
1918
-
1919
- return () =>
1920
- {
1921
- _log.Log(
1922
- new MessagingRegistration(
1923
- context,
1924
- type,
1925
- RegistrationType.Deregister,
1926
- registrationMethod
1927
- )
1928
- );
1929
- if (
1930
- !sinks.TryGetValue(type, out broadcastHandlers)
1931
- || !broadcastHandlers.TryGetValue(context, out handlers)
1932
- || !handlers.TryGetValue(priority, out handler)
1933
- || !handler.TryGetValue(messageHandler, out count)
1934
- )
1935
- {
1936
- MessagingDebug.Log(
1937
- LogLevel.Error,
1938
- "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1939
- type,
1940
- messageHandler
1941
- );
1942
- return;
1943
- }
1944
-
1945
- if (count <= 1)
1946
- {
1947
- bool complete = handler.Remove(messageHandler);
1948
- if (handler.Count <= 0)
1949
- {
1950
- _ = handlers.Remove(priority);
1951
- }
1952
-
1953
- if (handlers.Count <= 0)
1954
- {
1955
- _ = broadcastHandlers.Remove(context);
1956
- }
1957
-
1958
- if (broadcastHandlers.Count <= 0)
1959
- {
1960
- _ = sinks.Remove(type);
1961
- }
1962
-
1963
- if (!complete)
1964
- {
1965
- MessagingDebug.Log(
1966
- LogLevel.Error,
1967
- "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1968
- type,
1969
- messageHandler
1970
- );
1971
- }
1972
- }
1973
- else
1974
- {
1975
- handler[messageHandler] = count - 1;
1976
- }
1977
- };
1978
- }
1979
-
1980
- private List<
1981
- KeyValuePair<int, SortedList<MessageHandler, int>>
1982
- > GetOrAddMessageHandlerStack(
1983
- IEnumerable<KeyValuePair<int, SortedList<MessageHandler, int>>> handlers
1984
- )
1985
- {
1986
- if (
1987
- !_sortedHandlers.TryPop(
1988
- out List<KeyValuePair<int, SortedList<MessageHandler, int>>> messageHandlers
1989
- )
1990
- )
1991
- {
1992
- return new List<KeyValuePair<int, SortedList<MessageHandler, int>>>(handlers);
1993
- }
1994
-
1995
- messageHandlers.Clear();
1996
- messageHandlers.AddRange(handlers);
1997
- return messageHandlers;
1998
- }
1999
-
2000
- private List<MessageHandler> GetOrAddMessageHandlerStack(
2001
- IEnumerable<MessageHandler> handlers
2002
- )
2003
- {
2004
- if (!_messageHandlers.TryPop(out List<MessageHandler> messageHandlers))
2005
- {
2006
- return new List<MessageHandler>(handlers);
2007
- }
2008
-
2009
- messageHandlers.Clear();
2010
- messageHandlers.AddRange(handlers);
2011
- return messageHandlers;
2012
- }
2013
-
2014
- // https://blogs.msmvps.com/jonskeet/2008/08/09/making-reflection-fly-and-exploring-delegates/
2015
- private static Action<IUntargetedMessage> UntargetedBroadcastReflectionHelper<T>(
2016
- IMessageBus messageBus,
2017
- MethodInfo methodInfo
2018
- )
2019
- where T : IUntargetedMessage
2020
- {
2021
- FastUntargetedBroadcast<T> untargetedBroadcast =
2022
- (FastUntargetedBroadcast<T>)
2023
- Delegate.CreateDelegate(
2024
- typeof(FastUntargetedBroadcast<T>),
2025
- messageBus,
2026
- methodInfo
2027
- );
2028
-
2029
- return UntypedBroadcast;
2030
-
2031
- void UntypedBroadcast(IUntargetedMessage message)
2032
- {
2033
- T typedMessage = (T)message;
2034
- untargetedBroadcast(ref typedMessage);
2035
- }
2036
- }
2037
-
2038
- private static Action<InstanceId, ITargetedMessage> TargetedBroadcastReflectionHelper<T>(
2039
- IMessageBus messageBus,
2040
- MethodInfo methodInfo
2041
- )
2042
- where T : ITargetedMessage
2043
- {
2044
- FastTargetedBroadcast<T> targetedBroadcast =
2045
- (FastTargetedBroadcast<T>)
2046
- Delegate.CreateDelegate(
2047
- typeof(FastTargetedBroadcast<T>),
2048
- messageBus,
2049
- methodInfo
2050
- );
2051
-
2052
- return UntypedBroadcast;
2053
-
2054
- void UntypedBroadcast(InstanceId target, ITargetedMessage message)
2055
- {
2056
- T typedMessage = (T)message;
2057
- targetedBroadcast(ref target, ref typedMessage);
2058
- }
2059
- }
2060
-
2061
- private static Action<InstanceId, IBroadcastMessage> SourcedBroadcastReflectionHelper<T>(
2062
- IMessageBus messageBus,
2063
- MethodInfo methodInfo
2064
- )
2065
- where T : IBroadcastMessage
2066
- {
2067
- FastSourcedBroadcast<T> sourcedBroadcast =
2068
- (FastSourcedBroadcast<T>)
2069
- Delegate.CreateDelegate(
2070
- typeof(FastSourcedBroadcast<T>),
2071
- messageBus,
2072
- methodInfo
2073
- );
2074
-
2075
- return UntypedBroadcast;
2076
-
2077
- void UntypedBroadcast(InstanceId target, IBroadcastMessage message)
2078
- {
2079
- T typedMessage = (T)message;
2080
- sourcedBroadcast(ref target, ref typedMessage);
2081
- }
2082
- }
2083
- }
2084
- }
1
+ namespace DxMessaging.Core.MessageBus
2
+ {
3
+ using System;
4
+ using System.Collections.Generic;
5
+ using System.Reflection;
6
+ using Messages;
7
+ using static IMessageBus;
8
+
9
+ /// <summary>
10
+ /// Instanced MessageBus for use cases where you want distinct islands of MessageBuses.
11
+ /// </summary>
12
+ public sealed class MessageBus : IMessageBus
13
+ {
14
+ public int RegisteredTargeted
15
+ {
16
+ get
17
+ {
18
+ int count = 0;
19
+ foreach (
20
+ KeyValuePair<
21
+ Type,
22
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
23
+ > entry in _targetedSinks
24
+ )
25
+ {
26
+ count += entry.Value.Count;
27
+ }
28
+
29
+ return count;
30
+ }
31
+ }
32
+
33
+ public int RegisteredBroadcast
34
+ {
35
+ get
36
+ {
37
+ int count = 0;
38
+ foreach (var entry in _broadcastSinks)
39
+ {
40
+ count += entry.Value.Count;
41
+ }
42
+
43
+ return count;
44
+ }
45
+ }
46
+
47
+ public int RegisteredUntargeted
48
+ {
49
+ get
50
+ {
51
+ int count = 0;
52
+ foreach (var entry in _sinks)
53
+ {
54
+ count += entry.Value.Count;
55
+ }
56
+
57
+ return count;
58
+ }
59
+ }
60
+
61
+ private static readonly Type MessageBusType = typeof(MessageBus);
62
+
63
+ // For use with re-broadcasting to generic methods
64
+ private static readonly object[] ReflectionMethodArgumentsCache = new object[2];
65
+
66
+ private const BindingFlags ReflectionHelperBindingFlags =
67
+ BindingFlags.Static | BindingFlags.NonPublic;
68
+
69
+ private delegate void FastUntargetedBroadcast<T>(ref T message)
70
+ where T : IUntargetedMessage;
71
+ private delegate void FastTargetedBroadcast<T>(ref InstanceId target, ref T message)
72
+ where T : ITargetedMessage;
73
+ private delegate void FastSourcedBroadcast<T>(ref InstanceId target, ref T message)
74
+ where T : IBroadcastMessage;
75
+
76
+ public RegistrationLog Log => _log;
77
+
78
+ private readonly Dictionary<Type, SortedList<int, SortedList<MessageHandler, int>>> _sinks =
79
+ new();
80
+ private readonly Dictionary<
81
+ Type,
82
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
83
+ > _targetedSinks = new();
84
+
85
+ private readonly Dictionary<
86
+ Type,
87
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
88
+ > _broadcastSinks = new();
89
+ private readonly Dictionary<
90
+ Type,
91
+ SortedList<int, SortedList<MessageHandler, int>>
92
+ > _postProcessingSinks = new();
93
+ private readonly Dictionary<
94
+ Type,
95
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
96
+ > _postProcessingTargetedSinks = new();
97
+ private readonly Dictionary<
98
+ Type,
99
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
100
+ > _postProcessingBroadcastSinks = new();
101
+ private readonly Dictionary<
102
+ Type,
103
+ SortedList<int, SortedList<MessageHandler, int>>
104
+ > _postProcessingTargetedWithoutTargetingSinks = new();
105
+ private readonly Dictionary<
106
+ Type,
107
+ SortedList<int, SortedList<MessageHandler, int>>
108
+ > _postProcessingBroadcastWithoutSourceSinks = new();
109
+ private readonly SortedList<MessageHandler, int> _globalSinks = new();
110
+ private readonly Dictionary<Type, SortedList<int, List<object>>> _interceptsByType = new();
111
+ private readonly Dictionary<object, Dictionary<int, int>> _uniqueInterceptorsAndPriorities =
112
+ new();
113
+
114
+ private readonly Dictionary<Type, object> _broadcastMethodsByType = new();
115
+
116
+ private readonly RegistrationLog _log = new();
117
+
118
+ // These are used so we aren't allocating as much every time we send messages
119
+ private readonly Stack<List<MessageHandler>> _messageHandlers = new();
120
+ private readonly Stack<
121
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>>
122
+ > _sortedHandlers = new();
123
+ private readonly Stack<List<List<object>>> _interceptors = new();
124
+ private readonly Stack<List<object>> _innerInterceptorsStack = new();
125
+
126
+ public Action RegisterUntargeted<T>(MessageHandler messageHandler, int priority = 0)
127
+ where T : IUntargetedMessage
128
+ {
129
+ return InternalRegisterUntargeted<T>(
130
+ messageHandler,
131
+ _sinks,
132
+ RegistrationMethod.Untargeted,
133
+ priority
134
+ );
135
+ }
136
+
137
+ public Action RegisterTargeted<T>(
138
+ InstanceId target,
139
+ MessageHandler messageHandler,
140
+ int priority = 0
141
+ )
142
+ where T : ITargetedMessage
143
+ {
144
+ return InternalRegisterWithContext<T>(
145
+ target,
146
+ messageHandler,
147
+ _targetedSinks,
148
+ RegistrationMethod.Targeted,
149
+ priority
150
+ );
151
+ }
152
+
153
+ public Action RegisterSourcedBroadcast<T>(
154
+ InstanceId source,
155
+ MessageHandler messageHandler,
156
+ int priority = 0
157
+ )
158
+ where T : IBroadcastMessage
159
+ {
160
+ return InternalRegisterWithContext<T>(
161
+ source,
162
+ messageHandler,
163
+ _broadcastSinks,
164
+ RegistrationMethod.Broadcast,
165
+ priority
166
+ );
167
+ }
168
+
169
+ public Action RegisterSourcedBroadcastWithoutSource<T>(
170
+ MessageHandler messageHandler,
171
+ int priority = 0
172
+ )
173
+ where T : IBroadcastMessage
174
+ {
175
+ return InternalRegisterUntargeted<T>(
176
+ messageHandler,
177
+ _sinks,
178
+ RegistrationMethod.BroadcastWithoutSource,
179
+ priority
180
+ );
181
+ }
182
+
183
+ public Action RegisterTargetedWithoutTargeting<T>(
184
+ MessageHandler messageHandler,
185
+ int priority = 0
186
+ )
187
+ where T : ITargetedMessage
188
+ {
189
+ return InternalRegisterUntargeted<T>(
190
+ messageHandler,
191
+ _sinks,
192
+ RegistrationMethod.TargetedWithoutTargeting,
193
+ priority
194
+ );
195
+ }
196
+
197
+ public Action RegisterGlobalAcceptAll(MessageHandler messageHandler)
198
+ {
199
+ int count = _globalSinks.GetValueOrDefault(messageHandler, 0);
200
+
201
+ Type type = typeof(IMessage);
202
+ _globalSinks[messageHandler] = count + 1;
203
+ _log.Log(
204
+ new MessagingRegistration(
205
+ messageHandler.owner,
206
+ type,
207
+ RegistrationType.Register,
208
+ RegistrationMethod.GlobalAcceptAll
209
+ )
210
+ );
211
+
212
+ return () =>
213
+ {
214
+ _log.Log(
215
+ new MessagingRegistration(
216
+ messageHandler.owner,
217
+ type,
218
+ RegistrationType.Deregister,
219
+ RegistrationMethod.GlobalAcceptAll
220
+ )
221
+ );
222
+ if (!_globalSinks.TryGetValue(messageHandler, out count))
223
+ {
224
+ MessagingDebug.Log(
225
+ LogLevel.Error,
226
+ "Received over-deregistration of GlobalAcceptAll for MessageHandler {0}. Check to make sure you're not calling (de)registration multiple times.",
227
+ messageHandler
228
+ );
229
+ return;
230
+ }
231
+
232
+ if (count <= 1)
233
+ {
234
+ _ = _globalSinks.Remove(messageHandler);
235
+ }
236
+ else
237
+ {
238
+ _globalSinks[messageHandler] = count - 1;
239
+ }
240
+ };
241
+ }
242
+
243
+ public Action RegisterUntargetedInterceptor<T>(
244
+ UntargetedInterceptor<T> interceptor,
245
+ int priority = 0
246
+ )
247
+ where T : IUntargetedMessage
248
+ {
249
+ return RegisterInterceptor<T>(interceptor, priority);
250
+ }
251
+
252
+ public Action RegisterTargetedInterceptor<T>(
253
+ TargetedInterceptor<T> interceptor,
254
+ int priority = 0
255
+ )
256
+ where T : ITargetedMessage
257
+ {
258
+ return RegisterInterceptor<T>(interceptor, priority);
259
+ }
260
+
261
+ public Action RegisterBroadcastInterceptor<T>(
262
+ BroadcastInterceptor<T> interceptor,
263
+ int priority = 0
264
+ )
265
+ where T : IBroadcastMessage
266
+ {
267
+ return RegisterInterceptor<T>(interceptor, priority);
268
+ }
269
+
270
+ public Action RegisterUntargetedPostProcessor<T>(
271
+ MessageHandler messageHandler,
272
+ int priority = 0
273
+ )
274
+ where T : IUntargetedMessage
275
+ {
276
+ return InternalRegisterUntargeted<T>(
277
+ messageHandler,
278
+ _postProcessingSinks,
279
+ RegistrationMethod.UntargetedPostProcessor,
280
+ priority
281
+ );
282
+ }
283
+
284
+ public Action RegisterTargetedPostProcessor<T>(
285
+ InstanceId target,
286
+ MessageHandler messageHandler,
287
+ int priority = 0
288
+ )
289
+ where T : ITargetedMessage
290
+ {
291
+ return InternalRegisterWithContext<T>(
292
+ target,
293
+ messageHandler,
294
+ _postProcessingTargetedSinks,
295
+ RegistrationMethod.TargetedPostProcessor,
296
+ priority
297
+ );
298
+ }
299
+
300
+ public Action RegisterTargetedWithoutTargetingPostProcessor<T>(
301
+ MessageHandler messageHandler,
302
+ int priority = 0
303
+ )
304
+ where T : ITargetedMessage
305
+ {
306
+ return InternalRegisterUntargeted<T>(
307
+ messageHandler,
308
+ _postProcessingTargetedWithoutTargetingSinks,
309
+ RegistrationMethod.TargetedWithoutTargetingPostProcessor,
310
+ priority
311
+ );
312
+ }
313
+
314
+ public Action RegisterBroadcastPostProcessor<T>(
315
+ InstanceId source,
316
+ MessageHandler messageHandler,
317
+ int priority = 0
318
+ )
319
+ where T : IBroadcastMessage
320
+ {
321
+ return InternalRegisterWithContext<T>(
322
+ source,
323
+ messageHandler,
324
+ _postProcessingBroadcastSinks,
325
+ RegistrationMethod.BroadcastPostProcessor,
326
+ priority
327
+ );
328
+ }
329
+
330
+ public Action RegisterBroadcastWithoutSourcePostProcessor<T>(
331
+ MessageHandler messageHandler,
332
+ int priority = 0
333
+ )
334
+ where T : IBroadcastMessage
335
+ {
336
+ return InternalRegisterUntargeted<T>(
337
+ messageHandler,
338
+ _postProcessingBroadcastWithoutSourceSinks,
339
+ RegistrationMethod.BroadcastWithoutSourcePostProcessor,
340
+ priority
341
+ );
342
+ }
343
+
344
+ private Action RegisterInterceptor<T>(object interceptor, int priority)
345
+ where T : IMessage
346
+ {
347
+ Type type = typeof(T);
348
+ if (
349
+ !_interceptsByType.TryGetValue(
350
+ type,
351
+ out SortedList<int, List<object>> prioritizedInterceptors
352
+ )
353
+ )
354
+ {
355
+ prioritizedInterceptors = new SortedList<int, List<object>>();
356
+ _interceptsByType[type] = prioritizedInterceptors;
357
+ }
358
+
359
+ if (!prioritizedInterceptors.TryGetValue(priority, out List<object> interceptors))
360
+ {
361
+ interceptors = new List<object>();
362
+ prioritizedInterceptors[priority] = interceptors;
363
+ }
364
+
365
+ if (
366
+ !_uniqueInterceptorsAndPriorities.TryGetValue(
367
+ interceptor,
368
+ out Dictionary<int, int> priorityCount
369
+ )
370
+ )
371
+ {
372
+ priorityCount = new Dictionary<int, int>();
373
+ _uniqueInterceptorsAndPriorities[interceptor] = priorityCount;
374
+ }
375
+
376
+ if (!priorityCount.TryGetValue(priority, out int count))
377
+ {
378
+ count = 0;
379
+ interceptors.Add(interceptor);
380
+ }
381
+
382
+ priorityCount[priority] = count + 1;
383
+
384
+ _log.Log(
385
+ new MessagingRegistration(
386
+ InstanceId.EmptyId,
387
+ type,
388
+ RegistrationType.Register,
389
+ RegistrationMethod.Interceptor
390
+ )
391
+ );
392
+
393
+ return () =>
394
+ {
395
+ _log.Log(
396
+ new MessagingRegistration(
397
+ InstanceId.EmptyId,
398
+ type,
399
+ RegistrationType.Deregister,
400
+ RegistrationMethod.Interceptor
401
+ )
402
+ );
403
+ bool removed = false;
404
+ if (_uniqueInterceptorsAndPriorities.TryGetValue(interceptor, out priorityCount))
405
+ {
406
+ if (priorityCount.TryGetValue(priority, out count))
407
+ {
408
+ if (1 < count)
409
+ {
410
+ priorityCount[priority] = count - 1;
411
+ }
412
+ else
413
+ {
414
+ removed = true;
415
+ _ = priorityCount.Remove(priority);
416
+ }
417
+ }
418
+
419
+ if (priorityCount.Count <= 0)
420
+ {
421
+ _uniqueInterceptorsAndPriorities.Remove(interceptor);
422
+ }
423
+ }
424
+ else
425
+ {
426
+ MessagingDebug.Log(
427
+ LogLevel.Error,
428
+ "Received over-deregistration of Interceptor {0}. Check to make sure you're not calling (de)registration multiple times.",
429
+ interceptor
430
+ );
431
+ }
432
+
433
+ bool complete = false;
434
+ if (removed)
435
+ {
436
+ if (
437
+ _interceptsByType.TryGetValue(type, out prioritizedInterceptors)
438
+ && prioritizedInterceptors.TryGetValue(priority, out interceptors)
439
+ )
440
+ {
441
+ complete = interceptors.Remove(interceptor);
442
+ }
443
+
444
+ if (!complete)
445
+ {
446
+ MessagingDebug.Log(
447
+ LogLevel.Error,
448
+ "Received over-deregistration of Interceptor {0}. Check to make sure you're not calling (de)registration multiple times.",
449
+ interceptor
450
+ );
451
+ }
452
+ }
453
+ };
454
+ }
455
+
456
+ public void UntypedUntargetedBroadcast(IUntargetedMessage typedMessage)
457
+ {
458
+ Type messageType = typedMessage.MessageType;
459
+ if (!_broadcastMethodsByType.TryGetValue(messageType, out object untargetedMethod))
460
+ {
461
+ // ReSharper disable once PossibleNullReferenceException
462
+ MethodInfo broadcastMethod = MessageBusType
463
+ .GetMethod(nameof(UntargetedBroadcast))
464
+ .MakeGenericMethod(messageType);
465
+ // ReSharper disable once PossibleNullReferenceException
466
+ MethodInfo helperMethod = MessageBusType
467
+ .GetMethod(
468
+ nameof(UntargetedBroadcastReflectionHelper),
469
+ ReflectionHelperBindingFlags
470
+ )
471
+ .MakeGenericMethod(messageType);
472
+
473
+ ReflectionMethodArgumentsCache[0] = this;
474
+ ReflectionMethodArgumentsCache[1] = broadcastMethod;
475
+ untargetedMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
476
+ _broadcastMethodsByType[messageType] = untargetedMethod;
477
+ }
478
+
479
+ Action<IUntargetedMessage> broadcast = (Action<IUntargetedMessage>)untargetedMethod;
480
+ broadcast.Invoke(typedMessage);
481
+ }
482
+
483
+ public void UntargetedBroadcast<TMessage>(ref TMessage typedMessage)
484
+ where TMessage : IUntargetedMessage
485
+ {
486
+ Type type = typeof(TMessage);
487
+ if (!RunUntargetedInterceptors(type, ref typedMessage))
488
+ {
489
+ return;
490
+ }
491
+
492
+ if (0 < _globalSinks.Count)
493
+ {
494
+ IUntargetedMessage untargetedMessage = typedMessage;
495
+ BroadcastGlobalUntargeted(ref untargetedMessage);
496
+ }
497
+
498
+ bool foundAnyHandlers = InternalUntargetedBroadcast(ref typedMessage, type);
499
+
500
+ if (
501
+ _postProcessingSinks.TryGetValue(
502
+ type,
503
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
504
+ )
505
+ && 0 < sortedHandlers.Count
506
+ )
507
+ {
508
+ foundAnyHandlers = true;
509
+ if (sortedHandlers.Count == 1)
510
+ {
511
+ RunUntargetedPostProcessing(
512
+ ref typedMessage,
513
+ sortedHandlers.Keys[0],
514
+ sortedHandlers.Values[0]
515
+ );
516
+ }
517
+ else
518
+ {
519
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
520
+ GetOrAddMessageHandlerStack(sortedHandlers);
521
+ try
522
+ {
523
+ foreach (
524
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
525
+ )
526
+ {
527
+ RunUntargetedPostProcessing(ref typedMessage, entry.Key, entry.Value);
528
+ }
529
+ }
530
+ finally
531
+ {
532
+ _sortedHandlers.Push(handlerList);
533
+ }
534
+ }
535
+ }
536
+
537
+ if (!foundAnyHandlers)
538
+ {
539
+ MessagingDebug.Log(
540
+ LogLevel.Info,
541
+ "Could not find a matching untargeted broadcast handler for Message: {0}.",
542
+ typedMessage
543
+ );
544
+ }
545
+ }
546
+
547
+ private void RunUntargetedPostProcessing<TMessage>(
548
+ ref TMessage typedMessage,
549
+ int priority,
550
+ SortedList<MessageHandler, int> handlers
551
+ )
552
+ where TMessage : IUntargetedMessage
553
+ {
554
+ switch (handlers.Count)
555
+ {
556
+ case <= 0:
557
+ {
558
+ return;
559
+ }
560
+ case 1:
561
+ {
562
+ MessageHandler handler = handlers.Keys[0];
563
+ handler.HandleUntargetedPostProcessing(ref typedMessage, this, priority);
564
+ return;
565
+ }
566
+ default:
567
+ {
568
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
569
+ handlers.Keys
570
+ );
571
+ try
572
+ {
573
+ foreach (MessageHandler handler in messageHandlers)
574
+ {
575
+ handler.HandleUntargetedPostProcessing(
576
+ ref typedMessage,
577
+ this,
578
+ priority
579
+ );
580
+ }
581
+ }
582
+ finally
583
+ {
584
+ _messageHandlers.Push(messageHandlers);
585
+ }
586
+
587
+ break;
588
+ }
589
+ }
590
+ }
591
+
592
+ public void UntypedTargetedBroadcast(InstanceId target, ITargetedMessage typedMessage)
593
+ {
594
+ Type messageType = typedMessage.MessageType;
595
+ if (!_broadcastMethodsByType.TryGetValue(messageType, out object targetedMethod))
596
+ {
597
+ // ReSharper disable once PossibleNullReferenceException
598
+ MethodInfo broadcastMethod = MessageBusType
599
+ .GetMethod(nameof(TargetedBroadcast))
600
+ .MakeGenericMethod(messageType);
601
+ // ReSharper disable once PossibleNullReferenceException
602
+ MethodInfo helperMethod = MessageBusType
603
+ .GetMethod(
604
+ nameof(TargetedBroadcastReflectionHelper),
605
+ ReflectionHelperBindingFlags
606
+ )
607
+ .MakeGenericMethod(messageType);
608
+
609
+ ReflectionMethodArgumentsCache[0] = this;
610
+ ReflectionMethodArgumentsCache[1] = broadcastMethod;
611
+ targetedMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
612
+ _broadcastMethodsByType[messageType] = targetedMethod;
613
+ }
614
+
615
+ Action<InstanceId, ITargetedMessage> broadcast =
616
+ (Action<InstanceId, ITargetedMessage>)targetedMethod;
617
+ broadcast.Invoke(target, typedMessage);
618
+ }
619
+
620
+ public void TargetedBroadcast<TMessage>(ref InstanceId target, ref TMessage typedMessage)
621
+ where TMessage : ITargetedMessage
622
+ {
623
+ Type type = typeof(TMessage);
624
+ if (!RunTargetedInterceptors(type, ref typedMessage, ref target))
625
+ {
626
+ return;
627
+ }
628
+
629
+ if (0 < _globalSinks.Count)
630
+ {
631
+ ITargetedMessage targetedMessage = typedMessage;
632
+ BroadcastGlobalTargeted(ref target, ref targetedMessage);
633
+ }
634
+
635
+ bool foundAnyHandlers = false;
636
+ if (
637
+ _targetedSinks.TryGetValue(
638
+ type,
639
+ out Dictionary<
640
+ InstanceId,
641
+ SortedList<int, SortedList<MessageHandler, int>>
642
+ > targetedHandlers
643
+ )
644
+ && targetedHandlers.TryGetValue(
645
+ target,
646
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
647
+ )
648
+ && 0 < sortedHandlers.Count
649
+ )
650
+ {
651
+ foundAnyHandlers = true;
652
+ if (sortedHandlers.Count == 1)
653
+ {
654
+ RunTargetedBroadcast(
655
+ ref target,
656
+ ref typedMessage,
657
+ sortedHandlers.Keys[0],
658
+ sortedHandlers.Values[0]
659
+ );
660
+ }
661
+ else
662
+ {
663
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
664
+ GetOrAddMessageHandlerStack(sortedHandlers);
665
+ try
666
+ {
667
+ foreach (
668
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
669
+ )
670
+ {
671
+ RunTargetedBroadcast(
672
+ ref target,
673
+ ref typedMessage,
674
+ entry.Key,
675
+ entry.Value
676
+ );
677
+ }
678
+ }
679
+ finally
680
+ {
681
+ _sortedHandlers.Push(handlerList);
682
+ }
683
+ }
684
+ }
685
+
686
+ _ = InternalTargetedWithoutTargetingBroadcast(ref target, ref typedMessage, type);
687
+
688
+ if (
689
+ _postProcessingTargetedSinks.TryGetValue(type, out targetedHandlers)
690
+ && targetedHandlers.TryGetValue(target, out sortedHandlers)
691
+ && 0 < sortedHandlers.Count
692
+ )
693
+ {
694
+ foundAnyHandlers = true;
695
+ if (sortedHandlers.Count == 1)
696
+ {
697
+ RunTargetedPostProcessing(
698
+ ref target,
699
+ ref typedMessage,
700
+ sortedHandlers.Keys[0],
701
+ sortedHandlers.Values[0]
702
+ );
703
+ }
704
+ else
705
+ {
706
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
707
+ GetOrAddMessageHandlerStack(sortedHandlers);
708
+ try
709
+ {
710
+ foreach (
711
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
712
+ )
713
+ {
714
+ RunTargetedPostProcessing(
715
+ ref target,
716
+ ref typedMessage,
717
+ entry.Key,
718
+ entry.Value
719
+ );
720
+ }
721
+ }
722
+ finally
723
+ {
724
+ _sortedHandlers.Push(handlerList);
725
+ }
726
+ }
727
+ }
728
+
729
+ if (
730
+ _postProcessingTargetedWithoutTargetingSinks.TryGetValue(type, out sortedHandlers)
731
+ && 0 < sortedHandlers.Count
732
+ )
733
+ {
734
+ if (sortedHandlers.Count == 1)
735
+ {
736
+ RunTargetedWithoutTargetingPostProcessing(
737
+ ref target,
738
+ ref typedMessage,
739
+ sortedHandlers.Keys[0],
740
+ sortedHandlers.Values[0]
741
+ );
742
+ }
743
+ else
744
+ {
745
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
746
+ GetOrAddMessageHandlerStack(sortedHandlers);
747
+ try
748
+ {
749
+ foreach (
750
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
751
+ )
752
+ {
753
+ RunTargetedWithoutTargetingPostProcessing(
754
+ ref target,
755
+ ref typedMessage,
756
+ entry.Key,
757
+ entry.Value
758
+ );
759
+ }
760
+ }
761
+ finally
762
+ {
763
+ _sortedHandlers.Push(handlerList);
764
+ }
765
+ }
766
+ }
767
+
768
+ if (!foundAnyHandlers)
769
+ {
770
+ MessagingDebug.Log(
771
+ LogLevel.Info,
772
+ "Could not find a matching targeted broadcast handler for Id: {0}, Message: {1}.",
773
+ target,
774
+ typedMessage
775
+ );
776
+ }
777
+ }
778
+
779
+ private void RunTargetedWithoutTargetingPostProcessing<TMessage>(
780
+ ref InstanceId target,
781
+ ref TMessage typedMessage,
782
+ int priority,
783
+ SortedList<MessageHandler, int> handlers
784
+ )
785
+ where TMessage : ITargetedMessage
786
+ {
787
+ switch (handlers.Count)
788
+ {
789
+ case <= 0:
790
+ {
791
+ return;
792
+ }
793
+ case 1:
794
+ {
795
+ MessageHandler handler = handlers.Keys[0];
796
+ handler.HandleTargetedWithoutTargetingPostProcessing(
797
+ ref target,
798
+ ref typedMessage,
799
+ this,
800
+ priority
801
+ );
802
+ return;
803
+ }
804
+ default:
805
+ {
806
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
807
+ handlers.Keys
808
+ );
809
+ try
810
+ {
811
+ foreach (MessageHandler handler in messageHandlers)
812
+ {
813
+ handler.HandleTargetedWithoutTargetingPostProcessing(
814
+ ref target,
815
+ ref typedMessage,
816
+ this,
817
+ priority
818
+ );
819
+ }
820
+ }
821
+ finally
822
+ {
823
+ _messageHandlers.Push(messageHandlers);
824
+ }
825
+
826
+ break;
827
+ }
828
+ }
829
+ }
830
+
831
+ private void RunTargetedPostProcessing<TMessage>(
832
+ ref InstanceId target,
833
+ ref TMessage typedMessage,
834
+ int priority,
835
+ SortedList<MessageHandler, int> handlers
836
+ )
837
+ where TMessage : ITargetedMessage
838
+ {
839
+ switch (handlers.Count)
840
+ {
841
+ case <= 0:
842
+ {
843
+ return;
844
+ }
845
+ case 1:
846
+ {
847
+ MessageHandler handler = handlers.Keys[0];
848
+ handler.HandleTargetedPostProcessing(
849
+ ref target,
850
+ ref typedMessage,
851
+ this,
852
+ priority
853
+ );
854
+ return;
855
+ }
856
+ default:
857
+ {
858
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
859
+ handlers.Keys
860
+ );
861
+ try
862
+ {
863
+ foreach (MessageHandler handler in messageHandlers)
864
+ {
865
+ handler.HandleTargetedPostProcessing(
866
+ ref target,
867
+ ref typedMessage,
868
+ this,
869
+ priority
870
+ );
871
+ }
872
+ }
873
+ finally
874
+ {
875
+ _messageHandlers.Push(messageHandlers);
876
+ }
877
+
878
+ break;
879
+ }
880
+ }
881
+ }
882
+
883
+ private void RunTargetedBroadcast<TMessage>(
884
+ ref InstanceId target,
885
+ ref TMessage typedMessage,
886
+ int priority,
887
+ SortedList<MessageHandler, int> handlers
888
+ )
889
+ where TMessage : ITargetedMessage
890
+ {
891
+ switch (handlers.Count)
892
+ {
893
+ case <= 0:
894
+ {
895
+ return;
896
+ }
897
+ case 1:
898
+ {
899
+ MessageHandler handler = handlers.Keys[0];
900
+ handler.HandleTargeted(ref target, ref typedMessage, this, priority);
901
+ return;
902
+ }
903
+ default:
904
+ {
905
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
906
+ handlers.Keys
907
+ );
908
+ try
909
+ {
910
+ foreach (MessageHandler handler in messageHandlers)
911
+ {
912
+ handler.HandleTargeted(ref target, ref typedMessage, this, priority);
913
+ }
914
+ }
915
+ finally
916
+ {
917
+ _messageHandlers.Push(messageHandlers);
918
+ }
919
+
920
+ break;
921
+ }
922
+ }
923
+ }
924
+
925
+ public void UntypedSourcedBroadcast(InstanceId source, IBroadcastMessage typedMessage)
926
+ {
927
+ Type messageType = typedMessage.MessageType;
928
+ if (
929
+ !_broadcastMethodsByType.TryGetValue(messageType, out object sourcedBroadcastMethod)
930
+ )
931
+ {
932
+ // ReSharper disable once PossibleNullReferenceException
933
+ MethodInfo broadcastMethod = MessageBusType
934
+ .GetMethod(nameof(SourcedBroadcast))
935
+ .MakeGenericMethod(messageType);
936
+ // ReSharper disable once PossibleNullReferenceException
937
+ MethodInfo helperMethod = MessageBusType
938
+ .GetMethod(
939
+ nameof(SourcedBroadcastReflectionHelper),
940
+ ReflectionHelperBindingFlags
941
+ )
942
+ .MakeGenericMethod(messageType);
943
+
944
+ ReflectionMethodArgumentsCache[0] = this;
945
+ ReflectionMethodArgumentsCache[1] = broadcastMethod;
946
+ sourcedBroadcastMethod = helperMethod.Invoke(null, ReflectionMethodArgumentsCache);
947
+
948
+ _broadcastMethodsByType[messageType] = sourcedBroadcastMethod;
949
+ }
950
+
951
+ Action<InstanceId, IBroadcastMessage> broadcast =
952
+ (Action<InstanceId, IBroadcastMessage>)sourcedBroadcastMethod;
953
+ broadcast.Invoke(source, typedMessage);
954
+ }
955
+
956
+ public void SourcedBroadcast<TMessage>(ref InstanceId source, ref TMessage typedMessage)
957
+ where TMessage : IBroadcastMessage
958
+ {
959
+ Type type = typeof(TMessage);
960
+ if (!RunBroadcastInterceptors(type, ref typedMessage, ref source))
961
+ {
962
+ return;
963
+ }
964
+
965
+ if (0 < _globalSinks.Count)
966
+ {
967
+ IBroadcastMessage broadcastMessage = typedMessage;
968
+ BroadcastGlobalSourcedBroadcast(ref source, ref broadcastMessage);
969
+ }
970
+
971
+ bool foundAnyHandlers = false;
972
+ if (
973
+ _broadcastSinks.TryGetValue(
974
+ type,
975
+ out Dictionary<
976
+ InstanceId,
977
+ SortedList<int, SortedList<MessageHandler, int>>
978
+ > broadcastHandlers
979
+ )
980
+ && broadcastHandlers.TryGetValue(
981
+ source,
982
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
983
+ )
984
+ && 0 < sortedHandlers.Count
985
+ )
986
+ {
987
+ foundAnyHandlers = true;
988
+ if (sortedHandlers.Count == 1)
989
+ {
990
+ RunBroadcast(
991
+ ref source,
992
+ ref typedMessage,
993
+ sortedHandlers.Keys[0],
994
+ sortedHandlers.Values[0]
995
+ );
996
+ }
997
+ else
998
+ {
999
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1000
+ GetOrAddMessageHandlerStack(sortedHandlers);
1001
+ try
1002
+ {
1003
+ foreach (
1004
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
1005
+ )
1006
+ {
1007
+ RunBroadcast(ref source, ref typedMessage, entry.Key, entry.Value);
1008
+ }
1009
+ }
1010
+ finally
1011
+ {
1012
+ _sortedHandlers.Push(handlerList);
1013
+ }
1014
+ }
1015
+ }
1016
+
1017
+ _ = InternalBroadcastWithoutSource(ref source, ref typedMessage, type);
1018
+
1019
+ if (
1020
+ _postProcessingBroadcastSinks.TryGetValue(type, out broadcastHandlers)
1021
+ && broadcastHandlers.TryGetValue(source, out sortedHandlers)
1022
+ && 0 < sortedHandlers.Count
1023
+ )
1024
+ {
1025
+ foundAnyHandlers = true;
1026
+ if (sortedHandlers.Count == 1)
1027
+ {
1028
+ RunBroadcastPostProcessing(
1029
+ ref source,
1030
+ ref typedMessage,
1031
+ sortedHandlers.Keys[0],
1032
+ sortedHandlers.Values[0]
1033
+ );
1034
+ }
1035
+ else
1036
+ {
1037
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1038
+ GetOrAddMessageHandlerStack(sortedHandlers);
1039
+ try
1040
+ {
1041
+ foreach (
1042
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
1043
+ )
1044
+ {
1045
+ RunBroadcastPostProcessing(
1046
+ ref source,
1047
+ ref typedMessage,
1048
+ entry.Key,
1049
+ entry.Value
1050
+ );
1051
+ }
1052
+ }
1053
+ finally
1054
+ {
1055
+ _sortedHandlers.Push(handlerList);
1056
+ }
1057
+ }
1058
+ }
1059
+
1060
+ if (
1061
+ _postProcessingBroadcastWithoutSourceSinks.TryGetValue(type, out sortedHandlers)
1062
+ && 0 < sortedHandlers.Count
1063
+ )
1064
+ {
1065
+ if (sortedHandlers.Count == 1)
1066
+ {
1067
+ RunBroadcastWithoutSourcePostProcessing(
1068
+ ref source,
1069
+ ref typedMessage,
1070
+ sortedHandlers.Keys[0],
1071
+ sortedHandlers.Values[0]
1072
+ );
1073
+ }
1074
+ else
1075
+ {
1076
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1077
+ GetOrAddMessageHandlerStack(sortedHandlers);
1078
+ try
1079
+ {
1080
+ foreach (
1081
+ KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList
1082
+ )
1083
+ {
1084
+ RunBroadcastWithoutSourcePostProcessing(
1085
+ ref source,
1086
+ ref typedMessage,
1087
+ entry.Key,
1088
+ entry.Value
1089
+ );
1090
+ }
1091
+ }
1092
+ finally
1093
+ {
1094
+ _sortedHandlers.Push(handlerList);
1095
+ }
1096
+ }
1097
+ }
1098
+
1099
+ if (!foundAnyHandlers)
1100
+ {
1101
+ MessagingDebug.Log(
1102
+ LogLevel.Info,
1103
+ "Could not find a matching sourced broadcast handler for Id: {0}, Message: {1}.",
1104
+ source,
1105
+ typedMessage
1106
+ );
1107
+ }
1108
+ }
1109
+
1110
+ private void RunBroadcastWithoutSourcePostProcessing<TMessage>(
1111
+ ref InstanceId source,
1112
+ ref TMessage typedMessage,
1113
+ int priority,
1114
+ SortedList<MessageHandler, int> handlers
1115
+ )
1116
+ where TMessage : IBroadcastMessage
1117
+ {
1118
+ switch (handlers.Count)
1119
+ {
1120
+ case <= 0:
1121
+ {
1122
+ return;
1123
+ }
1124
+ case 1:
1125
+ {
1126
+ MessageHandler handler = handlers.Keys[0];
1127
+ handler.HandleSourcedBroadcastWithoutSourcePostProcessing(
1128
+ ref source,
1129
+ ref typedMessage,
1130
+ this,
1131
+ priority
1132
+ );
1133
+ return;
1134
+ }
1135
+ default:
1136
+ {
1137
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1138
+ handlers.Keys
1139
+ );
1140
+ try
1141
+ {
1142
+ foreach (MessageHandler handler in messageHandlers)
1143
+ {
1144
+ handler.HandleSourcedBroadcastWithoutSourcePostProcessing(
1145
+ ref source,
1146
+ ref typedMessage,
1147
+ this,
1148
+ priority
1149
+ );
1150
+ }
1151
+ }
1152
+ finally
1153
+ {
1154
+ _messageHandlers.Push(messageHandlers);
1155
+ }
1156
+
1157
+ break;
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ private void RunBroadcastPostProcessing<TMessage>(
1163
+ ref InstanceId source,
1164
+ ref TMessage typedMessage,
1165
+ int priority,
1166
+ SortedList<MessageHandler, int> handlers
1167
+ )
1168
+ where TMessage : IBroadcastMessage
1169
+ {
1170
+ switch (handlers.Count)
1171
+ {
1172
+ case <= 0:
1173
+ {
1174
+ return;
1175
+ }
1176
+ case 1:
1177
+ {
1178
+ MessageHandler handler = handlers.Keys[0];
1179
+ handler.HandleSourcedBroadcastPostProcessing(
1180
+ ref source,
1181
+ ref typedMessage,
1182
+ this,
1183
+ priority
1184
+ );
1185
+ return;
1186
+ }
1187
+ default:
1188
+ {
1189
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1190
+ handlers.Keys
1191
+ );
1192
+ try
1193
+ {
1194
+ foreach (MessageHandler handler in messageHandlers)
1195
+ {
1196
+ handler.HandleSourcedBroadcastPostProcessing(
1197
+ ref source,
1198
+ ref typedMessage,
1199
+ this,
1200
+ priority
1201
+ );
1202
+ }
1203
+ }
1204
+ finally
1205
+ {
1206
+ _messageHandlers.Push(messageHandlers);
1207
+ }
1208
+
1209
+ break;
1210
+ }
1211
+ }
1212
+ }
1213
+
1214
+ private void RunBroadcast<TMessage>(
1215
+ ref InstanceId source,
1216
+ ref TMessage typedMessage,
1217
+ int priority,
1218
+ SortedList<MessageHandler, int> handlers
1219
+ )
1220
+ where TMessage : IBroadcastMessage
1221
+ {
1222
+ switch (handlers.Count)
1223
+ {
1224
+ case <= 0:
1225
+ {
1226
+ return;
1227
+ }
1228
+ case 1:
1229
+ {
1230
+ MessageHandler handler = handlers.Keys[0];
1231
+ handler.HandleSourcedBroadcast(ref source, ref typedMessage, this, priority);
1232
+ return;
1233
+ }
1234
+ default:
1235
+ {
1236
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1237
+ handlers.Keys
1238
+ );
1239
+ try
1240
+ {
1241
+ foreach (MessageHandler handler in messageHandlers)
1242
+ {
1243
+ handler.HandleSourcedBroadcast(
1244
+ ref source,
1245
+ ref typedMessage,
1246
+ this,
1247
+ priority
1248
+ );
1249
+ }
1250
+ }
1251
+ finally
1252
+ {
1253
+ _messageHandlers.Push(messageHandlers);
1254
+ }
1255
+
1256
+ break;
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ private void BroadcastGlobalUntargeted(ref IUntargetedMessage message)
1262
+ {
1263
+ switch (_globalSinks.Count)
1264
+ {
1265
+ case <= 0:
1266
+ {
1267
+ return;
1268
+ }
1269
+ case 1:
1270
+ {
1271
+ MessageHandler handler = _globalSinks.Keys[0];
1272
+ handler.HandleGlobalUntargetedMessage(ref message, this);
1273
+ return;
1274
+ }
1275
+ default:
1276
+ {
1277
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1278
+ _globalSinks.Keys
1279
+ );
1280
+ try
1281
+ {
1282
+ foreach (MessageHandler handler in messageHandlers)
1283
+ {
1284
+ handler.HandleGlobalUntargetedMessage(ref message, this);
1285
+ }
1286
+ }
1287
+ finally
1288
+ {
1289
+ _messageHandlers.Push(messageHandlers);
1290
+ }
1291
+
1292
+ break;
1293
+ }
1294
+ }
1295
+ }
1296
+
1297
+ private void BroadcastGlobalTargeted(ref InstanceId target, ref ITargetedMessage message)
1298
+ {
1299
+ switch (_globalSinks.Count)
1300
+ {
1301
+ case <= 0:
1302
+ {
1303
+ return;
1304
+ }
1305
+ case 1:
1306
+ {
1307
+ MessageHandler handler = _globalSinks.Keys[0];
1308
+ handler.HandleGlobalTargetedMessage(ref target, ref message, this);
1309
+ return;
1310
+ }
1311
+ default:
1312
+ {
1313
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1314
+ _globalSinks.Keys
1315
+ );
1316
+ try
1317
+ {
1318
+ foreach (MessageHandler handler in messageHandlers)
1319
+ {
1320
+ handler.HandleGlobalTargetedMessage(ref target, ref message, this);
1321
+ }
1322
+ }
1323
+ finally
1324
+ {
1325
+ _messageHandlers.Push(messageHandlers);
1326
+ }
1327
+
1328
+ break;
1329
+ }
1330
+ }
1331
+ }
1332
+
1333
+ private void BroadcastGlobalSourcedBroadcast(
1334
+ ref InstanceId source,
1335
+ ref IBroadcastMessage message
1336
+ )
1337
+ {
1338
+ switch (_globalSinks.Count)
1339
+ {
1340
+ case <= 0:
1341
+ {
1342
+ return;
1343
+ }
1344
+ case 1:
1345
+ {
1346
+ MessageHandler handler = _globalSinks.Keys[0];
1347
+ handler.HandleGlobalSourcedBroadcastMessage(ref source, ref message, this);
1348
+ return;
1349
+ }
1350
+ default:
1351
+ {
1352
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1353
+ _globalSinks.Keys
1354
+ );
1355
+ try
1356
+ {
1357
+ foreach (MessageHandler handler in messageHandlers)
1358
+ {
1359
+ handler.HandleGlobalSourcedBroadcastMessage(
1360
+ ref source,
1361
+ ref message,
1362
+ this
1363
+ );
1364
+ }
1365
+ }
1366
+ finally
1367
+ {
1368
+ _messageHandlers.Push(messageHandlers);
1369
+ }
1370
+
1371
+ break;
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ private bool TryGetInterceptorCaches(
1377
+ Type type,
1378
+ out List<List<object>> interceptorStack,
1379
+ out List<object> interceptorObjects
1380
+ )
1381
+ {
1382
+ if (
1383
+ !_interceptsByType.TryGetValue(type, out SortedList<int, List<object>> interceptors)
1384
+ || interceptors.Count <= 0
1385
+ )
1386
+ {
1387
+ interceptorStack = default;
1388
+ interceptorObjects = default;
1389
+ return false;
1390
+ }
1391
+
1392
+ if (!_interceptors.TryPop(out interceptorStack))
1393
+ {
1394
+ interceptorStack = new List<List<object>>(interceptors.Values);
1395
+ }
1396
+ else
1397
+ {
1398
+ interceptorStack.Clear();
1399
+ switch (interceptors.Values)
1400
+ {
1401
+ case List<List<object>> list:
1402
+ {
1403
+ foreach (List<object> interceptor in list)
1404
+ {
1405
+ interceptorStack.Add(interceptor);
1406
+ }
1407
+
1408
+ break;
1409
+ }
1410
+ case List<object>[] array:
1411
+ {
1412
+ foreach (List<object> interceptor in array)
1413
+ {
1414
+ interceptorStack.Add(interceptor);
1415
+ }
1416
+
1417
+ break;
1418
+ }
1419
+ default:
1420
+ {
1421
+ // ReSharper disable once ForCanBeConvertedToForeach
1422
+ // ReSharper disable once LoopCanBeConvertedToQuery
1423
+ for (int i = 0; i < interceptors.Values.Count; i++)
1424
+ {
1425
+ List<object> interceptor = interceptors.Values[i];
1426
+ interceptorStack.Add(interceptor);
1427
+ }
1428
+
1429
+ break;
1430
+ }
1431
+ }
1432
+ }
1433
+
1434
+ if (!_innerInterceptorsStack.TryPop(out interceptorObjects))
1435
+ {
1436
+ interceptorObjects = new List<object>();
1437
+ }
1438
+
1439
+ return true;
1440
+ }
1441
+
1442
+ private bool RunUntargetedInterceptors<T>(Type type, ref T message)
1443
+ where T : IUntargetedMessage
1444
+ {
1445
+ if (
1446
+ !TryGetInterceptorCaches(
1447
+ type,
1448
+ out List<List<object>> interceptorStack,
1449
+ out List<object> interceptorObjects
1450
+ )
1451
+ )
1452
+ {
1453
+ return true;
1454
+ }
1455
+
1456
+ try
1457
+ {
1458
+ foreach (List<object> stack in interceptorStack)
1459
+ {
1460
+ interceptorObjects.Clear();
1461
+ foreach (object interceptor in stack)
1462
+ {
1463
+ interceptorObjects.Add(interceptor);
1464
+ }
1465
+
1466
+ foreach (object transformer in interceptorObjects)
1467
+ {
1468
+ if (transformer is not UntargetedInterceptor<T> typedTransformer)
1469
+ {
1470
+ continue;
1471
+ }
1472
+
1473
+ if (!typedTransformer(ref message))
1474
+ {
1475
+ return false;
1476
+ }
1477
+ }
1478
+ }
1479
+ }
1480
+ finally
1481
+ {
1482
+ _interceptors.Push(interceptorStack);
1483
+ _innerInterceptorsStack.Push(interceptorObjects);
1484
+ }
1485
+
1486
+ return true;
1487
+ }
1488
+
1489
+ private bool RunTargetedInterceptors<T>(Type type, ref T message, ref InstanceId target)
1490
+ where T : ITargetedMessage
1491
+ {
1492
+ if (
1493
+ !TryGetInterceptorCaches(
1494
+ type,
1495
+ out List<List<object>> interceptorStack,
1496
+ out List<object> interceptorObjects
1497
+ )
1498
+ )
1499
+ {
1500
+ return true;
1501
+ }
1502
+
1503
+ try
1504
+ {
1505
+ foreach (List<object> stack in interceptorStack)
1506
+ {
1507
+ interceptorObjects.Clear();
1508
+ foreach (object interceptor in stack)
1509
+ {
1510
+ interceptorObjects.Add(interceptor);
1511
+ }
1512
+
1513
+ foreach (object transformer in interceptorObjects)
1514
+ {
1515
+ if (transformer is not TargetedInterceptor<T> typedTransformer)
1516
+ {
1517
+ continue;
1518
+ }
1519
+
1520
+ if (!typedTransformer(ref target, ref message))
1521
+ {
1522
+ return false;
1523
+ }
1524
+ }
1525
+ }
1526
+ }
1527
+ finally
1528
+ {
1529
+ _interceptors.Push(interceptorStack);
1530
+ _innerInterceptorsStack.Push(interceptorObjects);
1531
+ }
1532
+
1533
+ return true;
1534
+ }
1535
+
1536
+ private bool RunBroadcastInterceptors<T>(Type type, ref T message, ref InstanceId source)
1537
+ where T : IBroadcastMessage
1538
+ {
1539
+ if (
1540
+ !TryGetInterceptorCaches(
1541
+ type,
1542
+ out List<List<object>> interceptorStack,
1543
+ out List<object> interceptorObjects
1544
+ )
1545
+ )
1546
+ {
1547
+ return true;
1548
+ }
1549
+
1550
+ try
1551
+ {
1552
+ foreach (List<object> stack in interceptorStack)
1553
+ {
1554
+ interceptorObjects.Clear();
1555
+ foreach (object interceptor in stack)
1556
+ {
1557
+ interceptorObjects.Add(interceptor);
1558
+ }
1559
+
1560
+ foreach (object transformer in interceptorObjects)
1561
+ {
1562
+ if (transformer is not BroadcastInterceptor<T> typedTransformer)
1563
+ {
1564
+ continue;
1565
+ }
1566
+
1567
+ if (!typedTransformer(ref source, ref message))
1568
+ {
1569
+ return false;
1570
+ }
1571
+ }
1572
+ }
1573
+ }
1574
+ finally
1575
+ {
1576
+ _interceptors.Push(interceptorStack);
1577
+ _innerInterceptorsStack.Push(interceptorObjects);
1578
+ }
1579
+
1580
+ return true;
1581
+ }
1582
+
1583
+ private bool InternalUntargetedBroadcast<TMessage>(ref TMessage message, Type type)
1584
+ where TMessage : IMessage
1585
+ {
1586
+ if (
1587
+ !_sinks.TryGetValue(
1588
+ type,
1589
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1590
+ )
1591
+ || sortedHandlers.Count <= 0
1592
+ )
1593
+ {
1594
+ return false;
1595
+ }
1596
+
1597
+ if (sortedHandlers.Count == 1)
1598
+ {
1599
+ RunUntargetedBroadcast(
1600
+ ref message,
1601
+ sortedHandlers.Keys[0],
1602
+ sortedHandlers.Values[0]
1603
+ );
1604
+ return true;
1605
+ }
1606
+
1607
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1608
+ GetOrAddMessageHandlerStack(sortedHandlers);
1609
+ try
1610
+ {
1611
+ foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1612
+ {
1613
+ RunUntargetedBroadcast(ref message, entry.Key, entry.Value);
1614
+ }
1615
+ }
1616
+ finally
1617
+ {
1618
+ _sortedHandlers.Push(handlerList);
1619
+ }
1620
+
1621
+ return true;
1622
+ }
1623
+
1624
+ private void RunUntargetedBroadcast<TMessage>(
1625
+ ref TMessage message,
1626
+ int priority,
1627
+ SortedList<MessageHandler, int> handlers
1628
+ )
1629
+ where TMessage : IMessage
1630
+ {
1631
+ switch (handlers.Count)
1632
+ {
1633
+ case <= 0:
1634
+ {
1635
+ return;
1636
+ }
1637
+ case 1:
1638
+ {
1639
+ MessageHandler handler = handlers.Keys[0];
1640
+ handler.HandleUntargetedMessage(ref message, this, priority);
1641
+ return;
1642
+ }
1643
+ default:
1644
+ {
1645
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1646
+ handlers.Keys
1647
+ );
1648
+ try
1649
+ {
1650
+ foreach (MessageHandler handler in messageHandlers)
1651
+ {
1652
+ handler.HandleUntargetedMessage(ref message, this, priority);
1653
+ }
1654
+ }
1655
+ finally
1656
+ {
1657
+ _messageHandlers.Push(messageHandlers);
1658
+ }
1659
+
1660
+ break;
1661
+ }
1662
+ }
1663
+ }
1664
+
1665
+ private bool InternalTargetedWithoutTargetingBroadcast<TMessage>(
1666
+ ref InstanceId target,
1667
+ ref TMessage message,
1668
+ Type type
1669
+ )
1670
+ where TMessage : ITargetedMessage
1671
+ {
1672
+ if (
1673
+ !_sinks.TryGetValue(
1674
+ type,
1675
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1676
+ )
1677
+ || sortedHandlers.Count <= 0
1678
+ )
1679
+ {
1680
+ return false;
1681
+ }
1682
+
1683
+ if (sortedHandlers.Count == 1)
1684
+ {
1685
+ RunTargetedWithoutTargeting(
1686
+ ref target,
1687
+ ref message,
1688
+ sortedHandlers.Keys[0],
1689
+ sortedHandlers.Values[0]
1690
+ );
1691
+ return true;
1692
+ }
1693
+
1694
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1695
+ GetOrAddMessageHandlerStack(sortedHandlers);
1696
+ try
1697
+ {
1698
+ foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1699
+ {
1700
+ RunTargetedWithoutTargeting(ref target, ref message, entry.Key, entry.Value);
1701
+ }
1702
+ }
1703
+ finally
1704
+ {
1705
+ _sortedHandlers.Push(handlerList);
1706
+ }
1707
+
1708
+ return true;
1709
+ }
1710
+
1711
+ private void RunTargetedWithoutTargeting<TMessage>(
1712
+ ref InstanceId target,
1713
+ ref TMessage message,
1714
+ int priority,
1715
+ SortedList<MessageHandler, int> handlers
1716
+ )
1717
+ where TMessage : ITargetedMessage
1718
+ {
1719
+ switch (handlers.Count)
1720
+ {
1721
+ case <= 0:
1722
+ {
1723
+ return;
1724
+ }
1725
+ case 1:
1726
+ {
1727
+ MessageHandler handler = handlers.Keys[0];
1728
+ handler.HandleTargetedWithoutTargeting(ref target, ref message, this, priority);
1729
+ return;
1730
+ }
1731
+ default:
1732
+ {
1733
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1734
+ handlers.Keys
1735
+ );
1736
+ try
1737
+ {
1738
+ foreach (MessageHandler handler in messageHandlers)
1739
+ {
1740
+ handler.HandleTargetedWithoutTargeting(
1741
+ ref target,
1742
+ ref message,
1743
+ this,
1744
+ priority
1745
+ );
1746
+ }
1747
+ }
1748
+ finally
1749
+ {
1750
+ _messageHandlers.Push(messageHandlers);
1751
+ }
1752
+
1753
+ break;
1754
+ }
1755
+ }
1756
+ }
1757
+
1758
+ private bool InternalBroadcastWithoutSource<TMessage>(
1759
+ ref InstanceId source,
1760
+ ref TMessage message,
1761
+ Type type
1762
+ )
1763
+ where TMessage : IBroadcastMessage
1764
+ {
1765
+ if (
1766
+ !_sinks.TryGetValue(
1767
+ type,
1768
+ out SortedList<int, SortedList<MessageHandler, int>> sortedHandlers
1769
+ )
1770
+ || sortedHandlers.Count <= 0
1771
+ )
1772
+ {
1773
+ return false;
1774
+ }
1775
+
1776
+ if (sortedHandlers.Count == 1)
1777
+ {
1778
+ RunBroadcastWithoutSource(
1779
+ ref source,
1780
+ ref message,
1781
+ sortedHandlers.Keys[0],
1782
+ sortedHandlers.Values[0]
1783
+ );
1784
+ return true;
1785
+ }
1786
+
1787
+ List<KeyValuePair<int, SortedList<MessageHandler, int>>> handlerList =
1788
+ GetOrAddMessageHandlerStack(sortedHandlers);
1789
+ try
1790
+ {
1791
+ foreach (KeyValuePair<int, SortedList<MessageHandler, int>> entry in handlerList)
1792
+ {
1793
+ RunBroadcastWithoutSource(ref source, ref message, entry.Key, entry.Value);
1794
+ }
1795
+ }
1796
+ finally
1797
+ {
1798
+ _sortedHandlers.Push(handlerList);
1799
+ }
1800
+
1801
+ return true;
1802
+ }
1803
+
1804
+ private void RunBroadcastWithoutSource<TMessage>(
1805
+ ref InstanceId source,
1806
+ ref TMessage message,
1807
+ int priority,
1808
+ SortedList<MessageHandler, int> handlers
1809
+ )
1810
+ where TMessage : IBroadcastMessage
1811
+ {
1812
+ switch (handlers.Count)
1813
+ {
1814
+ case <= 0:
1815
+ {
1816
+ return;
1817
+ }
1818
+ case 1:
1819
+ {
1820
+ MessageHandler handler = handlers.Keys[0];
1821
+ handler.HandleSourcedBroadcastWithoutSource(
1822
+ ref source,
1823
+ ref message,
1824
+ this,
1825
+ priority
1826
+ );
1827
+ return;
1828
+ }
1829
+ default:
1830
+ {
1831
+ List<MessageHandler> messageHandlers = GetOrAddMessageHandlerStack(
1832
+ handlers.Keys
1833
+ );
1834
+ try
1835
+ {
1836
+ foreach (MessageHandler handler in messageHandlers)
1837
+ {
1838
+ handler.HandleSourcedBroadcastWithoutSource(
1839
+ ref source,
1840
+ ref message,
1841
+ this,
1842
+ priority
1843
+ );
1844
+ }
1845
+ }
1846
+ finally
1847
+ {
1848
+ _messageHandlers.Push(messageHandlers);
1849
+ }
1850
+
1851
+ break;
1852
+ }
1853
+ }
1854
+ }
1855
+
1856
+ private Action InternalRegisterUntargeted<T>(
1857
+ MessageHandler messageHandler,
1858
+ Dictionary<Type, SortedList<int, SortedList<MessageHandler, int>>> sinks,
1859
+ RegistrationMethod registrationMethod,
1860
+ int priority
1861
+ )
1862
+ where T : IMessage
1863
+ {
1864
+ if (messageHandler == null)
1865
+ {
1866
+ throw new ArgumentNullException(nameof(messageHandler));
1867
+ }
1868
+
1869
+ InstanceId handlerOwnerId = messageHandler.owner;
1870
+ Type type = typeof(T);
1871
+
1872
+ if (
1873
+ !sinks.TryGetValue(
1874
+ type,
1875
+ out SortedList<int, SortedList<MessageHandler, int>> handlers
1876
+ )
1877
+ )
1878
+ {
1879
+ handlers = new SortedList<int, SortedList<MessageHandler, int>>();
1880
+ sinks[type] = handlers;
1881
+ }
1882
+
1883
+ if (!handlers.TryGetValue(priority, out SortedList<MessageHandler, int> handler))
1884
+ {
1885
+ handler = new SortedList<MessageHandler, int>();
1886
+ handlers[priority] = handler;
1887
+ }
1888
+
1889
+ int count = handler.GetValueOrDefault(messageHandler, 0);
1890
+
1891
+ handler[messageHandler] = count + 1;
1892
+ _log.Log(
1893
+ new MessagingRegistration(
1894
+ handlerOwnerId,
1895
+ type,
1896
+ RegistrationType.Register,
1897
+ registrationMethod
1898
+ )
1899
+ );
1900
+
1901
+ return () =>
1902
+ {
1903
+ _log.Log(
1904
+ new MessagingRegistration(
1905
+ handlerOwnerId,
1906
+ type,
1907
+ RegistrationType.Deregister,
1908
+ registrationMethod
1909
+ )
1910
+ );
1911
+ if (
1912
+ !sinks.TryGetValue(type, out handlers)
1913
+ || !handlers.TryGetValue(priority, out handler)
1914
+ || !handler.TryGetValue(messageHandler, out count)
1915
+ )
1916
+ {
1917
+ MessagingDebug.Log(
1918
+ LogLevel.Error,
1919
+ "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1920
+ type,
1921
+ messageHandler
1922
+ );
1923
+ return;
1924
+ }
1925
+
1926
+ if (count <= 1)
1927
+ {
1928
+ bool complete = handler.Remove(messageHandler);
1929
+
1930
+ if (handler.Count <= 0)
1931
+ {
1932
+ _ = handlers.Remove(priority);
1933
+ }
1934
+
1935
+ if (handlers.Count <= 0)
1936
+ {
1937
+ _ = sinks.Remove(type);
1938
+ }
1939
+
1940
+ if (!complete)
1941
+ {
1942
+ MessagingDebug.Log(
1943
+ LogLevel.Error,
1944
+ "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
1945
+ type,
1946
+ messageHandler
1947
+ );
1948
+ }
1949
+ }
1950
+ else
1951
+ {
1952
+ handler[messageHandler] = count - 1;
1953
+ }
1954
+ };
1955
+ }
1956
+
1957
+ private Action InternalRegisterWithContext<T>(
1958
+ InstanceId context,
1959
+ MessageHandler messageHandler,
1960
+ Dictionary<
1961
+ Type,
1962
+ Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>
1963
+ > sinks,
1964
+ RegistrationMethod registrationMethod,
1965
+ int priority
1966
+ )
1967
+ {
1968
+ if (messageHandler == null)
1969
+ {
1970
+ throw new ArgumentNullException(nameof(messageHandler));
1971
+ }
1972
+
1973
+ Type type = typeof(T);
1974
+ if (
1975
+ !sinks.TryGetValue(
1976
+ type,
1977
+ out Dictionary<
1978
+ InstanceId,
1979
+ SortedList<int, SortedList<MessageHandler, int>>
1980
+ > broadcastHandlers
1981
+ )
1982
+ )
1983
+ {
1984
+ broadcastHandlers =
1985
+ new Dictionary<InstanceId, SortedList<int, SortedList<MessageHandler, int>>>();
1986
+ sinks[type] = broadcastHandlers;
1987
+ }
1988
+
1989
+ if (
1990
+ !broadcastHandlers.TryGetValue(
1991
+ context,
1992
+ out SortedList<int, SortedList<MessageHandler, int>> handlers
1993
+ )
1994
+ )
1995
+ {
1996
+ handlers = new SortedList<int, SortedList<MessageHandler, int>>();
1997
+ broadcastHandlers[context] = handlers;
1998
+ }
1999
+
2000
+ if (!handlers.TryGetValue(priority, out SortedList<MessageHandler, int> handler))
2001
+ {
2002
+ handler = new SortedList<MessageHandler, int>();
2003
+ handlers[priority] = handler;
2004
+ }
2005
+
2006
+ int count = handler.GetValueOrDefault(messageHandler, 0);
2007
+
2008
+ handler[messageHandler] = count + 1;
2009
+ _log.Log(
2010
+ new MessagingRegistration(
2011
+ context,
2012
+ type,
2013
+ RegistrationType.Register,
2014
+ registrationMethod
2015
+ )
2016
+ );
2017
+
2018
+ return () =>
2019
+ {
2020
+ _log.Log(
2021
+ new MessagingRegistration(
2022
+ context,
2023
+ type,
2024
+ RegistrationType.Deregister,
2025
+ registrationMethod
2026
+ )
2027
+ );
2028
+ if (
2029
+ !sinks.TryGetValue(type, out broadcastHandlers)
2030
+ || !broadcastHandlers.TryGetValue(context, out handlers)
2031
+ || !handlers.TryGetValue(priority, out handler)
2032
+ || !handler.TryGetValue(messageHandler, out count)
2033
+ )
2034
+ {
2035
+ MessagingDebug.Log(
2036
+ LogLevel.Error,
2037
+ "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
2038
+ type,
2039
+ messageHandler
2040
+ );
2041
+ return;
2042
+ }
2043
+
2044
+ if (count <= 1)
2045
+ {
2046
+ bool complete = handler.Remove(messageHandler);
2047
+ if (handler.Count <= 0)
2048
+ {
2049
+ _ = handlers.Remove(priority);
2050
+ }
2051
+
2052
+ if (handlers.Count <= 0)
2053
+ {
2054
+ _ = broadcastHandlers.Remove(context);
2055
+ }
2056
+
2057
+ if (broadcastHandlers.Count <= 0)
2058
+ {
2059
+ _ = sinks.Remove(type);
2060
+ }
2061
+
2062
+ if (!complete)
2063
+ {
2064
+ MessagingDebug.Log(
2065
+ LogLevel.Error,
2066
+ "Received over-deregistration of {0} for {1}. Check to make sure you're not calling (de)registration multiple times.",
2067
+ type,
2068
+ messageHandler
2069
+ );
2070
+ }
2071
+ }
2072
+ else
2073
+ {
2074
+ handler[messageHandler] = count - 1;
2075
+ }
2076
+ };
2077
+ }
2078
+
2079
+ private List<
2080
+ KeyValuePair<int, SortedList<MessageHandler, int>>
2081
+ > GetOrAddMessageHandlerStack(
2082
+ IEnumerable<KeyValuePair<int, SortedList<MessageHandler, int>>> handlers
2083
+ )
2084
+ {
2085
+ if (
2086
+ !_sortedHandlers.TryPop(
2087
+ out List<KeyValuePair<int, SortedList<MessageHandler, int>>> messageHandlers
2088
+ )
2089
+ )
2090
+ {
2091
+ return new List<KeyValuePair<int, SortedList<MessageHandler, int>>>(handlers);
2092
+ }
2093
+
2094
+ messageHandlers.Clear();
2095
+ if (handlers is SortedList<int, SortedList<MessageHandler, int>> sortedList)
2096
+ {
2097
+ for (int i = 0; i < sortedList.Count; ++i)
2098
+ {
2099
+ messageHandlers.Add(
2100
+ new KeyValuePair<int, SortedList<MessageHandler, int>>(
2101
+ sortedList.Keys[i],
2102
+ sortedList.Values[i]
2103
+ )
2104
+ );
2105
+ }
2106
+ }
2107
+ else
2108
+ {
2109
+ messageHandlers.AddRange(handlers);
2110
+ }
2111
+ return messageHandlers;
2112
+ }
2113
+
2114
+ private List<MessageHandler> GetOrAddMessageHandlerStack(
2115
+ IEnumerable<MessageHandler> handlers
2116
+ )
2117
+ {
2118
+ if (!_messageHandlers.TryPop(out List<MessageHandler> messageHandlers))
2119
+ {
2120
+ return new List<MessageHandler>(handlers);
2121
+ }
2122
+
2123
+ messageHandlers.Clear();
2124
+ // Try to avoid allocations if at all possible
2125
+ switch (handlers)
2126
+ {
2127
+ case List<MessageHandler> list:
2128
+ {
2129
+ foreach (MessageHandler handler in list)
2130
+ {
2131
+ messageHandlers.Add(handler);
2132
+ }
2133
+
2134
+ break;
2135
+ }
2136
+ case MessageHandler[] array:
2137
+ {
2138
+ foreach (MessageHandler handler in array)
2139
+ {
2140
+ messageHandlers.Add(handler);
2141
+ }
2142
+
2143
+ break;
2144
+ }
2145
+ case IList<MessageHandler> interfaceList:
2146
+ {
2147
+ for (int i = 0; i < interfaceList.Count; ++i)
2148
+ {
2149
+ messageHandlers.Add(interfaceList[i]);
2150
+ }
2151
+
2152
+ break;
2153
+ }
2154
+ case HashSet<MessageHandler> set:
2155
+ {
2156
+ foreach (MessageHandler handler in set)
2157
+ {
2158
+ messageHandlers.Add(handler);
2159
+ }
2160
+
2161
+ break;
2162
+ }
2163
+ default:
2164
+ {
2165
+ messageHandlers.AddRange(handlers);
2166
+ break;
2167
+ }
2168
+ }
2169
+
2170
+ return messageHandlers;
2171
+ }
2172
+
2173
+ // https://blogs.msmvps.com/jonskeet/2008/08/09/making-reflection-fly-and-exploring-delegates/
2174
+ private static Action<IUntargetedMessage> UntargetedBroadcastReflectionHelper<T>(
2175
+ IMessageBus messageBus,
2176
+ MethodInfo methodInfo
2177
+ )
2178
+ where T : IUntargetedMessage
2179
+ {
2180
+ FastUntargetedBroadcast<T> untargetedBroadcast =
2181
+ (FastUntargetedBroadcast<T>)
2182
+ Delegate.CreateDelegate(
2183
+ typeof(FastUntargetedBroadcast<T>),
2184
+ messageBus,
2185
+ methodInfo
2186
+ );
2187
+
2188
+ return UntypedBroadcast;
2189
+
2190
+ void UntypedBroadcast(IUntargetedMessage message)
2191
+ {
2192
+ T typedMessage = (T)message;
2193
+ untargetedBroadcast(ref typedMessage);
2194
+ }
2195
+ }
2196
+
2197
+ private static Action<InstanceId, ITargetedMessage> TargetedBroadcastReflectionHelper<T>(
2198
+ IMessageBus messageBus,
2199
+ MethodInfo methodInfo
2200
+ )
2201
+ where T : ITargetedMessage
2202
+ {
2203
+ FastTargetedBroadcast<T> targetedBroadcast =
2204
+ (FastTargetedBroadcast<T>)
2205
+ Delegate.CreateDelegate(
2206
+ typeof(FastTargetedBroadcast<T>),
2207
+ messageBus,
2208
+ methodInfo
2209
+ );
2210
+
2211
+ return UntypedBroadcast;
2212
+
2213
+ void UntypedBroadcast(InstanceId target, ITargetedMessage message)
2214
+ {
2215
+ T typedMessage = (T)message;
2216
+ targetedBroadcast(ref target, ref typedMessage);
2217
+ }
2218
+ }
2219
+
2220
+ private static Action<InstanceId, IBroadcastMessage> SourcedBroadcastReflectionHelper<T>(
2221
+ IMessageBus messageBus,
2222
+ MethodInfo methodInfo
2223
+ )
2224
+ where T : IBroadcastMessage
2225
+ {
2226
+ FastSourcedBroadcast<T> sourcedBroadcast =
2227
+ (FastSourcedBroadcast<T>)
2228
+ Delegate.CreateDelegate(
2229
+ typeof(FastSourcedBroadcast<T>),
2230
+ messageBus,
2231
+ methodInfo
2232
+ );
2233
+
2234
+ return UntypedBroadcast;
2235
+
2236
+ void UntypedBroadcast(InstanceId target, IBroadcastMessage message)
2237
+ {
2238
+ T typedMessage = (T)message;
2239
+ sourcedBroadcast(ref target, ref typedMessage);
2240
+ }
2241
+ }
2242
+ }
2243
+ }