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,142 @@
1
+ namespace DxMessaging.Tests.Runtime.Benchmarks
2
+ {
3
+ using System;
4
+ using System.Diagnostics;
5
+ using DxMessaging.Core;
6
+ using DxMessaging.Core.Extensions;
7
+ using DxMessaging.Core.MessageBus;
8
+ using DxMessaging.Core.Messages;
9
+ using NUnit.Framework;
10
+
11
+ public sealed class ProviderResolutionBenchmarks : BenchmarkTestBase
12
+ {
13
+ private IMessageBus _originalBus;
14
+
15
+ [SetUp]
16
+ public void CaptureGlobalBus()
17
+ {
18
+ _originalBus = MessageHandler.MessageBus;
19
+ MessageHandler.ResetGlobalMessageBus();
20
+ }
21
+
22
+ [TearDown]
23
+ public void RestoreGlobalBus()
24
+ {
25
+ MessageHandler.SetGlobalMessageBus(_originalBus);
26
+ }
27
+
28
+ [Test]
29
+ public void ProviderResolutionPerformance()
30
+ {
31
+ string section = BenchmarkDocumentation.GetOperatingSystemSection();
32
+ BenchmarkSession session = new(section, "### ", Array.Empty<Func<string>>());
33
+
34
+ RunWithSession(
35
+ session,
36
+ () =>
37
+ {
38
+ TimeSpan timeout = TimeSpan.FromSeconds(2);
39
+
40
+ BenchmarkResult direct = RunBenchmark(timeout, useProvider: false);
41
+ BenchmarkResult provider = RunBenchmark(timeout, useProvider: true);
42
+
43
+ RecordBenchmark(
44
+ "DxMessaging (Untargeted) - Direct Bus",
45
+ direct.Count,
46
+ direct.Duration,
47
+ allocating: false
48
+ );
49
+ RecordBenchmark(
50
+ "DxMessaging (Untargeted) - Provider",
51
+ provider.Count,
52
+ provider.Duration,
53
+ allocating: false
54
+ );
55
+
56
+ double directOps = direct.OperationsPerSecond;
57
+ double providerOps = provider.OperationsPerSecond;
58
+ Assume.That(providerOps, Is.GreaterThan(0));
59
+
60
+ double slowdown = directOps / providerOps;
61
+ Assert.That(
62
+ slowdown,
63
+ Is.LessThanOrEqualTo(1.15d),
64
+ $"Provider path must remain within 15% of direct bus dispatch. Direct: {directOps:N0} ops/s, Provider: {providerOps:N0} ops/s."
65
+ );
66
+ }
67
+ );
68
+ }
69
+
70
+ private BenchmarkResult RunBenchmark(TimeSpan timeout, bool useProvider)
71
+ {
72
+ MessageBus bus = new();
73
+ MessageHandler handler = new(new InstanceId(5000), bus) { active = true };
74
+ MessageRegistrationToken token = MessageRegistrationToken.Create(handler, bus);
75
+ _ = token.RegisterUntargeted((ref BenchmarkUntargetedMessage _) => { });
76
+ token.Enable();
77
+
78
+ Stopwatch stopwatch = Stopwatch.StartNew();
79
+ int count = 0;
80
+ BenchmarkUntargetedMessage message = new(0);
81
+ IMessageBusProvider provider = useProvider ? new StaticMessageBusProvider(bus) : null;
82
+
83
+ while (stopwatch.Elapsed < timeout)
84
+ {
85
+ if (useProvider)
86
+ {
87
+ message.EmitUntargeted(messageBusProvider: provider);
88
+ }
89
+ else
90
+ {
91
+ message.EmitUntargeted(bus);
92
+ }
93
+
94
+ count++;
95
+ }
96
+
97
+ stopwatch.Stop();
98
+ token.Disable();
99
+
100
+ return new BenchmarkResult(count, stopwatch.Elapsed);
101
+ }
102
+
103
+ private readonly struct BenchmarkResult
104
+ {
105
+ internal BenchmarkResult(int count, TimeSpan duration)
106
+ {
107
+ Count = count;
108
+ Duration = duration;
109
+ }
110
+
111
+ internal int Count { get; }
112
+ internal TimeSpan Duration { get; }
113
+ internal double OperationsPerSecond =>
114
+ Duration.TotalSeconds <= 0 ? 0 : Count / Duration.TotalSeconds;
115
+ }
116
+
117
+ private sealed class StaticMessageBusProvider : IMessageBusProvider
118
+ {
119
+ private readonly IMessageBus _bus;
120
+
121
+ internal StaticMessageBusProvider(IMessageBus bus)
122
+ {
123
+ _bus = bus;
124
+ }
125
+
126
+ public IMessageBus Resolve()
127
+ {
128
+ return _bus;
129
+ }
130
+ }
131
+
132
+ private readonly struct BenchmarkUntargetedMessage : IUntargetedMessage
133
+ {
134
+ internal BenchmarkUntargetedMessage(int value)
135
+ {
136
+ Value = value;
137
+ }
138
+
139
+ internal int Value { get; }
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: e3285ba401ba49a4aa87a7a5609638c0
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
12
+
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks",
3
+ "rootNamespace": "DxMessaging.Tests.Runtime.Benchmarks",
4
+ "references": [
5
+ "UnityEngine.TestRunner",
6
+ "UnityEditor.TestRunner",
7
+ "WallstopStudios.DxMessaging",
8
+ "WallstopStudios.DxMessaging.Tests.Runtime",
9
+ "Unity.PerformanceTesting",
10
+ "Zenject",
11
+ "MessagePipe",
12
+ "UniRx",
13
+ "UniTask"
14
+ ],
15
+ "includePlatforms": [],
16
+ "excludePlatforms": [],
17
+ "allowUnsafeCode": false,
18
+ "overrideReferences": true,
19
+ "precompiledReferences": ["nunit.framework.dll"],
20
+ "autoReferenced": true,
21
+ "defineConstraints": ["UNITY_INCLUDE_TESTS"],
22
+ "versionDefines": [
23
+ {
24
+ "name": "com.cysharp.messagepipe",
25
+ "expression": "0.0.1",
26
+ "define": "MESSAGEPIPE_PRESENT"
27
+ },
28
+ {
29
+ "name": "com.neuecc.unirx",
30
+ "expression": "0.0.1",
31
+ "define": "UNIRX_PRESENT"
32
+ },
33
+ {
34
+ "name": "com.cysharp.unirx",
35
+ "expression": "0.0.1",
36
+ "define": "UNIRX_PRESENT"
37
+ },
38
+ {
39
+ "name": "com.svermeulen.extenject",
40
+ "expression": "0.0.1",
41
+ "define": "ZENJECT_PRESENT"
42
+ },
43
+ {
44
+ "name": "com.svermeulen.extenject",
45
+ "expression": "0.0.1",
46
+ "define": "ZENJECT_PRESENT"
47
+ }
48
+ ],
49
+ "noEngineReferences": false
50
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: bf76d018b2a2417c8deb1f803eedd719
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,333 @@
1
+ namespace DxMessaging.Tests.Runtime.Core
2
+ {
3
+ using System.Collections;
4
+ using System.Collections.Generic;
5
+ using DxMessaging.Core;
6
+ using DxMessaging.Core.Extensions;
7
+ using DxMessaging.Core.MessageBus;
8
+ using DxMessaging.Tests.Runtime.Scripts.Components;
9
+ using DxMessaging.Tests.Runtime.Scripts.Messages;
10
+ using DxMessaging.Unity;
11
+ using NUnit.Framework;
12
+ using UnityEngine;
13
+ using UnityEngine.TestTools;
14
+
15
+ public sealed class DefaultBusFallbackTests : MessagingTestBase
16
+ {
17
+ private readonly List<MessageRegistrationHandle> _handles = new();
18
+ private readonly List<MessageRegistrationToken> _tokens = new();
19
+
20
+ [TearDown]
21
+ public void TearDown()
22
+ {
23
+ foreach (var token in _tokens)
24
+ {
25
+ foreach (var handle in _handles)
26
+ {
27
+ token.RemoveRegistration(handle);
28
+ }
29
+ token.Disable();
30
+ }
31
+
32
+ _handles.Clear();
33
+ _tokens.Clear();
34
+ }
35
+
36
+ [Test]
37
+ public void HandlerUsesInjectedDefaultBusWhenTokenOmitsBus()
38
+ {
39
+ MessageBus customBus = new();
40
+ MessageHandler handler = new(new InstanceId(42), customBus) { active = true };
41
+ MessageRegistrationToken token = MessageRegistrationToken.Create(handler);
42
+ _tokens.Add(token);
43
+
44
+ int callCount = 0;
45
+ MessageRegistrationHandle handle = token.RegisterUntargeted<SimpleUntargetedMessage>(
46
+ _ => ++callCount
47
+ );
48
+ _handles.Add(handle);
49
+
50
+ token.Enable();
51
+
52
+ SimpleUntargetedMessage message = new();
53
+ message.EmitUntargeted(customBus);
54
+ Assert.AreEqual(
55
+ 1,
56
+ callCount,
57
+ "Handler should observe messages emitted through its injected bus."
58
+ );
59
+
60
+ message.EmitUntargeted();
61
+ Assert.AreEqual(
62
+ 1,
63
+ callCount,
64
+ "Handler should remain isolated from the global bus when using an injected default."
65
+ );
66
+ }
67
+
68
+ [Test]
69
+ public void HandlerUsesInjectedDefaultBusForTargetedMessages()
70
+ {
71
+ MessageBus customBus = new();
72
+ MessageHandler handler = new(new InstanceId(99), customBus) { active = true };
73
+ MessageRegistrationToken token = MessageRegistrationToken.Create(handler);
74
+ _tokens.Add(token);
75
+
76
+ InstanceId target = new(1234);
77
+ int callCount = 0;
78
+ MessageRegistrationHandle handle = token.RegisterTargeted<SimpleTargetedMessage>(
79
+ target,
80
+ _ => ++callCount
81
+ );
82
+ _handles.Add(handle);
83
+
84
+ token.Enable();
85
+
86
+ SimpleTargetedMessage message = new();
87
+ message.EmitTargeted(target, customBus);
88
+ Assert.AreEqual(
89
+ 1,
90
+ callCount,
91
+ "Targeted handlers should fire when messages emit on the injected bus."
92
+ );
93
+
94
+ message.EmitTargeted(target);
95
+ Assert.AreEqual(
96
+ 1,
97
+ callCount,
98
+ "Targeted handler should ignore global bus emissions when a default bus is injected."
99
+ );
100
+ }
101
+
102
+ [Test]
103
+ public void HandlerUsesInjectedDefaultBusForBroadcastMessages()
104
+ {
105
+ MessageBus customBus = new();
106
+ MessageHandler handler = new(new InstanceId(1337), customBus) { active = true };
107
+ MessageRegistrationToken token = MessageRegistrationToken.Create(handler);
108
+ _tokens.Add(token);
109
+
110
+ int callCount = 0;
111
+ MessageRegistrationHandle handle = token.RegisterBroadcastWithoutSource(
112
+ (ref InstanceId _, ref SimpleBroadcastMessage _) => ++callCount
113
+ );
114
+ _handles.Add(handle);
115
+
116
+ token.Enable();
117
+
118
+ SimpleBroadcastMessage message = new();
119
+ InstanceId source = new(777);
120
+ message.EmitBroadcast(source, customBus);
121
+ Assert.AreEqual(
122
+ 1,
123
+ callCount,
124
+ "Broadcast handlers should observe emissions on the injected bus."
125
+ );
126
+
127
+ message.EmitBroadcast(source);
128
+ Assert.AreEqual(
129
+ 1,
130
+ callCount,
131
+ "Broadcast handler should remain isolated from global emissions when using an injected default bus."
132
+ );
133
+ }
134
+
135
+ [UnityTest]
136
+ public IEnumerator MessagingComponentConfigureRebindsExistingHandlerToCustomBus()
137
+ {
138
+ MessageBus customBus = new();
139
+ GameObject go = new(
140
+ nameof(MessagingComponentConfigureRebindsExistingHandlerToCustomBus),
141
+ typeof(MessagingComponent),
142
+ typeof(ManualListenerComponent)
143
+ );
144
+ _spawned.Add(go);
145
+
146
+ MessagingComponent messagingComponent = go.GetComponent<MessagingComponent>();
147
+ messagingComponent.Configure(customBus, MessageBusRebindMode.RebindActive);
148
+
149
+ ManualListenerComponent listener = go.GetComponent<ManualListenerComponent>();
150
+ MessageRegistrationToken token = listener.RequestToken(messagingComponent);
151
+ _tokens.Add(token);
152
+
153
+ int callCount = 0;
154
+ MessageRegistrationHandle handle = token.RegisterUntargeted<SimpleUntargetedMessage>(
155
+ _ => ++callCount
156
+ );
157
+ _handles.Add(handle);
158
+ token.Enable();
159
+
160
+ SimpleUntargetedMessage message = new();
161
+ message.EmitUntargeted(customBus);
162
+ Assert.AreEqual(
163
+ 1,
164
+ callCount,
165
+ "Configure should redirect tokens to the provided MessageBus."
166
+ );
167
+
168
+ message.EmitUntargeted();
169
+ Assert.AreEqual(
170
+ 1,
171
+ callCount,
172
+ "Global emissions should not reach tokens configured to use a custom bus."
173
+ );
174
+ yield break;
175
+ }
176
+
177
+ [UnityTest]
178
+ public IEnumerator MessagingComponentConfigurePreserveDefersRebindUntilReenabled()
179
+ {
180
+ MessageBus initialBus = new();
181
+ MessageBus newBus = new();
182
+ GameObject go = new(
183
+ nameof(MessagingComponentConfigurePreserveDefersRebindUntilReenabled),
184
+ typeof(MessagingComponent),
185
+ typeof(ManualListenerComponent)
186
+ );
187
+ _spawned.Add(go);
188
+
189
+ MessagingComponent messagingComponent = go.GetComponent<MessagingComponent>();
190
+ messagingComponent.Configure(initialBus, MessageBusRebindMode.RebindActive);
191
+
192
+ ManualListenerComponent listener = go.GetComponent<ManualListenerComponent>();
193
+ MessageRegistrationToken token = listener.RequestToken(messagingComponent);
194
+ _tokens.Add(token);
195
+
196
+ int callCount = 0;
197
+ MessageRegistrationHandle handle = token.RegisterUntargeted<SimpleUntargetedMessage>(
198
+ _ => ++callCount
199
+ );
200
+ _handles.Add(handle);
201
+ token.Enable();
202
+
203
+ SimpleUntargetedMessage message = new();
204
+ message.EmitUntargeted(initialBus);
205
+ Assert.AreEqual(1, callCount, "Initial bus should deliver to the registered handler.");
206
+
207
+ messagingComponent.Configure(newBus, MessageBusRebindMode.PreserveRegistrations);
208
+
209
+ message.EmitUntargeted(newBus);
210
+ Assert.AreEqual(
211
+ 1,
212
+ callCount,
213
+ "Preserve mode should avoid rebinding active registrations immediately."
214
+ );
215
+
216
+ message.EmitUntargeted(initialBus);
217
+ Assert.AreEqual(
218
+ 2,
219
+ callCount,
220
+ "Handlers should continue observing the original bus until re-enabled."
221
+ );
222
+
223
+ token.Disable();
224
+ token.Enable();
225
+
226
+ message.EmitUntargeted(newBus);
227
+ Assert.AreEqual(
228
+ 3,
229
+ callCount,
230
+ "Re-enabling the token should rebind handlers to the new bus."
231
+ );
232
+
233
+ yield break;
234
+ }
235
+
236
+ [UnityTest]
237
+ public IEnumerator MessageAwareComponentConfigureMessageBusAppliesOverride()
238
+ {
239
+ MessageBus customBus = new();
240
+ GameObject go = new(
241
+ nameof(MessageAwareComponentConfigureMessageBusAppliesOverride),
242
+ typeof(MessagingComponent),
243
+ typeof(BusAwareComponent)
244
+ );
245
+ _spawned.Add(go);
246
+
247
+ BusAwareComponent component = go.GetComponent<BusAwareComponent>();
248
+ component.ConfigureMessageBus(customBus, MessageBusRebindMode.RebindActive);
249
+
250
+ yield return null;
251
+
252
+ SimpleUntargetedMessage message = new();
253
+ message.EmitUntargeted(customBus);
254
+ Assert.AreEqual(
255
+ 1,
256
+ component.Received,
257
+ "MessageAwareComponent should route through the configured bus."
258
+ );
259
+
260
+ message.EmitUntargeted();
261
+ Assert.AreEqual(
262
+ 1,
263
+ component.Received,
264
+ "Global bus should no longer deliver to the component after override."
265
+ );
266
+ }
267
+
268
+ [UnityTest]
269
+ public IEnumerator MessageAwareComponentConfigureMessageBusPreserveDefersUntilReenable()
270
+ {
271
+ MessageBus initialBus = new();
272
+ MessageBus newBus = new();
273
+ GameObject go = new(
274
+ nameof(MessageAwareComponentConfigureMessageBusPreserveDefersUntilReenable),
275
+ typeof(MessagingComponent),
276
+ typeof(BusAwareComponent)
277
+ );
278
+ _spawned.Add(go);
279
+
280
+ BusAwareComponent component = go.GetComponent<BusAwareComponent>();
281
+ component.ConfigureMessageBus(initialBus, MessageBusRebindMode.RebindActive);
282
+
283
+ yield return null;
284
+
285
+ SimpleUntargetedMessage message = new();
286
+ message.EmitUntargeted(initialBus);
287
+ Assert.AreEqual(
288
+ 1,
289
+ component.Received,
290
+ "Component should receive messages emitted via the initial bus."
291
+ );
292
+
293
+ component.ConfigureMessageBus(newBus, MessageBusRebindMode.PreserveRegistrations);
294
+
295
+ message.EmitUntargeted(newBus);
296
+ Assert.AreEqual(
297
+ 1,
298
+ component.Received,
299
+ "Preserve mode should not rebind active handlers immediately."
300
+ );
301
+
302
+ message.EmitUntargeted(initialBus);
303
+ Assert.AreEqual(
304
+ 2,
305
+ component.Received,
306
+ "Existing registrations should continue to observe the original bus."
307
+ );
308
+
309
+ component.Token.Disable();
310
+ component.Token.Enable();
311
+
312
+ message.EmitUntargeted(newBus);
313
+ Assert.AreEqual(
314
+ 3,
315
+ component.Received,
316
+ "Re-enabling the token should rebind handlers to the new bus."
317
+ );
318
+ }
319
+
320
+ private sealed class BusAwareComponent : MessageAwareComponent
321
+ {
322
+ internal int Received { get; private set; }
323
+
324
+ protected override bool RegisterForStringMessages => false;
325
+
326
+ protected override void RegisterMessageHandlers()
327
+ {
328
+ base.RegisterMessageHandlers();
329
+ _ = Token.RegisterUntargeted<SimpleUntargetedMessage>(_ => ++Received);
330
+ }
331
+ }
332
+ }
333
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: e054d054d78a4b0e8b607a1efa203420
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: