You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -19,125 +19,153 @@ Please read the [Introduction](intro.md) before reading this provider documentat
19
19
20
20
## Introduction
21
21
22
-
The Memory transport provider can be used for internal communication within the same process. It is the simplest transport provider and does not require any external messaging infrastructure.
22
+
The **Memory transport provider** enables message-based communication within a single process. It’s the simplest transport option in SlimMessageBus and doesn’t require any external infrastructure like Kafka or Azure Service Bus.
23
23
24
-
> Since messages are passed in memory and never persisted, they will be lost if the application process terminates while consuming these messages.
24
+
> ⚠️ Messages are passed entirely in memory and are never persisted. If the application process terminates while messages are in-flight, those messages will be lost.
25
25
26
-
Good use case for inmemory communication is:
26
+
**Common use cases for in-memory transport include:**
27
27
28
-
- to integrate the domain layer with other application layers via domain events pattern,
29
-
- to implement mediator pattern (when combined with [interceptors](intro.md#interceptors)),
30
-
- to run unit tests against application code that normally runs with an out of process transport provider (Kafka, Azure Service Bus, etc),
31
-
- to start simple messaging without having to provision messaging infrastructure, but when time comes reconfigure SMB to leverage messaging infrastructure.
28
+
- Integrating the domain layer with other application layers using the **domain events** pattern.
29
+
- Implementing the **mediator pattern** (especially when combined with [interceptors](intro.md#interceptors)).
30
+
- Writing **unit tests** for messaging logic without requiring a full transport setup.
31
+
- Starting with messaging quickly and easily — no infrastructure required — and switching to an external provider later by reconfiguring SlimMessageBus.
32
+
33
+
---
32
34
33
35
## Configuration
34
36
35
-
The memory transport is configured using the `.WithProviderMemory()`:
37
+
First, install the NuGet package:
36
38
37
-
```cs
39
+
```bash
40
+
dotnet add package SlimMessageBus.Host.Memory
41
+
```
42
+
43
+
Then, configure the memory transport using `.WithProviderMemory()`:
> 💡 No serializer is needed by default for the in-memory transport — unless you [opt in to serialization](#serialization).
56
+
47
57
### Virtual Topics
48
58
49
-
Unlike other transport providers, memory transport does not have true notion of topics (or queues). However, it is still required to use topic names. This is required, so that the bus knows on which virtual topic to deliver the message to, and from what virtual topic to consume from.
59
+
The in-memory transport doesn't use real topics or queues like other transport providers. However, **virtual topic names** are still required. These names allow the bus to correctly route messages to and from the appropriate consumers.
50
60
51
-
The consumer configuration side should use `.Topic()` to set the virtual topic name:
61
+
On the **consumer side**, use `.Topic()` to specify the virtual topic:
52
62
53
-
```cs
54
-
//declare that OrderSubmittedEvent will be consumed
> The virtual topic name can be any string. It helps to connect the relevant producers and consumers together.
77
+
> Virtual topic names can be any string, as long as producers and consumers use the same value. This is what links them together internally.
68
78
69
79
### Auto Declaration
70
80
71
-
For bus configuration, we can leverage `.AutoDeclareFrom()` methodto discover all the consumers (`IConsumer<T>`) and handlers (`IRequestHandler<T,R>`) types in an assembly and auto declare the respective producers and consumers/handlers in the bus.
72
-
This can be useful to auto declare all of the domain event handlers in an application layer.
81
+
You can simplify your bus configuration using the `.AutoDeclareFrom()` method, which scans an assembly to automatically discover all consumers (`IConsumer<T>`) and handlers (`IRequestHandler<T,R>`). It then declares the corresponding producers and consumers/handlers on the bus for you.
82
+
This is especially useful for automatically registering all domain event handlers within an application layer.
By default, the virtual topic name is derived from the message type’s [`FullName`](https://learn.microsoft.com/en-us/dotnet/api/system.type.fullname?view=net-9.0) — meaning it includes both the namespace and any outer class names.
119
+
You can customize this by providing your own `messageTypeToTopicConverter`:
The virtual topic name will be derived from the message type name by default. This can be customized by passing an additional parameter to the `AutoDeclareFrom()` method.
128
+
Using `.AutoDeclareFrom()` is highly recommended when configuring the memory bus, as it ensures producers and consumers are kept up to date automatically as your application evolves.
103
129
104
-
Using `.AutoDeclareFrom()`to configure the memory bus is recommended, as it will declare the producers and consumers automatically as consumer types are added over time.
130
+
> Note: `.AutoDeclareFrom()`and `.AutoDeclareFromAssemblyContaining<T>()` will also register discovered consumers and handlers into the Microsoft Dependency Injection (MSDI) container. [Learn more here](intro.md#autoregistration-of-consumers-interceptors-and-configurators).
105
131
106
-
> The `.AutoDeclareFrom()` and `.AutoDeclareFromAssembly<T>()` will also register the found consumers/handlers into MSDI (see [here](intro.md#autoregistration-of-consumers-interceptors-and-configurators)).
132
+
#### Polymorphic Message Support
107
133
108
-
#### Polymorphic message support
134
+
The memory transport supports **polymorphic message types**—messages that share a common base class or interface—via the `AutoDeclareFrom()` method.
109
135
110
-
The polymorphic message types (message that share a common ancestry) are supported by the `AutoDeclareFrom()`:
136
+
Here’s how it works:
111
137
112
-
- for every consumer / handler implementation found it analyzes the message type inheritance tree,
113
-
- it declares a producer in the bus for the oldest ancestor of the message type hierarchy,
114
-
- it declares a consumer in the bus for the oldest ancestor message type and within that, configures a consumer for derived message type,
115
-
- topic names are derived from the ancestor message type.
138
+
- For each discovered consumer or handler, the message type's inheritance hierarchy is analyzed.
139
+
- A producer is registered for the **root ancestor** of the message type.
140
+
- A consumer is registered for the **root ancestor**, and configured to handle the specific **derived** message type.
141
+
- The topic name is based on the **ancestor message type**, ensuring consistent routing for all related messages.
142
+
143
+
This allows you to declare base-level contracts and consume polymorphic messages seamlessly.
116
144
117
145
### Serialization
118
146
119
-
Since messages are passed within the same process, serializing and deserializing them is redundant. Also, disabling serialization gives a performance improvement.
147
+
Because messages are exchanged entirely within the same process, serialization is typically unnecessary—and skipping it can yield performance benefits.
120
148
121
-
> Serialization is disabled by default for memory bus.
149
+
> 🟢 **Serialization is disabled by default** for the memory transport.
122
150
123
-
Serialization can be disabled or enabled:
151
+
However, you can opt-in to serialization if needed—for example, to simulate production scenarios during testing or to enforce immutability:
124
152
125
-
```cs
153
+
```csharp
126
154
services.AddSlimMessageBus(mbb=>
127
155
{
128
-
// Bus configuration happens here (...)
129
-
mbb.WithProviderMemory(cfg=>
130
-
{
131
-
// Serialize the domain events instead of passing the same instance across to handlers/consumers
132
-
cfg.EnableMessageSerialization=true
133
-
});
134
-
//Serializer not needed if EnableMessageSerialization = false
135
-
mbb.AddJsonSerializer();
156
+
mbb.WithProviderMemory(cfg=>
157
+
{
158
+
// Enable serialization for in-memory messages
159
+
cfg.EnableMessageSerialization=true;
160
+
});
161
+
162
+
//Required only if serialization is enabled
163
+
mbb.AddJsonSerializer();
136
164
});
137
165
```
138
166
139
-
> When serialization is disabled for in memory passed messages, the exact same object instance send by the producer will be received by the consumer. Therefore state changes on the consumer end will be visible by the producer.
140
-
> Consider making the messages immutable (read only) in that case.
167
+
> ⚠️ When serialization is disabled, the **same object instance** sent by the producer is received by the consumer.
168
+
> This means any changes made by the consumer will be visible to the producer. To avoid side effects, it’s recommended to use **immutable message types** in such cases.
0 commit comments