com.wallstop-studios.dxmessaging 2.0.0-rc27.3.1 → 2.1.0

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 (185) 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 +1352 -141
  10. package/Docs/Compatibility.md +27 -0
  11. package/Docs/DesignAndArchitecture.md +41 -34
  12. package/Docs/EmitShorthands.md +34 -0
  13. package/Docs/GettingStarted.md +84 -17
  14. package/Docs/Helpers.md +1 -1
  15. package/Docs/Index.md +28 -25
  16. package/Docs/Install.md +29 -6
  17. package/Docs/Integrations/Reflex.md +292 -0
  18. package/Docs/Integrations/Reflex.md.meta +7 -0
  19. package/Docs/Integrations/VContainer.md +324 -0
  20. package/Docs/Integrations/VContainer.md.meta +7 -0
  21. package/Docs/Integrations/Zenject.md +333 -0
  22. package/Docs/Integrations/Zenject.md.meta +7 -0
  23. package/{Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta → Docs/Integrations.meta} +2 -1
  24. package/Docs/InterceptorsAndOrdering.md +371 -17
  25. package/Docs/ListeningPatterns.md +206 -0
  26. package/Docs/MessageBusProviders.md +496 -0
  27. package/Docs/MessageBusProviders.md.meta +7 -0
  28. package/Docs/MessageTypes.md +27 -0
  29. package/Docs/MigrationGuide.md +45 -0
  30. package/Docs/Overview.md +114 -20
  31. package/Docs/Patterns.md +327 -2
  32. package/Docs/Performance.md +9 -9
  33. package/Docs/QuickReference.md +31 -0
  34. package/Docs/RuntimeConfiguration.md +407 -0
  35. package/Docs/RuntimeConfiguration.md.meta +7 -0
  36. package/Docs/UnityIntegration.md +3 -1
  37. package/Docs/VisualGuide.md +281 -167
  38. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  39. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +3 -3
  40. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
  41. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +2 -2
  42. package/Editor/Analyzers/System.Collections.Immutable.dll +0 -0
  43. package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
  44. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
  45. package/Editor/CustomEditors/MessagingComponentEditor.cs +15 -6
  46. package/README.md +388 -67
  47. package/Runtime/AssemblyInfo.cs +4 -0
  48. package/Runtime/Core/Extensions/MessageBusExtensions.cs +253 -0
  49. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -0
  50. package/Runtime/Core/Extensions/MessageExtensions.cs +137 -89
  51. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs +23 -0
  52. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -0
  53. package/Runtime/Core/MessageBus/IMessageBusProvider.cs +14 -0
  54. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -0
  55. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +18 -0
  56. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -0
  57. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs +26 -0
  58. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -0
  59. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +383 -0
  60. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -0
  61. package/Runtime/Core/MessageHandler.cs +198 -27
  62. package/Runtime/Core/MessageRegistrationToken.cs +67 -25
  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 +164 -2
  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 +81 -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 +67 -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 +86 -28
  118. package/Samples~/Mini Combat/Walkthrough.md +41 -25
  119. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +12 -2
  120. package/Samples~/UI Buttons + Inspector/README.md +55 -12
  121. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -0
  122. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +444 -0
  123. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs.meta +11 -0
  124. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +94 -0
  125. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs.meta +11 -0
  126. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +395 -0
  127. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs.meta +11 -0
  128. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +77 -429
  129. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs +142 -0
  130. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs.meta +12 -0
  131. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +50 -0
  132. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef.meta +7 -0
  133. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +333 -0
  134. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs.meta +11 -0
  135. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +278 -0
  136. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs.meta +11 -0
  137. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +289 -0
  138. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs.meta +11 -0
  139. package/Tests/Runtime/Core/Extensions.meta +8 -0
  140. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs +57 -0
  141. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs.meta +11 -0
  142. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs +219 -0
  143. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs.meta +11 -0
  144. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs +204 -0
  145. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs.meta +11 -0
  146. package/Tests/Runtime/Core/MessagingTestBase.cs +4 -4
  147. package/Tests/Runtime/Core/NominalTests.cs +2 -2
  148. package/Tests/Runtime/Core/SourceGeneratorNestedTests.cs +1 -1
  149. package/Tests/Runtime/Core/TypedShorthandTests.cs +2 -2
  150. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +1 -1
  151. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +2 -4
  152. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +162 -0
  153. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs.meta +11 -0
  154. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset +16 -0
  155. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset.meta +8 -0
  156. package/Tests/Runtime/Integrations/Reflex/Resources.meta +8 -0
  157. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +27 -0
  158. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef.meta +7 -0
  159. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  160. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +140 -0
  161. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs.meta +11 -0
  162. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +37 -0
  163. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef.meta +7 -0
  164. package/Tests/Runtime/Integrations/VContainer.meta +8 -0
  165. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +37 -0
  166. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef.meta +7 -0
  167. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +140 -0
  168. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs.meta +11 -0
  169. package/Tests/Runtime/Integrations/Zenject.meta +8 -0
  170. package/Tests/Runtime/Integrations.meta +8 -0
  171. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +1 -1
  172. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +1 -1
  173. package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +1 -1
  174. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +64 -0
  175. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs.meta +12 -0
  176. package/Tests/Runtime/TestUtilities.meta +9 -0
  177. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +57 -0
  178. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs.meta +11 -0
  179. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +107 -0
  180. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs.meta +12 -0
  181. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +210 -0
  182. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs.meta +12 -0
  183. package/Tests/Runtime/Unity.meta +9 -0
  184. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +3 -1
  185. package/package.json +1 -1
@@ -0,0 +1,292 @@
1
+ # DxMessaging + Reflex
2
+
3
+ [← Back to Integrations Overview](../README.md#-integrations)
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ **Reflex** is a minimal, lightweight dependency injection framework for Unity with blazing-fast performance. DxMessaging integrates seamlessly with Reflex, allowing you to:
10
+
11
+ - **Inject `IMessageBus`** in any class with minimal overhead
12
+ - **Use DI for construction** + DxMessaging for events (best of both worlds)
13
+ - **Minimal API surface** — easy to learn, easy to use
14
+ - **High performance** — Reflex + DxMessaging = minimal allocations
15
+
16
+ **Why combine DI + Messaging?** Use constructor injection for service dependencies (repositories, managers) and messaging for reactive events (damage taken, item collected). Reflex's minimal API makes integration simple and straightforward.
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ### Prerequisites
23
+
24
+ - DxMessaging installed via UPM
25
+ - Reflex installed (`gustavopsantos/Reflex`) via source or UPM
26
+
27
+ ### 1. Create a Reflex Installer
28
+
29
+ ```csharp
30
+ using DxMessaging.Core.MessageBus;
31
+ using Reflex.Core;
32
+
33
+ public sealed class DxMessagingInstaller : Installer
34
+ {
35
+ public override void InstallBindings(ContainerDescriptor descriptor)
36
+ {
37
+ // Bind MessageBus as both concrete and interface
38
+ descriptor.AddSingleton(typeof(MessageBus), typeof(MessageBus));
39
+ descriptor.AddSingleton(typeof(IMessageBus), c => c.Resolve<MessageBus>());
40
+
41
+ // Optional: Enable automatic IMessageRegistrationBuilder binding
42
+ // Requires REFLEX_PRESENT define (auto-added by DxMessaging when Reflex detected)
43
+ #if REFLEX_PRESENT
44
+ descriptor.AddMessageRegistrationBuilder();
45
+ #endif
46
+ }
47
+ }
48
+ ```
49
+
50
+ #### Add to your scene
51
+
52
+ 1. Create a `SceneContext` or `ProjectContext` in your scene
53
+ 1. Add `DxMessagingInstaller` to the installers list
54
+ 1. Reflex will now inject `IMessageBus` automatically
55
+
56
+ ---
57
+
58
+ ## Usage Patterns
59
+
60
+ ### Pattern 1: Inject into Plain Classes (Recommended for Services)
61
+
62
+ Use `IMessageRegistrationBuilder` to create message handlers in non-MonoBehaviour classes:
63
+
64
+ ```csharp
65
+ using DxMessaging.Core.MessageBus;
66
+ using DxMessaging.Core.Attributes;
67
+
68
+ // Define a message
69
+ [DxUntargetedMessage]
70
+ [DxAutoConstructor]
71
+ public readonly partial struct PlayerDamaged
72
+ {
73
+ public readonly int damage;
74
+ }
75
+
76
+ // Service that listens to messages
77
+ public sealed class DamageService
78
+ {
79
+ private readonly MessageRegistrationLease _lease;
80
+
81
+ // Builder is injected automatically when using the installer
82
+ public DamageService(IMessageRegistrationBuilder registrationBuilder)
83
+ {
84
+ var options = new MessageRegistrationBuildOptions
85
+ {
86
+ Configure = token =>
87
+ {
88
+ _ = token.RegisterUntargeted<PlayerDamaged>(OnPlayerDamaged);
89
+ }
90
+ };
91
+
92
+ _lease = registrationBuilder.Build(options);
93
+ }
94
+
95
+ public void Initialize()
96
+ {
97
+ _lease.Activate(); // Start listening
98
+ }
99
+
100
+ public void Dispose()
101
+ {
102
+ _lease.Dispose(); // Clean up
103
+ }
104
+
105
+ private static void OnPlayerDamaged(ref PlayerDamaged message)
106
+ {
107
+ UnityEngine.Debug.Log($"Player took {message.damage} damage!");
108
+ }
109
+ }
110
+ ```
111
+
112
+ #### Register the service in your installer
113
+
114
+ ```csharp
115
+ public override void InstallBindings(ContainerDescriptor descriptor)
116
+ {
117
+ descriptor.AddSingleton<DamageService>();
118
+ // Call Initialize() from a bootstrap MonoBehaviour
119
+ }
120
+ ```
121
+
122
+ **Note:** Reflex doesn't have lifecycle interfaces like `IInitializable`. Call `Initialize()` and `Dispose()` manually from a controlling MonoBehaviour or bootstrap script.
123
+
124
+ ---
125
+
126
+ ### Pattern 2: Configure MessagingComponents (For Existing MonoBehaviours)
127
+
128
+ ```csharp
129
+ using DxMessaging.Core.MessageBus;
130
+ using DxMessaging.Unity;
131
+ using Reflex.Attributes;
132
+ using UnityEngine;
133
+
134
+ [DisallowMultipleComponent]
135
+ [RequireComponent(typeof(MessagingComponent))]
136
+ public sealed class MessagingComponentConfigurator : MonoBehaviour
137
+ {
138
+ [Inject]
139
+ private IMessageBus _messageBus;
140
+
141
+ private void Awake()
142
+ {
143
+ GetComponent<MessagingComponent>().Configure(
144
+ _messageBus,
145
+ MessageBusRebindMode.RebindActive
146
+ );
147
+ }
148
+ }
149
+ ```
150
+
151
+ #### Usage
152
+
153
+ 1. Add `MessagingComponentConfigurator` alongside any `MessagingComponent` in your prefabs
154
+ 1. Reflex will inject the bus in `Awake()` before handlers are registered
155
+ 1. Your message handlers now use the container-managed bus
156
+
157
+ ---
158
+
159
+ ### Pattern 3: Inject IMessageBus Directly
160
+
161
+ For simple emission without listening, inject `IMessageBus` directly:
162
+
163
+ ```csharp
164
+ public sealed class GameBootstrap : MonoBehaviour
165
+ {
166
+ [Inject]
167
+ private IMessageBus _messageBus;
168
+
169
+ private void Start()
170
+ {
171
+ var message = new GameStarted();
172
+ _messageBus.EmitUntargeted(ref message);
173
+ }
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Advanced: Object Pooling
180
+
181
+ When using object pooling with Reflex:
182
+
183
+ ```csharp
184
+ public sealed class EnemyPool
185
+ {
186
+ private readonly Container _container;
187
+ private readonly Queue<Enemy> _pool = new();
188
+
189
+ public EnemyPool(Container container)
190
+ {
191
+ _container = container;
192
+ }
193
+
194
+ public Enemy Spawn()
195
+ {
196
+ Enemy enemy;
197
+ if (_pool.Count > 0)
198
+ {
199
+ enemy = _pool.Dequeue();
200
+ }
201
+ else
202
+ {
203
+ enemy = Object.Instantiate(enemyPrefab);
204
+ _container.Inject(enemy); // Inject dependencies
205
+ }
206
+ return enemy;
207
+ }
208
+
209
+ public void Return(Enemy enemy)
210
+ {
211
+ _pool.Enqueue(enemy);
212
+ }
213
+ }
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Testing with Reflex
219
+
220
+ ### Unit Tests
221
+
222
+ ```csharp
223
+ using DxMessaging.Core.MessageBus;
224
+ using Reflex.Core;
225
+ using NUnit.Framework;
226
+
227
+ [TestFixture]
228
+ public class DamageServiceTests
229
+ {
230
+ [Test]
231
+ public void Initialize_ListensToMessages()
232
+ {
233
+ // Arrange
234
+ var builder = new ContainerBuilder();
235
+ var bus = new MessageBus();
236
+ builder.AddSingleton<IMessageBus>(bus);
237
+ builder.AddSingleton<DamageService>();
238
+ var container = builder.Build();
239
+
240
+ bool messageReceived = false;
241
+ var handler = new MessageHandler(new InstanceId(1), bus) { active = true };
242
+ var token = MessageRegistrationToken.Create(handler, bus);
243
+ _ = token.RegisterUntargeted<PlayerDamaged>(ref msg => messageReceived = true);
244
+ token.Enable();
245
+
246
+ // Act
247
+ var service = container.Resolve<DamageService>();
248
+ service.Initialize();
249
+ var message = new PlayerDamaged(25);
250
+ bus.EmitUntargeted(ref message);
251
+
252
+ // Assert
253
+ Assert.IsTrue(messageReceived);
254
+ }
255
+ }
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Checklist
261
+
262
+ ### Initial Setup
263
+
264
+ - [ ] Install DxMessaging and Reflex
265
+ - [ ] Create `DxMessagingInstaller` with bus bindings
266
+ - [ ] Add installer to your `SceneContext` or `ProjectContext`
267
+ - [ ] Add `#if REFLEX_PRESENT` check and call `descriptor.AddMessageRegistrationBuilder()`
268
+
269
+ ### Integration
270
+
271
+ - [ ] Use `IMessageRegistrationBuilder` in plain classes
272
+ - [ ] Call `Initialize()` and `Dispose()` manually from a bootstrap script
273
+ - [ ] Add `MessagingComponentConfigurator` to prefabs with `MessagingComponent`
274
+ - [ ] Replace `MessageHandler.MessageBus` references with injected `IMessageBus`
275
+
276
+ ### Pooling
277
+
278
+ - [ ] Use `container.Inject(instance)` for pooled objects
279
+ - [ ] Ensure injection happens before message handlers are registered
280
+
281
+ ### Testing
282
+
283
+ - [ ] Create isolated `ContainerBuilder` instances in tests
284
+ - [ ] Use `builder.AddSingleton<IMessageBus>(new MessageBus())` for test buses
285
+
286
+ ---
287
+
288
+ ## Next Steps
289
+
290
+ - **[Zenject Integration](Zenject.md)** — Full-featured DI with extensive Unity support
291
+ - **[VContainer Integration](VContainer.md)** — Lightweight alternative with scoped lifetimes
292
+ - **[Back to Documentation Hub](../Index.md)** — Browse all docs
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 42871dfbdf4daa14c80c05d47f380c96
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,324 @@
1
+ # DxMessaging + VContainer
2
+
3
+ [← Back to Integrations Overview](../README.md#-integrations)
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ **VContainer** is a fast, lightweight dependency injection framework for Unity with minimal overhead. DxMessaging integrates seamlessly with VContainer, allowing you to:
10
+
11
+ - **Inject `IMessageBus`** in any class with deterministic lifetimes
12
+ - **Create per-scope buses** for scene isolation (perfect for additive scenes)
13
+ - **Use DI for construction** + DxMessaging for events (best of both worlds)
14
+ - **Minimal performance overhead** — VContainer + DxMessaging = blazing fast
15
+
16
+ **Why combine DI + Messaging?** Use constructor injection for service dependencies (repositories, managers) and messaging for reactive events (damage taken, item collected). VContainer's scoped lifetimes make it perfect for per-scene message buses.
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ### Prerequisites
23
+
24
+ - DxMessaging installed via UPM
25
+ - VContainer installed (Git URL or OpenUPM)
26
+
27
+ ### 1. Create a LifetimeScope with DxMessaging
28
+
29
+ ```csharp
30
+ using DxMessaging.Core.MessageBus;
31
+ using UnityEngine;
32
+ using VContainer;
33
+ using VContainer.Unity;
34
+
35
+ public sealed class MessagingLifetimeScope : LifetimeScope
36
+ {
37
+ protected override void Configure(IContainerBuilder builder)
38
+ {
39
+ // Register MessageBus as both concrete and interface
40
+ builder.Register<MessageBus>(Lifetime.Singleton).As<IMessageBus>();
41
+
42
+ // Optional: Enable automatic IMessageRegistrationBuilder binding
43
+ // Requires VCONTAINER_PRESENT define (auto-added by DxMessaging when VContainer detected)
44
+ #if VCONTAINER_PRESENT
45
+ builder.RegisterMessageRegistrationBuilder();
46
+ #endif
47
+ }
48
+ }
49
+ ```
50
+
51
+ #### Add to your scene
52
+
53
+ 1. Create an empty GameObject in your scene
54
+ 1. Add the `MessagingLifetimeScope` component
55
+ 1. This creates a singleton bus for the entire scene
56
+
57
+ **Tip:** Use `Lifetime.Singleton` for project-wide buses, or `Lifetime.Scoped` for isolated scene/feature buses.
58
+
59
+ ---
60
+
61
+ ## Usage Patterns
62
+
63
+ ### Pattern 1: Inject into Plain Classes (Recommended for Services)
64
+
65
+ Use `IMessageRegistrationBuilder` to create message handlers in non-MonoBehaviour classes:
66
+
67
+ ```csharp
68
+ using DxMessaging.Core.MessageBus;
69
+ using DxMessaging.Core.Attributes;
70
+ using VContainer.Unity;
71
+
72
+ // Define a message
73
+ [DxUntargetedMessage]
74
+ [DxAutoConstructor]
75
+ public readonly partial struct PlayerSpawned
76
+ {
77
+ public readonly int playerId;
78
+ }
79
+
80
+ // Service that listens to messages
81
+ public sealed class PlayerService : IStartable, IDisposable
82
+ {
83
+ private readonly MessageRegistrationLease _lease;
84
+
85
+ // Builder is injected automatically when using the scope
86
+ public PlayerService(IMessageRegistrationBuilder registrationBuilder)
87
+ {
88
+ var options = new MessageRegistrationBuildOptions
89
+ {
90
+ Configure = token =>
91
+ {
92
+ _ = token.RegisterUntargeted<PlayerSpawned>(OnPlayerSpawned);
93
+ }
94
+ };
95
+
96
+ _lease = registrationBuilder.Build(options);
97
+ }
98
+
99
+ public void Start()
100
+ {
101
+ _lease.Activate(); // Start listening when container starts
102
+ }
103
+
104
+ public void Dispose()
105
+ {
106
+ _lease.Dispose(); // Clean up when container disposes
107
+ }
108
+
109
+ private static void OnPlayerSpawned(ref PlayerSpawned message)
110
+ {
111
+ UnityEngine.Debug.Log($"Player {message.playerId} spawned!");
112
+ }
113
+ }
114
+ ```
115
+
116
+ #### Register the service in your scope
117
+
118
+ ```csharp
119
+ protected override void Configure(IContainerBuilder builder)
120
+ {
121
+ builder.Register<MessageBus>(Lifetime.Singleton).As<IMessageBus>();
122
+ #if VCONTAINER_PRESENT
123
+ builder.RegisterMessageRegistrationBuilder();
124
+ #endif
125
+
126
+ // Register your service
127
+ builder.RegisterEntryPoint<PlayerService>();
128
+ }
129
+ ```
130
+
131
+ ---
132
+
133
+ ### Pattern 2: Configure MessagingComponents (For Existing MonoBehaviours)
134
+
135
+ ```csharp
136
+ using DxMessaging.Core.MessageBus;
137
+ using DxMessaging.Unity;
138
+ using UnityEngine;
139
+ using VContainer;
140
+ using VContainer.Unity;
141
+
142
+ [RequireComponent(typeof(MessagingComponent))]
143
+ public sealed class MessagingComponentConfigurator : MonoBehaviour, IStartable
144
+ {
145
+ [Inject]
146
+ private readonly IMessageBus _messageBus;
147
+
148
+ private MessagingComponent _messagingComponent;
149
+
150
+ private void Awake()
151
+ {
152
+ _messagingComponent = GetComponent<MessagingComponent>();
153
+ }
154
+
155
+ public void Start()
156
+ {
157
+ _messagingComponent.Configure(_messageBus, MessageBusRebindMode.RebindActive);
158
+ }
159
+ }
160
+ ```
161
+
162
+ #### Usage
163
+
164
+ 1. Add `MessagingComponentConfigurator` alongside any `MessagingComponent` in your prefabs
165
+ 1. VContainer will inject the bus via `IStartable.Start()` before handlers are registered
166
+ 1. Your message handlers now use the container-managed bus
167
+
168
+ ---
169
+
170
+ ### Pattern 3: Inject IMessageBus Directly
171
+
172
+ For simple emission without listening, inject `IMessageBus` directly:
173
+
174
+ ```csharp
175
+ public sealed class GameInitializer : IStartable
176
+ {
177
+ private readonly IMessageBus _messageBus;
178
+
179
+ public GameInitializer(IMessageBus messageBus)
180
+ {
181
+ _messageBus = messageBus;
182
+ }
183
+
184
+ public void Start()
185
+ {
186
+ var message = new GameStarted();
187
+ _messageBus.EmitUntargeted(ref message);
188
+ }
189
+ }
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Advanced: Scene Scopes and Isolation
195
+
196
+ VContainer's scoped lifetimes make it perfect for per-scene message buses. This is useful for additive scenes or isolated gameplay features:
197
+
198
+ ```csharp
199
+ using DxMessaging.Core.MessageBus;
200
+ using VContainer;
201
+ using VContainer.Unity;
202
+
203
+ public sealed class LevelLoader
204
+ {
205
+ private readonly LifetimeScope _parentScope;
206
+
207
+ public LevelLoader(LifetimeScope parentScope)
208
+ {
209
+ _parentScope = parentScope;
210
+ }
211
+
212
+ public LifetimeScope LoadLevel(GameObject lifetimeScopePrefab)
213
+ {
214
+ // Create a child scope with its own MessageBus
215
+ return _parentScope.CreateChildFromPrefab(lifetimeScopePrefab, builder =>
216
+ {
217
+ builder.Register<MessageBus>(Lifetime.Singleton).As<IMessageBus>();
218
+ #if VCONTAINER_PRESENT
219
+ builder.RegisterMessageRegistrationBuilder();
220
+ #endif
221
+ });
222
+ }
223
+ }
224
+ ```
225
+
226
+ ### Benefits
227
+
228
+ - Each scene gets its own isolated message bus
229
+ - Messages don't leak between scenes
230
+ - Perfect for multiplayer lobbies, mini-games, or feature-scoped events
231
+
232
+ ---
233
+
234
+ ## Testing with VContainer
235
+
236
+ ### Unit Tests
237
+
238
+ ```csharp
239
+ using DxMessaging.Core.MessageBus;
240
+ using VContainer;
241
+ using VContainer.Unity;
242
+ using NUnit.Framework;
243
+
244
+ [TestFixture]
245
+ public class GameInitializerTests
246
+ {
247
+ [Test]
248
+ public void Initialize_EmitsGameStarted()
249
+ {
250
+ // Arrange
251
+ var builder = new ContainerBuilder();
252
+ var bus = new MessageBus();
253
+ builder.RegisterInstance<IMessageBus>(bus);
254
+ builder.RegisterEntryPoint<GameInitializer>();
255
+ var container = builder.Build();
256
+
257
+ bool messageReceived = false;
258
+ var handler = new MessageHandler(new InstanceId(1), bus) { active = true };
259
+ var token = MessageRegistrationToken.Create(handler, bus);
260
+ _ = token.RegisterUntargeted<GameStarted>(ref msg => messageReceived = true);
261
+ token.Enable();
262
+
263
+ // Act
264
+ container.Resolve<GameInitializer>().Start();
265
+
266
+ // Assert
267
+ Assert.IsTrue(messageReceived);
268
+ }
269
+ }
270
+ ```
271
+
272
+ ### Play-Mode Tests
273
+
274
+ For play-mode tests, create a temporary `LifetimeScope`:
275
+
276
+ ```csharp
277
+ [UnityTest]
278
+ public IEnumerator PlayMode_MessageBusIsolation()
279
+ {
280
+ // Create isolated scope for this test
281
+ var scope = LifetimeScope.Create(builder =>
282
+ {
283
+ builder.Register<MessageBus>(Lifetime.Singleton).As<IMessageBus>();
284
+ });
285
+
286
+ var bus = scope.Container.Resolve<IMessageBus>();
287
+ // ... test logic ...
288
+
289
+ scope.Dispose(); // Clean up
290
+ yield return null;
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ## Checklist
297
+
298
+ ### Initial Setup
299
+
300
+ - [ ] Install DxMessaging and VContainer
301
+ - [ ] Create `MessagingLifetimeScope` with `builder.Register<MessageBus>().As<IMessageBus>()`
302
+ - [ ] Add scope to your scene as a GameObject component
303
+ - [ ] Add `#if VCONTAINER_PRESENT` check and call `builder.RegisterMessageRegistrationBuilder()`
304
+
305
+ ### Integration
306
+
307
+ - [ ] Use `IMessageRegistrationBuilder` in plain classes with `IStartable`/`IDisposable`
308
+ - [ ] Add `MessagingComponentConfigurator` to prefabs with `MessagingComponent`
309
+ - [ ] Replace `MessageHandler.MessageBus` references with injected `IMessageBus`
310
+ - [ ] Consider using scoped buses for scene isolation
311
+
312
+ ### Testing
313
+
314
+ - [ ] Create isolated `ContainerBuilder` instances in tests
315
+ - [ ] Use `builder.RegisterInstance<IMessageBus>(new MessageBus())` for test buses
316
+ - [ ] Dispose scopes after tests to ensure clean teardown
317
+
318
+ ---
319
+
320
+ ## Next Steps
321
+
322
+ - **[Zenject Integration](Zenject.md)** — Full-featured DI with extensive Unity support
323
+ - **[Reflex Integration](Reflex.md)** — Minimal DI framework
324
+ - **[Back to Documentation Hub](../Index.md)** — Browse all docs
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 14b0f2e146fecb24eb5317b196d6af62
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant: