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,97 @@
1
+ namespace DxMessaging.Unity
2
+ {
3
+ using System;
4
+ using DxMessaging.Core.MessageBus;
5
+ using UnityEngine;
6
+ using UnityEngine.Serialization;
7
+
8
+ /// <summary>
9
+ /// Serializable handle that references a <see cref="ScriptableMessageBusProvider"/> or runtime provider.
10
+ /// </summary>
11
+ [Serializable]
12
+ public struct MessageBusProviderHandle
13
+ {
14
+ [FormerlySerializedAs("providerAsset")]
15
+ [SerializeField]
16
+ private ScriptableMessageBusProvider _provider;
17
+
18
+ [NonSerialized]
19
+ private IMessageBusProvider _runtimeProvider;
20
+
21
+ /// <summary>
22
+ /// Initializes a new instance referencing the supplied provider asset.
23
+ /// </summary>
24
+ /// <param name="provider">Serialized provider asset.</param>
25
+ public MessageBusProviderHandle(ScriptableMessageBusProvider provider)
26
+ {
27
+ _provider = provider;
28
+ _runtimeProvider = provider;
29
+ }
30
+
31
+ /// <summary>
32
+ /// Gets an empty handle.
33
+ /// </summary>
34
+ public static MessageBusProviderHandle Empty => default;
35
+
36
+ /// <summary>
37
+ /// Creates a handle that wraps a runtime-only provider instance.
38
+ /// </summary>
39
+ /// <param name="provider">Runtime provider.</param>
40
+ /// <returns>Handle referencing the provider.</returns>
41
+ public static MessageBusProviderHandle FromProvider(IMessageBusProvider provider)
42
+ {
43
+ MessageBusProviderHandle handle = default;
44
+ handle._runtimeProvider = provider;
45
+ return handle;
46
+ }
47
+
48
+ /// <summary>
49
+ /// Associates the handle with a runtime provider, returning a new handle.
50
+ /// </summary>
51
+ /// <param name="provider">Provider to associate.</param>
52
+ /// <returns>New handle referencing the provider.</returns>
53
+ public MessageBusProviderHandle WithRuntimeProvider(IMessageBusProvider provider)
54
+ {
55
+ MessageBusProviderHandle handle = this;
56
+ handle._runtimeProvider = provider;
57
+ return handle;
58
+ }
59
+
60
+ /// <summary>
61
+ /// Attempts to resolve the provider referenced by this handle.
62
+ /// </summary>
63
+ /// <param name="provider">Resolved provider.</param>
64
+ /// <returns><c>true</c> when a provider exists; otherwise <c>false</c>.</returns>
65
+ public bool TryGetProvider(out IMessageBusProvider provider)
66
+ {
67
+ if (_runtimeProvider != null)
68
+ {
69
+ provider = _runtimeProvider;
70
+ return true;
71
+ }
72
+
73
+ if (_provider != null)
74
+ {
75
+ provider = _provider;
76
+ return true;
77
+ }
78
+
79
+ provider = null;
80
+ return false;
81
+ }
82
+
83
+ /// <summary>
84
+ /// Resolves the effective message bus for this handle.
85
+ /// </summary>
86
+ /// <returns>The resolved bus, or <see langword="null"/> if none available.</returns>
87
+ public IMessageBus ResolveBus()
88
+ {
89
+ if (!TryGetProvider(out IMessageBusProvider provider))
90
+ {
91
+ return null;
92
+ }
93
+
94
+ return provider.Resolve();
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 6c23b0c0c26d4bafbf0036ad36345a63
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
12
+
@@ -3,6 +3,7 @@ namespace DxMessaging.Unity
3
3
  using System;
4
4
  using System.Collections.Generic;
5
5
  using Core;
6
+ using Core.MessageBus;
6
7
  using UnityEngine;
7
8
  using UnityEngine.Serialization;
8
9
 
@@ -26,11 +27,37 @@ namespace DxMessaging.Unity
26
27
  [FormerlySerializedAs("_emitMessagesWhenDisabled")]
27
28
  public bool emitMessagesWhenDisabled;
28
29
 
30
+ [SerializeField]
31
+ private bool autoConfigureSerializedProviderOnAwake;
32
+
33
+ [SerializeField]
34
+ private MessageBusProviderHandle _serializedProviderHandle;
35
+
29
36
  private MessageHandler _messageHandler;
30
37
 
38
+ [NonSerialized]
39
+ private IMessageBus _messageBusOverride;
40
+
41
+ [NonSerialized]
42
+ private IMessageBusProvider _messageBusProvider;
43
+
31
44
  internal readonly Dictionary<MonoBehaviour, MessageRegistrationToken> _registeredListeners =
32
45
  new();
33
46
 
47
+ /// <summary>
48
+ /// Creates a <see cref="IMessageRegistrationBuilder"/> aligned with this component's configured bus or provider.
49
+ /// </summary>
50
+ public IMessageRegistrationBuilder CreateRegistrationBuilder()
51
+ {
52
+ IMessageBusProvider provider = ResolveRegistrationProvider();
53
+ if (provider != null)
54
+ {
55
+ return new MessageRegistrationBuilder(provider);
56
+ }
57
+
58
+ return new MessageRegistrationBuilder();
59
+ }
60
+
34
61
  /// <summary>
35
62
  /// Creates (or returns existing) registration token for the given component on this GameObject.
36
63
  /// </summary>
@@ -45,10 +72,10 @@ namespace DxMessaging.Unity
45
72
  throw new ArgumentNullException(nameof(listener));
46
73
  }
47
74
 
48
- if (gameObject.GetInstanceID() != listener.gameObject.GetInstanceID())
75
+ if (gameObject != listener.gameObject)
49
76
  {
50
77
  throw new ArgumentException(
51
- $"Cannot create a RegistrationToken without an valid owner. {listener.gameObject.GetInstanceID()}."
78
+ $"Cannot create a RegistrationToken without a mismatched owner. {listener.gameObject} != existing {gameObject}."
52
79
  );
53
80
  }
54
81
 
@@ -59,11 +86,15 @@ namespace DxMessaging.Unity
59
86
  )
60
87
  )
61
88
  {
62
- MessagingDebug.Log(
63
- LogLevel.Warn,
64
- "Ignoring double RegistrationToken request for {0}.",
65
- listener
66
- );
89
+ if (MessagingDebug.enabled)
90
+ {
91
+ MessagingDebug.Log(
92
+ LogLevel.Warn,
93
+ "Ignoring double RegistrationToken request for {0}.",
94
+ listener
95
+ );
96
+ }
97
+
67
98
  return createdToken;
68
99
  }
69
100
 
@@ -73,6 +104,66 @@ namespace DxMessaging.Unity
73
104
  return createdToken;
74
105
  }
75
106
 
107
+ /// <summary>
108
+ /// Overrides the default message bus used when new handlers are created.
109
+ /// </summary>
110
+ /// <param name="messageBus">Message bus to prefer. Pass <c>null</c> to fall back to the global bus.</param>
111
+ /// <param name="rebindMode">Controls whether existing registrations move to the new bus immediately.</param>
112
+ public void Configure(IMessageBus messageBus, MessageBusRebindMode rebindMode)
113
+ {
114
+ _messageBusOverride = messageBus;
115
+ _messageBusProvider = null;
116
+ _serializedProviderHandle = MessageBusProviderHandle.Empty;
117
+ ApplyMessageBusConfiguration(rebindMode);
118
+ }
119
+
120
+ /// <summary>
121
+ /// Configures the component to resolve message buses via the supplied provider.
122
+ /// </summary>
123
+ /// <param name="messageBusProvider">Provider to use for subsequent handler/token resolution.</param>
124
+ /// <param name="rebindMode">Controls whether existing listeners should migrate immediately.</param>
125
+ public void Configure(
126
+ IMessageBusProvider messageBusProvider,
127
+ MessageBusRebindMode rebindMode
128
+ )
129
+ {
130
+ _messageBusProvider = messageBusProvider;
131
+ if (messageBusProvider != null)
132
+ {
133
+ _messageBusOverride = null;
134
+ }
135
+
136
+ _serializedProviderHandle =
137
+ messageBusProvider != null
138
+ ? MessageBusProviderHandle.FromProvider(messageBusProvider)
139
+ : MessageBusProviderHandle.Empty;
140
+ ApplyMessageBusConfiguration(rebindMode);
141
+ }
142
+
143
+ /// <summary>
144
+ /// Configures the component using a serialized provider handle.
145
+ /// </summary>
146
+ /// <param name="providerHandle">Handle that resolves the preferred provider.</param>
147
+ /// <param name="rebindMode">Controls whether existing listeners should migrate immediately.</param>
148
+ public void Configure(
149
+ MessageBusProviderHandle providerHandle,
150
+ MessageBusRebindMode rebindMode
151
+ )
152
+ {
153
+ _serializedProviderHandle = providerHandle;
154
+ if (providerHandle.TryGetProvider(out IMessageBusProvider provider))
155
+ {
156
+ _messageBusProvider = provider;
157
+ _messageBusOverride = null;
158
+ }
159
+ else
160
+ {
161
+ _messageBusProvider = null;
162
+ }
163
+
164
+ ApplyMessageBusConfiguration(rebindMode);
165
+ }
166
+
76
167
  /// <summary>
77
168
  /// Releases the registration token previously created for <paramref name="listener"/>.
78
169
  /// </summary>
@@ -83,7 +174,7 @@ namespace DxMessaging.Unity
83
174
  /// </remarks>
84
175
  public bool Release(MonoBehaviour listener)
85
176
  {
86
- if (listener is null)
177
+ if (listener == null)
87
178
  {
88
179
  return false;
89
180
  }
@@ -102,6 +193,16 @@ namespace DxMessaging.Unity
102
193
  /// </summary>
103
194
  private void Awake()
104
195
  {
196
+ if (
197
+ autoConfigureSerializedProviderOnAwake
198
+ && _messageBusOverride == null
199
+ && _messageBusProvider == null
200
+ && _serializedProviderHandle.TryGetProvider(out IMessageBusProvider provider)
201
+ )
202
+ {
203
+ _messageBusProvider = provider;
204
+ }
205
+
105
206
  _messageHandler ??= CreateMessageHandler();
106
207
  }
107
208
 
@@ -143,7 +244,72 @@ namespace DxMessaging.Unity
143
244
  /// </summary>
144
245
  private MessageHandler CreateMessageHandler()
145
246
  {
146
- return new MessageHandler(gameObject) { active = true };
247
+ IMessageBus resolvedBus = ResolveConfiguredBus();
248
+ MessageHandler handler = new(gameObject, resolvedBus) { active = true };
249
+ return handler;
250
+ }
251
+
252
+ private void ApplyMessageBusConfiguration(MessageBusRebindMode rebindMode)
253
+ {
254
+ IMessageBus resolvedBus = ResolveConfiguredBus();
255
+ _messageHandler?.SetDefaultMessageBus(resolvedBus);
256
+ if (_registeredListeners.Count == 0)
257
+ {
258
+ return;
259
+ }
260
+
261
+ MessageBusRebindMode effectiveMode =
262
+ #pragma warning disable CS0618 // Type or member is obsolete
263
+ rebindMode == MessageBusRebindMode.Unknown
264
+ #pragma warning restore CS0618 // Type or member is obsolete
265
+ ? MessageBusRebindMode.RebindActive
266
+ : rebindMode;
267
+
268
+ foreach (MessageRegistrationToken token in _registeredListeners.Values)
269
+ {
270
+ token.RetargetMessageBus(resolvedBus, effectiveMode);
271
+ }
272
+ }
273
+
274
+ private IMessageBus ResolveConfiguredBus()
275
+ {
276
+ if (_messageBusOverride != null)
277
+ {
278
+ return _messageBusOverride;
279
+ }
280
+
281
+ if (_messageBusProvider != null)
282
+ {
283
+ IMessageBus providedBus = _messageBusProvider.Resolve();
284
+ if (providedBus != null)
285
+ {
286
+ return providedBus;
287
+ }
288
+ }
289
+
290
+ return null;
291
+ }
292
+
293
+ private IMessageBusProvider ResolveRegistrationProvider()
294
+ {
295
+ if (_messageBusProvider != null)
296
+ {
297
+ return _messageBusProvider;
298
+ }
299
+
300
+ if (
301
+ _serializedProviderHandle.TryGetProvider(out IMessageBusProvider providerFromHandle)
302
+ )
303
+ {
304
+ return providerFromHandle;
305
+ }
306
+
307
+ if (_messageBusOverride != null)
308
+ {
309
+ return new FixedMessageBusProvider(_messageBusOverride);
310
+ }
311
+
312
+ return null;
147
313
  }
148
314
  }
149
315
  }
@@ -0,0 +1,120 @@
1
+ namespace DxMessaging.Unity
2
+ {
3
+ using System.Collections.Generic;
4
+ using Core.MessageBus;
5
+ using UnityEngine;
6
+
7
+ /// <summary>
8
+ /// Applies a shared message bus or provider to <see cref="MessagingComponent"/> instances in the hierarchy.
9
+ /// </summary>
10
+ [DisallowMultipleComponent]
11
+ public sealed class MessagingComponentInstaller : MonoBehaviour
12
+ {
13
+ [SerializeField]
14
+ private bool applyOnAwake = true;
15
+
16
+ [SerializeField]
17
+ private bool includeInactive = true;
18
+
19
+ [SerializeField]
20
+ private MessageBusProviderHandle providerHandle;
21
+
22
+ [SerializeReference]
23
+ private IMessageBus explicitMessageBus;
24
+
25
+ private readonly List<MessagingComponent> _messagingComponents = new();
26
+
27
+ private void Awake()
28
+ {
29
+ if (applyOnAwake)
30
+ {
31
+ ApplyConfiguration();
32
+ }
33
+ }
34
+
35
+ /// <summary>
36
+ /// Applies the configured bus or provider to all <see cref="MessagingComponent"/> descendants.
37
+ /// </summary>
38
+ public void ApplyConfiguration()
39
+ {
40
+ GetComponentsInChildren<MessagingComponent>(includeInactive, _messagingComponents);
41
+
42
+ if (_messagingComponents.Count == 0)
43
+ {
44
+ return;
45
+ }
46
+
47
+ if (providerHandle.TryGetProvider(out IMessageBusProvider provider))
48
+ {
49
+ foreach (MessagingComponent component in _messagingComponents)
50
+ {
51
+ component.Configure(providerHandle, MessageBusRebindMode.RebindActive);
52
+ }
53
+
54
+ return;
55
+ }
56
+
57
+ if (explicitMessageBus != null)
58
+ {
59
+ foreach (MessagingComponent component in _messagingComponents)
60
+ {
61
+ component.Configure(explicitMessageBus, MessageBusRebindMode.RebindActive);
62
+ }
63
+
64
+ return;
65
+ }
66
+
67
+ Debug.LogWarning(
68
+ $"{nameof(MessagingComponentInstaller)} on {name} has no provider or explicit message bus configured.",
69
+ this
70
+ );
71
+ }
72
+
73
+ /// <summary>
74
+ /// Creates a registration builder that mirrors the installer configuration.
75
+ /// </summary>
76
+ public IMessageRegistrationBuilder CreateRegistrationBuilder()
77
+ {
78
+ IMessageBusProvider provider = ResolveEffectiveProvider();
79
+ if (provider != null)
80
+ {
81
+ return new MessageRegistrationBuilder(provider);
82
+ }
83
+
84
+ if (explicitMessageBus != null)
85
+ {
86
+ return new MessageRegistrationBuilder(
87
+ new FixedMessageBusProvider(explicitMessageBus)
88
+ );
89
+ }
90
+
91
+ return new MessageRegistrationBuilder();
92
+ }
93
+
94
+ /// <summary>
95
+ /// Assigns the provider handle that will be used for subsequent applications.
96
+ /// </summary>
97
+ public void SetProvider(MessageBusProviderHandle handle)
98
+ {
99
+ providerHandle = handle;
100
+ }
101
+
102
+ /// <summary>
103
+ /// Assigns an explicit message bus that overrides the provider handle when present.
104
+ /// </summary>
105
+ public void SetExplicitMessageBus(IMessageBus messageBus)
106
+ {
107
+ explicitMessageBus = messageBus;
108
+ }
109
+
110
+ private IMessageBusProvider ResolveEffectiveProvider()
111
+ {
112
+ if (providerHandle.TryGetProvider(out IMessageBusProvider provider))
113
+ {
114
+ return provider;
115
+ }
116
+
117
+ return null;
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 3a28d2b5a3c74e44b922cb972782f7d1
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,14 @@
1
+ namespace DxMessaging.Unity
2
+ {
3
+ using DxMessaging.Core.MessageBus;
4
+ using UnityEngine;
5
+
6
+ /// <summary>
7
+ /// Base <see cref="ScriptableObject"/> that resolves an <see cref="IMessageBus"/> instance.
8
+ /// </summary>
9
+ public abstract class ScriptableMessageBusProvider : ScriptableObject, IMessageBusProvider
10
+ {
11
+ /// <inheritdoc />
12
+ public abstract IMessageBus Resolve();
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 9a0b0701f2dbb8946b7bc27f68c1cc55
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,98 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!1 &100000
4
+ GameObject:
5
+ m_ObjectHideFlags: 0
6
+ m_CorrespondingSourceObject: {fileID: 0}
7
+ m_PrefabInstance: {fileID: 0}
8
+ m_PrefabAsset: {fileID: 0}
9
+ serializedVersion: 6
10
+ m_Component:
11
+ - component: {fileID: 400000}
12
+ - component: {fileID: 11400000}
13
+ m_Layer: 0
14
+ m_Name: MessagingInstallerSample
15
+ m_TagString: Untagged
16
+ m_Icon: {fileID: 0}
17
+ m_NavMeshLayer: 0
18
+ m_StaticEditorFlags: 0
19
+ m_IsActive: 1
20
+ --- !u!4 &400000
21
+ Transform:
22
+ m_ObjectHideFlags: 0
23
+ m_CorrespondingSourceObject: {fileID: 0}
24
+ m_PrefabInstance: {fileID: 0}
25
+ m_PrefabAsset: {fileID: 0}
26
+ m_GameObject: {fileID: 100000}
27
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
28
+ m_LocalPosition: {x: 0, y: 0, z: 0}
29
+ m_LocalScale: {x: 1, y: 1, z: 1}
30
+ m_ConstrainProportionsScale: 0
31
+ m_Children:
32
+ - {fileID: 400001}
33
+ m_Father: {fileID: 0}
34
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
35
+ --- !u!114 &11400000
36
+ MonoBehaviour:
37
+ m_ObjectHideFlags: 0
38
+ m_CorrespondingSourceObject: {fileID: 0}
39
+ m_PrefabInstance: {fileID: 0}
40
+ m_PrefabAsset: {fileID: 0}
41
+ m_GameObject: {fileID: 100000}
42
+ m_Enabled: 1
43
+ m_EditorHideFlags: 0
44
+ m_Script: {fileID: 11500000, guid: 3a28d2b5a3c74e44b922cb972782f7d1, type: 3}
45
+ m_Name:
46
+ m_EditorClassIdentifier:
47
+ applyOnAwake: 1
48
+ includeInactive: 1
49
+ providerHandle:
50
+ providerAsset: {fileID: 11400000, guid: a4f3a0b76ff44160a7453a58aa654a3a, type: 2}
51
+ explicitMessageBus: {}
52
+ --- !u!1 &100001
53
+ GameObject:
54
+ m_ObjectHideFlags: 0
55
+ m_CorrespondingSourceObject: {fileID: 0}
56
+ m_PrefabInstance: {fileID: 0}
57
+ m_PrefabAsset: {fileID: 0}
58
+ serializedVersion: 6
59
+ m_Component:
60
+ - component: {fileID: 400001}
61
+ - component: {fileID: 11400001}
62
+ m_Layer: 0
63
+ m_Name: MessagingListener
64
+ m_TagString: Untagged
65
+ m_Icon: {fileID: 0}
66
+ m_NavMeshLayer: 0
67
+ m_StaticEditorFlags: 0
68
+ m_IsActive: 1
69
+ --- !u!4 &400001
70
+ Transform:
71
+ m_ObjectHideFlags: 0
72
+ m_CorrespondingSourceObject: {fileID: 0}
73
+ m_PrefabInstance: {fileID: 0}
74
+ m_PrefabAsset: {fileID: 0}
75
+ m_GameObject: {fileID: 100001}
76
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
77
+ m_LocalPosition: {x: 0, y: 0, z: 0}
78
+ m_LocalScale: {x: 1, y: 1, z: 1}
79
+ m_ConstrainProportionsScale: 0
80
+ m_Children: []
81
+ m_Father: {fileID: 400000}
82
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
83
+ --- !u!114 &11400001
84
+ MonoBehaviour:
85
+ m_ObjectHideFlags: 0
86
+ m_CorrespondingSourceObject: {fileID: 0}
87
+ m_PrefabInstance: {fileID: 0}
88
+ m_PrefabAsset: {fileID: 0}
89
+ m_GameObject: {fileID: 100001}
90
+ m_Enabled: 1
91
+ m_EditorHideFlags: 0
92
+ m_Script: {fileID: 11500000, guid: 98ea04ea326660845ba49942dacbf907, type: 3}
93
+ m_Name:
94
+ m_EditorClassIdentifier:
95
+ emitMessagesWhenDisabled: 0
96
+ autoConfigureSerializedProviderOnAwake: 0
97
+ _serializedProviderHandle:
98
+ providerAsset: {fileID: 0}
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 2d5f318e8b9a4a559ef886795bc8a1dd
3
+ PrefabImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: e4e0e7c97cb24f4fa4a8718f2768e8c4
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,14 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!114 &11400000
4
+ MonoBehaviour:
5
+ m_ObjectHideFlags: 0
6
+ m_CorrespondingSourceObject: {fileID: 0}
7
+ m_PrefabInstance: {fileID: 0}
8
+ m_PrefabAsset: {fileID: 0}
9
+ m_GameObject: {fileID: 0}
10
+ m_Enabled: 1
11
+ m_EditorHideFlags: 0
12
+ m_Script: {fileID: 11500000, guid: 689f1e1a8d9f4c34f9e3ab4e3f94ec37, type: 3}
13
+ m_Name: GlobalMessageBusProvider
14
+ m_EditorClassIdentifier:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: a4f3a0b76ff44160a7453a58aa654a3a
3
+ NativeFormatImporter:
4
+ externalObjects: {}
5
+ mainObjectFileID: 11400000
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,14 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!114 &11400000
4
+ MonoBehaviour:
5
+ m_ObjectHideFlags: 0
6
+ m_CorrespondingSourceObject: {fileID: 0}
7
+ m_PrefabInstance: {fileID: 0}
8
+ m_PrefabAsset: {fileID: 0}
9
+ m_GameObject: {fileID: 0}
10
+ m_Enabled: 1
11
+ m_EditorHideFlags: 0
12
+ m_Script: {fileID: 11500000, guid: 1f3f2efbb7f4441ebde8b418d178885a, type: 3}
13
+ m_Name: InitialGlobalMessageBusProvider
14
+ m_EditorClassIdentifier:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 9224435f740044bebddcdabe6a8ecc87
3
+ NativeFormatImporter:
4
+ externalObjects: {}
5
+ mainObjectFileID: 11400000
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 6b1ab34b9b8c4886ab4e6a5f5c23af62
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant: