com.wallstop-studios.dxmessaging 2.0.0 → 2.1.1

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 (183) hide show
  1. package/.github/workflows/format-on-demand.yml +2 -2
  2. package/.github/workflows/json-format-check.yml +1 -1
  3. package/.github/workflows/markdown-json.yml +1 -1
  4. package/.github/workflows/markdownlint.yml +1 -1
  5. package/.github/workflows/npm-publish.yml +1 -1
  6. package/.github/workflows/prettier-autofix.yml +2 -2
  7. package/.github/workflows/yaml-format-lint.yml +1 -1
  8. package/Docs/Advanced.md +26 -1
  9. package/Docs/Comparisons.md +1229 -146
  10. package/Docs/Compatibility.md +27 -0
  11. package/Docs/DesignAndArchitecture.md +41 -34
  12. package/Docs/EmitShorthands.md +34 -0
  13. package/Docs/Helpers.md +91 -76
  14. package/Docs/Index.md +28 -25
  15. package/Docs/Install.md +29 -6
  16. package/Docs/Integrations/Reflex.md +292 -0
  17. package/{package-lock.json.meta → Docs/Integrations/Reflex.md.meta} +1 -1
  18. package/Docs/Integrations/VContainer.md +324 -0
  19. package/Docs/Integrations/VContainer.md.meta +7 -0
  20. package/Docs/Integrations/Zenject.md +333 -0
  21. package/Docs/Integrations/Zenject.md.meta +7 -0
  22. package/{Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta → Docs/Integrations.meta} +2 -1
  23. package/Docs/InterceptorsAndOrdering.md +371 -17
  24. package/Docs/ListeningPatterns.md +206 -0
  25. package/Docs/MessageBusProviders.md +496 -0
  26. package/Docs/MessageBusProviders.md.meta +7 -0
  27. package/Docs/MessageTypes.md +27 -0
  28. package/Docs/MigrationGuide.md +45 -0
  29. package/Docs/Patterns.md +286 -0
  30. package/Docs/Performance.md +9 -9
  31. package/Docs/QuickReference.md +31 -0
  32. package/Docs/QuickStart.md +1 -2
  33. package/Docs/RuntimeConfiguration.md +407 -0
  34. package/Docs/RuntimeConfiguration.md.meta +7 -0
  35. package/Docs/UnityIntegration.md +3 -1
  36. package/Docs/VisualGuide.md +206 -157
  37. package/Editor/CustomEditors/MessagingComponentEditor.cs +15 -6
  38. package/README.md +148 -26
  39. package/Runtime/AssemblyInfo.cs +4 -0
  40. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs +1 -1
  41. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +1 -1
  42. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +1 -1
  43. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +1 -1
  44. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +1 -1
  45. package/Runtime/Core/Extensions/MessageBusExtensions.cs +253 -0
  46. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -0
  47. package/Runtime/Core/Extensions/MessageExtensions.cs +137 -89
  48. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs +23 -0
  49. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -0
  50. package/Runtime/Core/MessageBus/IMessageBusProvider.cs +14 -0
  51. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -0
  52. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +18 -0
  53. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -0
  54. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs +26 -0
  55. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -0
  56. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +383 -0
  57. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -0
  58. package/Runtime/Core/MessageHandler.cs +198 -27
  59. package/Runtime/Core/MessageRegistrationToken.cs +67 -25
  60. package/Runtime/Core/Messages/IBroadcastMessage.cs +1 -1
  61. package/Runtime/Core/Messages/ITargetedMessage.cs +1 -1
  62. package/Runtime/Core/Messages/IUntargetedMessage.cs +1 -1
  63. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +31 -0
  64. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -0
  65. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +38 -0
  66. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -0
  67. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs +11 -0
  68. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +3 -0
  69. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  70. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -0
  71. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -0
  72. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -0
  73. package/Runtime/Unity/Integrations/Reflex.meta +8 -0
  74. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs +11 -0
  75. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  76. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +46 -0
  77. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -0
  78. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -0
  79. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -0
  80. package/Runtime/Unity/Integrations/VContainer.meta +8 -0
  81. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs +11 -0
  82. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  83. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -0
  84. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -0
  85. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +55 -0
  86. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -0
  87. package/Runtime/Unity/Integrations/Zenject.meta +8 -0
  88. package/Runtime/Unity/Integrations.meta +8 -0
  89. package/Runtime/Unity/MessageAwareComponent.cs +102 -0
  90. package/Runtime/Unity/MessageBusProviderHandle.cs +97 -0
  91. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -0
  92. package/Runtime/Unity/MessagingComponent.cs +175 -9
  93. package/Runtime/Unity/MessagingComponentInstaller.cs +120 -0
  94. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -0
  95. package/Runtime/Unity/ScriptableMessageBusProvider.cs +14 -0
  96. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -0
  97. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -0
  98. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -0
  99. package/Samples~/DI/Prefabs.meta +8 -0
  100. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -0
  101. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -0
  102. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -0
  103. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -0
  104. package/Samples~/DI/Providers.meta +8 -0
  105. package/Samples~/DI/README.md +51 -0
  106. package/Samples~/DI/README.md.meta +7 -0
  107. package/Samples~/DI/Reflex/SampleInstaller.cs +75 -0
  108. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -0
  109. package/Samples~/DI/Reflex.meta +8 -0
  110. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +79 -0
  111. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -0
  112. package/Samples~/DI/VContainer.meta +8 -0
  113. package/Samples~/DI/Zenject/SampleInstaller.cs +65 -0
  114. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -0
  115. package/Samples~/DI/Zenject.meta +8 -0
  116. package/Samples~/DI.meta +8 -0
  117. package/Samples~/Mini Combat/README.md +5 -7
  118. package/Samples~/Mini Combat/Walkthrough.md +18 -24
  119. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +12 -2
  120. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -0
  121. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +444 -0
  122. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs.meta +11 -0
  123. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +94 -0
  124. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs.meta +11 -0
  125. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +395 -0
  126. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs.meta +11 -0
  127. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +77 -429
  128. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs +142 -0
  129. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs.meta +12 -0
  130. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +50 -0
  131. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef.meta +7 -0
  132. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +333 -0
  133. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs.meta +11 -0
  134. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +278 -0
  135. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs.meta +11 -0
  136. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +289 -0
  137. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs.meta +11 -0
  138. package/Tests/Runtime/Core/Extensions.meta +8 -0
  139. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs +57 -0
  140. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs.meta +11 -0
  141. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs +219 -0
  142. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs.meta +11 -0
  143. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs +204 -0
  144. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs.meta +11 -0
  145. package/Tests/Runtime/Core/MessagingTestBase.cs +4 -4
  146. package/Tests/Runtime/Core/NominalTests.cs +2 -2
  147. package/Tests/Runtime/Core/TypedShorthandTests.cs +2 -2
  148. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +1 -1
  149. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +2 -4
  150. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +162 -0
  151. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs.meta +11 -0
  152. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset +16 -0
  153. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset.meta +8 -0
  154. package/Tests/Runtime/Integrations/Reflex/Resources.meta +8 -0
  155. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +27 -0
  156. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef.meta +7 -0
  157. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  158. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +140 -0
  159. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs.meta +11 -0
  160. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +37 -0
  161. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef.meta +7 -0
  162. package/Tests/Runtime/Integrations/VContainer.meta +8 -0
  163. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +37 -0
  164. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef.meta +7 -0
  165. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +140 -0
  166. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs.meta +11 -0
  167. package/Tests/Runtime/Integrations/Zenject.meta +8 -0
  168. package/Tests/Runtime/Integrations.meta +8 -0
  169. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +1 -1
  170. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +1 -1
  171. package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +1 -1
  172. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +64 -0
  173. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs.meta +12 -0
  174. package/Tests/Runtime/TestUtilities.meta +9 -0
  175. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +57 -0
  176. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs.meta +11 -0
  177. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +107 -0
  178. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs.meta +12 -0
  179. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +210 -0
  180. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs.meta +12 -0
  181. package/Tests/Runtime/Unity.meta +9 -0
  182. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +3 -1
  183. package/package.json +1 -1
@@ -0,0 +1,407 @@
1
+ # Runtime Message Bus Configuration
2
+
3
+ This guide covers how to configure message buses at runtime and retarget existing registrations. These features enable advanced scenarios like dependency injection, testing with isolated buses, and dynamic reconfiguration of messaging hierarchies.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Runtime Message Bus Configuration](#runtime-message-bus-configuration)
8
+ - [When You Need This](#when-you-need-this)
9
+ - [Global Message Bus Management](#global-message-bus-management)
10
+ - [Re-binding Registrations](#re-binding-registrations)
11
+ - [Common Patterns](#common-patterns)
12
+
13
+ ---
14
+
15
+ ## When You Need This
16
+
17
+ You'll use runtime configuration when you need to:
18
+
19
+ - **Integrate with DI containers** — Replace the global bus with a container-managed instance
20
+ - **Isolate tests** — Ensure each test uses its own bus to prevent interference
21
+ - **Support multiple game modes** — Use different buses for different gameplay contexts (e.g., main game vs. mini-games)
22
+ - **Dynamically reconfigure components** — Change which bus a component listens to after it's been created
23
+
24
+ If you're just getting started with DxMessaging, you probably don't need these features yet. The default global bus works great for most scenarios.
25
+
26
+ ---
27
+
28
+ ## Global Message Bus Management
29
+
30
+ By default, DxMessaging creates a single process-wide message bus during static initialization. This bus is available through `MessageHandler.MessageBus` and works great for most scenarios.
31
+
32
+ ### Replacing the Global Bus
33
+
34
+ Use `SetGlobalMessageBus()` when you want to permanently replace the default bus:
35
+
36
+ ```csharp
37
+ using DxMessaging.Core;
38
+ using DxMessaging.Core.MessageBus;
39
+
40
+ // Create a custom bus (often from a DI container)
41
+ IMessageBus customBus = new MessageBus();
42
+
43
+ // Replace the global bus
44
+ MessageHandler.SetGlobalMessageBus(customBus);
45
+
46
+ // All new registrations will now use customBus
47
+ var handler = new MessageHandler(new InstanceId(1)) { active = true };
48
+ // handler.MessageBus is now customBus
49
+ ```
50
+
51
+ #### When to use this
52
+
53
+ - During application startup when integrating with DI containers
54
+ - When you want all message traffic to flow through a specific bus instance
55
+ - In integration tests that need complete control over message routing
56
+
57
+ **Important:** This permanently replaces the global bus for the lifetime of the application. All subsequent registrations will use the new bus unless explicitly configured otherwise.
58
+
59
+ ### Temporarily Overriding the Global Bus
60
+
61
+ Use `OverrideGlobalMessageBus()` when you want to temporarily replace the bus and automatically restore it later:
62
+
63
+ ```csharp
64
+ IMessageBus originalBus = MessageHandler.MessageBus;
65
+ IMessageBus temporaryBus = new MessageBus();
66
+
67
+ // Temporarily override
68
+ using (MessageHandler.OverrideGlobalMessageBus(temporaryBus))
69
+ {
70
+ // Inside this scope, MessageHandler.MessageBus returns temporaryBus
71
+ Assert.AreSame(temporaryBus, MessageHandler.MessageBus);
72
+
73
+ // Any message handlers created here use temporaryBus
74
+ var msg = new MyMessage();
75
+ msg.EmitUntargeted(); // Goes to temporaryBus
76
+ }
77
+
78
+ // Outside the scope, the original bus is restored
79
+ Assert.AreSame(originalBus, MessageHandler.MessageBus);
80
+ ```
81
+
82
+ #### When to use this
83
+
84
+ - In unit tests to isolate message traffic
85
+ - When temporarily redirecting messages for debugging or logging
86
+ - For scoped gameplay features that need their own message channel
87
+
88
+ **Pattern:** This returns an `IDisposable`, so you can use it with `using` statements for automatic cleanup. When the scope exits (either normally or via exception), the previous bus is restored.
89
+
90
+ ### Resetting to the Default Bus
91
+
92
+ Use `ResetGlobalMessageBus()` to restore the original startup bus:
93
+
94
+ ```csharp
95
+ // Replace the global bus
96
+ MessageHandler.SetGlobalMessageBus(containerBus);
97
+
98
+ // Later, restore the original default bus
99
+ MessageHandler.ResetGlobalMessageBus();
100
+
101
+ // MessageHandler.MessageBus is now back to the original startup bus
102
+ ```
103
+
104
+ #### When to use this
105
+
106
+ - After tests that called `SetGlobalMessageBus()`
107
+ - When tearing down a DI container and reverting to default behavior
108
+ - In development/debug scenarios where you want to reset state
109
+
110
+ ### Accessing the Original Startup Bus
111
+
112
+ `MessageHandler.InitialGlobalMessageBus` always returns the original bus that was created during static initialization, regardless of any calls to `SetGlobalMessageBus()`:
113
+
114
+ ```csharp
115
+ IMessageBus startupBus = MessageHandler.InitialGlobalMessageBus;
116
+
117
+ // Replace the global bus
118
+ MessageHandler.SetGlobalMessageBus(new MessageBus());
119
+
120
+ // InitialGlobalMessageBus is unchanged
121
+ Assert.AreSame(startupBus, MessageHandler.InitialGlobalMessageBus);
122
+
123
+ // But MessageBus returns the new bus
124
+ Assert.AreNotSame(startupBus, MessageHandler.MessageBus);
125
+ ```
126
+
127
+ #### When to use this
128
+
129
+ - In diagnostic tools that need a stable reference point
130
+ - When you want to compare against the original bus for debugging
131
+ - In tests that need to verify bus isolation while still accessing the original
132
+
133
+ ### Example: Bootstrapping a DI Container
134
+
135
+ Here's a complete example of integrating DxMessaging with a DI container:
136
+
137
+ ```csharp
138
+ using DxMessaging.Core;
139
+ using DxMessaging.Core.MessageBus;
140
+
141
+ public class GameBootstrapper
142
+ {
143
+ public void Bootstrap()
144
+ {
145
+ // Create container-managed bus
146
+ IMessageBus containerBus = new MessageBus();
147
+
148
+ // Register with container
149
+ container.RegisterInstance<IMessageBus>(containerBus);
150
+
151
+ // Replace global bus so all subsequent registrations use it
152
+ MessageHandler.SetGlobalMessageBus(containerBus);
153
+
154
+ // Now when MessagingComponents are created, they automatically
155
+ // use the container-managed bus
156
+ }
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Re-binding Registrations
163
+
164
+ Sometimes you need to change which bus a component listens to after it's already been set up. This is called "re-binding."
165
+
166
+ ### The MessageBusRebindMode Enum
167
+
168
+ When re-binding, you have two options:
169
+
170
+ #### PreserveRegistrations
171
+
172
+ Keeps existing active registrations on their current bus, but sets the specified bus for future registrations:
173
+
174
+ ```csharp
175
+ // Component is currently using busA
176
+ component.Configure(busA, MessageBusRebindMode.RebindActive);
177
+
178
+ // Later, switch to busB but preserve existing registrations
179
+ component.Configure(busB, MessageBusRebindMode.PreserveRegistrations);
180
+
181
+ // Existing handlers still listen on busA
182
+ // New registrations will use busB
183
+ ```
184
+
185
+ ##### When to use this
186
+
187
+ - When you want to gradually migrate a component to a new bus
188
+ - If you need to maintain backwards compatibility during refactoring
189
+ - When existing registrations must continue processing messages from their original source
190
+
191
+ #### RebindActive
192
+
193
+ Immediately moves all active registrations to the new bus:
194
+
195
+ ```csharp
196
+ // Component is listening on busA
197
+ component.Configure(busA, MessageBusRebindMode.RebindActive);
198
+
199
+ // Switch everything to busB
200
+ component.Configure(busB, MessageBusRebindMode.RebindActive);
201
+
202
+ // All handlers now listen on busB
203
+ // busA handlers are deregistered and re-registered on busB
204
+ ```
205
+
206
+ ##### When to use this
207
+
208
+ - When you want complete, immediate migration to a new bus
209
+ - In DI scenarios where the container provides a new bus instance
210
+ - When you need atomic switching without mixed-bus behavior
211
+
212
+ ### Retarget a Token Directly
213
+
214
+ You can also retarget individual `MessageRegistrationToken` instances:
215
+
216
+ ```csharp
217
+ using DxMessaging.Core;
218
+ using DxMessaging.Core.MessageBus;
219
+
220
+ IMessageBus busA = new MessageBus();
221
+ IMessageBus busB = new MessageBus();
222
+
223
+ var handler = new MessageHandler(new InstanceId(1), busA) { active = true };
224
+ var token = MessageRegistrationToken.Create(handler, busA);
225
+ token.RegisterUntargeted<MyMessage>(OnMessage);
226
+ token.Enable();
227
+
228
+ // Later, retarget to busB
229
+ token.RetargetMessageBus(busB, MessageBusRebindMode.RebindActive);
230
+
231
+ // All registrations are now on busB
232
+ ```
233
+
234
+ #### When to use this
235
+
236
+ - When you have direct access to a token and want fine-grained control
237
+ - In advanced scenarios like dynamic message routing or pooling
238
+ - When building custom messaging abstractions
239
+
240
+ ### Example: Scene-Specific Buses
241
+
242
+ Here's a practical example of using re-binding for scene isolation:
243
+
244
+ ```csharp
245
+ using DxMessaging.Core.MessageBus;
246
+ using DxMessaging.Unity;
247
+ using UnityEngine;
248
+
249
+ public class SceneMessagingManager : MonoBehaviour
250
+ {
251
+ private IMessageBus _sceneLocalBus;
252
+
253
+ private void Awake()
254
+ {
255
+ // Create a bus specific to this scene
256
+ _sceneLocalBus = new MessageBus();
257
+
258
+ // Find all messaging components in this scene
259
+ MessagingComponent[] components = FindObjectsOfType<MessagingComponent>();
260
+
261
+ // Retarget them to the scene-local bus
262
+ foreach (var component in components)
263
+ {
264
+ component.Configure(_sceneLocalBus, MessageBusRebindMode.RebindActive);
265
+ }
266
+ }
267
+
268
+ private void OnDestroy()
269
+ {
270
+ // When scene unloads, components are destroyed automatically
271
+ // No need to manually clean up registrations
272
+ }
273
+ }
274
+ ```
275
+
276
+ #### Why this is useful
277
+
278
+ - Messages sent in this scene won't leak to other scenes
279
+ - When the scene unloads, all message traffic stops cleanly
280
+ - Perfect for additive scene workflows or mini-games
281
+
282
+ ---
283
+
284
+ ## Common Patterns
285
+
286
+ ### Pattern 1: Test Isolation
287
+
288
+ Ensure each test has its own isolated bus:
289
+
290
+ ```csharp
291
+ using NUnit.Framework;
292
+ using DxMessaging.Core;
293
+ using DxMessaging.Core.MessageBus;
294
+
295
+ [TestFixture]
296
+ public class MySystemTests
297
+ {
298
+ private IMessageBus _testBus;
299
+
300
+ [SetUp]
301
+ public void SetUp()
302
+ {
303
+ // Create a fresh bus for each test
304
+ _testBus = new MessageBus();
305
+ MessageHandler.SetGlobalMessageBus(_testBus);
306
+ }
307
+
308
+ [TearDown]
309
+ public void TearDown()
310
+ {
311
+ // Restore the default bus
312
+ MessageHandler.ResetGlobalMessageBus();
313
+ }
314
+
315
+ [Test]
316
+ public void MyTest()
317
+ {
318
+ // This test uses _testBus exclusively
319
+ // No interference from other tests
320
+ }
321
+ }
322
+ ```
323
+
324
+ ### Pattern 2: Temporary Override with Automatic Cleanup
325
+
326
+ Use `using` statements for scoped overrides:
327
+
328
+ ```csharp
329
+ [Test]
330
+ public void TestWithIsolation()
331
+ {
332
+ IMessageBus isolatedBus = new MessageBus();
333
+
334
+ using (MessageHandler.OverrideGlobalMessageBus(isolatedBus))
335
+ {
336
+ // Test code here uses isolatedBus
337
+ var msg = new TestMessage();
338
+ msg.EmitUntargeted();
339
+
340
+ // Verify only this test's bus received the message
341
+ }
342
+
343
+ // Original bus automatically restored
344
+ }
345
+ ```
346
+
347
+ ### Pattern 3: DI Container Integration
348
+
349
+ Bootstrap with container-managed bus:
350
+
351
+ ```csharp
352
+ public class DependencyInjectionBootstrap
353
+ {
354
+ public void Initialize(IContainer container)
355
+ {
356
+ // Container creates the bus
357
+ IMessageBus containerBus = container.Resolve<IMessageBus>();
358
+
359
+ // Make it the global default
360
+ MessageHandler.SetGlobalMessageBus(containerBus);
361
+
362
+ // Now all MessagingComponents use the container bus by default
363
+ }
364
+ }
365
+ ```
366
+
367
+ ### Pattern 4: Dynamic Component Reconfiguration
368
+
369
+ Change a component's bus at runtime:
370
+
371
+ ```csharp
372
+ public class DynamicComponentManager
373
+ {
374
+ public void SwitchComponentToBus(MessagingComponent component, IMessageBus newBus)
375
+ {
376
+ // Immediately move all handlers to the new bus
377
+ component.Configure(newBus, MessageBusRebindMode.RebindActive);
378
+
379
+ // Component now listens on newBus
380
+ }
381
+ }
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Quick Reference
387
+
388
+ | API | Purpose | Use Case |
389
+ | ---------------------------------------------- | ------------------------------------------ | ------------------------------- |
390
+ | `MessageHandler.MessageBus` | Access current global bus | Normal message emission |
391
+ | `MessageHandler.InitialGlobalMessageBus` | Access original startup bus | Diagnostics, debugging |
392
+ | `MessageHandler.SetGlobalMessageBus(bus)` | Permanently replace global bus | DI integration, test setup |
393
+ | `MessageHandler.OverrideGlobalMessageBus(bus)` | Temporarily override (returns IDisposable) | Test isolation, scoped features |
394
+ | `MessageHandler.ResetGlobalMessageBus()` | Restore original startup bus | Test teardown, reset state |
395
+ | `component.Configure(bus, mode)` | Set component's bus | Component configuration |
396
+ | `token.RetargetMessageBus(bus, mode)` | Retarget a token | Fine-grained control |
397
+ | `MessageBusRebindMode.PreserveRegistrations` | Keep existing registrations on old bus | Gradual migration |
398
+ | `MessageBusRebindMode.RebindActive` | Move all registrations to new bus | Atomic switching |
399
+
400
+ ---
401
+
402
+ ## See Also
403
+
404
+ - **[Message Bus Providers](MessageBusProviders.md)** — ScriptableObject-based provider system for design-time configuration
405
+ - **[DI Integration Guides](Integrations/)** — Zenject, VContainer, and Reflex integration patterns
406
+ - **[Testing Guide](Testing.md)** — Comprehensive testing patterns with DxMessaging
407
+ - **[Back to Documentation Hub](Index.md)** — Browse all docs
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 47ac7e57ecec8284f8b542d4142e521b
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -5,7 +5,8 @@ Unity‑centric helpers make registration lifecycles explicit and safe.
5
5
  MessagingComponent
6
6
 
7
7
  - Attach to any GameObject that will send or receive messages.
8
- - Creates a perowner `MessageHandler` and offers `Create(this)` to get a `MessageRegistrationToken`.
8
+ - Creates a per-owner `MessageHandler` and offers `Create(this)` to get a `MessageRegistrationToken`.
9
+ - Call `Configure(IMessageBus, MessageBusRebindMode)` before `Create` if you want the component to use a custom bus (e.g., one resolved from a DI container). Passing `MessageBusRebindMode.RebindActive` migrates current registrations; `PreserveRegistrations` defers the swap until the next enable.
9
10
  - Optional: set `emitMessagesWhenDisabled` if you need to emit while disabled.
10
11
 
11
12
  MessageAwareComponent
@@ -13,6 +14,7 @@ MessageAwareComponent
13
14
  - Derive for a batteries‑included pattern; it manages a token for you.
14
15
  - Override `RegisterMessageHandlers()` to stage registrations.
15
16
  - The token is enabled/disabled with the component’s enable state.
17
+ - Call `ConfigureMessageBus(IMessageBus, MessageBusRebindMode)` before `base.Awake()` (or shortly after via a DI bootstrapper) to ensure the token is created against your container-provided bus.
16
18
 
17
19
  ```csharp
18
20
  using DxMessaging.Unity;