@@ -38,23 +38,7 @@ public class KurrentDBClientSerializationSettings {
38
38
/// </summary>
39
39
public IMessageTypeNamingStrategy ? MessageTypeNamingStrategy { get ; set ; }
40
40
41
- /// <summary>
42
- /// Allows to register mapping of CLR message types to their corresponding message type names used in serialized messages.
43
- /// </summary>
44
- public IDictionary < string , Type > MessageTypeMap { get ; set ; } = new Dictionary < string , Type > ( ) ;
45
-
46
- /// <summary>
47
- /// Registers CLR message types that can be appended to the specific stream category.
48
- /// Types will have message type names resolved based on the used <see cref="KurrentDB.Client.Core.Serialization.IMessageTypeNamingStrategy"/>
49
- /// </summary>
50
- public IDictionary < string , Type [ ] > CategoryMessageTypesMap { get ; set ; } = new Dictionary < string , Type [ ] > ( ) ;
51
-
52
- /// <summary>
53
- /// Specifies the CLR type that should be used when deserializing metadata for all events.
54
- /// When set, the client will attempt to deserialize event metadata into this type.
55
- /// If not provided, <see cref="Kurrent.Diagnostics.Tracing.TracingMetadata"/> will be used.
56
- /// </summary>
57
- public Type ? DefaultMetadataType { get ; set ; }
41
+ public MessageTypeMappingSettings MessageTypeMapping { get ; set ; } = new MessageTypeMappingSettings ( ) ;
58
42
59
43
/// <summary>
60
44
/// Creates a new instance of serialization settings with either default values or custom configuration.
@@ -181,113 +165,24 @@ IMessageTypeNamingStrategy messageTypeNamingStrategy
181
165
}
182
166
183
167
/// <summary>
184
- /// Associates a message type with a specific stream category to enable automatic deserialization.
185
- /// In event sourcing, streams are often prefixed with a category (e.g., "user-123", "order-456").
186
- /// This method tells the client which message types can appear in streams of a given category.
187
- /// </summary>
188
- /// <typeparam name="T">The event or message type that can appear in the category's streams.</typeparam>
189
- /// <param name="categoryName">The category prefix (e.g., "user", "order", "account").</param>
190
- /// <returns>The current instance for method chaining.</returns>
191
- /// <example>
192
- /// <code>
193
- /// // Register event types that can appear in user streams
194
- /// settings.RegisterMessageTypeForCategory<UserCreated>("user")
195
- /// .RegisterMessageTypeForCategory<UserUpdated>("user")
196
- /// .RegisterMessageTypeForCategory<UserDeleted>("user");
197
- /// </code>
198
- /// </example>
199
- public KurrentDBClientSerializationSettings RegisterMessageTypeForCategory < T > ( string categoryName ) =>
200
- RegisterMessageTypeForCategory ( categoryName , typeof ( T ) ) ;
201
-
202
- /// <summary>
203
- /// Registers multiple message types for a specific stream category.
204
- /// </summary>
205
- /// <param name="categoryName">The category name to register the types with.</param>
206
- /// <param name="types">The message types to register.</param>
207
- /// <returns>The current instance for method chaining.</returns>
208
- public KurrentDBClientSerializationSettings RegisterMessageTypeForCategory ( string categoryName , params Type [ ] types ) {
209
- CategoryMessageTypesMap [ categoryName ] = CategoryMessageTypesMap . TryGetValue ( categoryName , out var current )
210
- ? [ ..current , ..types ]
211
- : types ;
212
-
213
- return this ;
214
- }
215
-
216
- /// <summary>
217
- /// Maps a .NET type to a specific message type name that will be stored in the message metadata.
218
- /// This mapping is used during automatic deserialization, as it tells the client which CLR type
219
- /// to instantiate when encountering a message with a particular type name in the database.
220
- /// </summary>
221
- /// <typeparam name="T">The .NET type to register (typically a message class).</typeparam>
222
- /// <param name="typeName">The string identifier to use for this type in the database.</param>
223
- /// <returns>The current instance for method chaining.</returns>
224
- /// <remarks>
225
- /// The type name is often different from the .NET type name to support versioning and evolution
226
- /// of your domain model without breaking existing stored messages.
227
- /// </remarks>
228
- /// <example>
229
- /// <code>
230
- /// // Register me types with their corresponding type identifiers
231
- /// settings.RegisterMessageType<UserCreated>("user-created-v1")
232
- /// .RegisterMessageType<OrderPlaced>("order-placed-v2");
233
- /// </code>
234
- /// </example>
235
- public KurrentDBClientSerializationSettings RegisterMessageType < T > ( string typeName ) =>
236
- RegisterMessageType ( typeName , typeof ( T ) ) ;
237
-
238
- /// <summary>
239
- /// Registers a message type with a specific type name.
240
- /// </summary>
241
- /// <param name="type">The message type to register.</param>
242
- /// <param name="typeName">The type name to register for the message type.</param>
243
- /// <returns>The current instance for method chaining.</returns>
244
- public KurrentDBClientSerializationSettings RegisterMessageType ( string typeName , Type type ) {
245
- MessageTypeMap [ typeName ] = type ;
246
-
247
- return this ;
248
- }
249
-
250
- /// <summary>
251
- /// Registers multiple message types with their corresponding type names.
168
+ /// Configures which serialization format (JSON or binary) is used by default when writing messages
169
+ /// where the content type isn't explicitly specified. The default content type is "application/json"
252
170
/// </summary>
253
- /// <param name="typeMap">Dictionary mapping types to their type names. </param>
171
+ /// <param name="contentType">The serialization format content type</param>
254
172
/// <returns>The current instance for method chaining.</returns>
255
- public KurrentDBClientSerializationSettings RegisterMessageTypes ( IDictionary < string , Type > typeMap ) {
256
- foreach ( var map in typeMap ) {
257
- MessageTypeMap [ map . Key ] = map . Value ;
258
- }
173
+ public KurrentDBClientSerializationSettings UseContentType ( ContentType contentType ) {
174
+ DefaultContentType = contentType ;
259
175
260
176
return this ;
261
177
}
262
178
263
179
/// <summary>
264
- /// Configures a strongly-typed metadata class for all mes in the system.
265
- /// This enables accessing metadata properties in a type-safe manner rather than using dynamic objects.
266
- /// </summary>
267
- /// <typeparam name="T">The metadata class type containing properties matching the expected metadata fields.</typeparam>
268
- /// <returns>The current instance for method chaining.</returns>
269
- public KurrentDBClientSerializationSettings UseMetadataType < T > ( ) =>
270
- UseMetadataType ( typeof ( T ) ) ;
271
-
272
- /// <summary>
273
- /// Configures a strongly-typed metadata class for all mes in the system.
274
- /// This enables accessing metadata properties in a type-safe manner rather than using dynamic objects.
275
- /// </summary>
276
- /// <param name="type">The metadata class type containing properties matching the expected metadata fields.</param>
277
- /// <returns>The current instance for method chaining.</returns>
278
- public KurrentDBClientSerializationSettings UseMetadataType ( Type type ) {
279
- DefaultMetadataType = type ;
280
-
281
- return this ;
282
- }
283
- /// <summary>
284
- /// Configures which serialization format (JSON or binary) is used by default when writing messages
285
- /// where the content type isn't explicitly specified. The default content type is "application/json"
180
+ /// Allows to configure message type mapping
286
181
/// </summary>
287
- /// <param name="contentType">The serialization format content type </param>
182
+ /// <param name="configure"> </param>
288
183
/// <returns>The current instance for method chaining.</returns>
289
- public KurrentDBClientSerializationSettings UseContentType ( ContentType contentType ) {
290
- DefaultContentType = contentType ;
184
+ public KurrentDBClientSerializationSettings ConfigureTypeMap ( Action < MessageTypeMappingSettings > configure ) {
185
+ configure ( MessageTypeMapping ) ;
291
186
292
187
return this ;
293
188
}
@@ -301,8 +196,7 @@ internal KurrentDBClientSerializationSettings Clone() {
301
196
BytesSerializer = BytesSerializer ,
302
197
JsonSerializer = JsonSerializer ,
303
198
DefaultContentType = DefaultContentType ,
304
- MessageTypeMap = new Dictionary < string , Type > ( MessageTypeMap ) ,
305
- CategoryMessageTypesMap = new Dictionary < string , Type [ ] > ( CategoryMessageTypesMap ) ,
199
+ MessageTypeMapping = MessageTypeMapping . Clone ( ) ,
306
200
MessageTypeNamingStrategy = MessageTypeNamingStrategy
307
201
} ;
308
202
}
@@ -369,3 +263,134 @@ public enum AutomaticDeserialization {
369
263
/// </summary>
370
264
Enabled = 1
371
265
}
266
+
267
+ /// <summary>
268
+ /// Represents message type mapping settings
269
+ /// </summary>
270
+ public class MessageTypeMappingSettings {
271
+ /// <summary>
272
+ /// Allows to register mapping of CLR message types to their corresponding message type names used in serialized messages.
273
+ /// </summary>
274
+ public IDictionary < string , Type > TypeMap { get ; set ; } = new Dictionary < string , Type > ( ) ;
275
+
276
+ /// <summary>
277
+ /// Registers CLR message types that can be appended to the specific stream category.
278
+ /// Types will have message type names resolved based on the used <see cref="KurrentDB.Client.Core.Serialization.IMessageTypeNamingStrategy"/>
279
+ /// </summary>
280
+ public IDictionary < string , Type [ ] > CategoryTypesMap { get ; set ; } = new Dictionary < string , Type [ ] > ( ) ;
281
+
282
+ /// <summary>
283
+ /// Specifies the CLR type that should be used when deserializing metadata for all events.
284
+ /// When set, the client will attempt to deserialize event metadata into this type.
285
+ /// If not provided, <see cref="Kurrent.Diagnostics.Tracing.TracingMetadata"/> will be used.
286
+ /// </summary>
287
+ public Type ? DefaultMetadataType { get ; set ; }
288
+
289
+ /// <summary>
290
+ /// Associates a message type with a specific stream category to enable automatic deserialization.
291
+ /// In event sourcing, streams are often prefixed with a category (e.g., "user-123", "order-456").
292
+ /// This method tells the client which message types can appear in streams of a given category.
293
+ /// </summary>
294
+ /// <typeparam name="T">The event or message type that can appear in the category's streams.</typeparam>
295
+ /// <param name="categoryName">The category prefix (e.g., "user", "order", "account").</param>
296
+ /// <returns>The current instance for method chaining.</returns>
297
+ /// <example>
298
+ /// <code>
299
+ /// // Register event types that can appear in user streams
300
+ /// settings.RegisterMessageTypeForCategory<UserCreated>("user")
301
+ /// .RegisterMessageTypeForCategory<UserUpdated>("user")
302
+ /// .RegisterMessageTypeForCategory<UserDeleted>("user");
303
+ /// </code>
304
+ /// </example>
305
+ public MessageTypeMappingSettings RegisterForCategory < T > ( string categoryName ) =>
306
+ RegisterForCategory ( categoryName , typeof ( T ) ) ;
307
+
308
+ /// <summary>
309
+ /// Registers multiple message types for a specific stream category.
310
+ /// </summary>
311
+ /// <param name="categoryName">The category name to register the types with.</param>
312
+ /// <param name="types">The message types to register.</param>
313
+ /// <returns>The current instance for method chaining.</returns>
314
+ public MessageTypeMappingSettings RegisterForCategory ( string categoryName , params Type [ ] types ) {
315
+ CategoryTypesMap [ categoryName ] =
316
+ CategoryTypesMap . TryGetValue ( categoryName , out var current )
317
+ ? [ ..current , ..types ]
318
+ : types ;
319
+
320
+ return this ;
321
+ }
322
+
323
+ /// <summary>
324
+ /// Maps a .NET type to a specific message type name that will be stored in the message metadata.
325
+ /// This mapping is used during automatic deserialization, as it tells the client which CLR type
326
+ /// to instantiate when encountering a message with a particular type name in the database.
327
+ /// </summary>
328
+ /// <typeparam name="T">The .NET type to register (typically a message class).</typeparam>
329
+ /// <param name="typeName">The string identifier to use for this type in the database.</param>
330
+ /// <returns>The current instance for method chaining.</returns>
331
+ /// <remarks>
332
+ /// The type name is often different from the .NET type name to support versioning and evolution
333
+ /// of your domain model without breaking existing stored messages.
334
+ /// </remarks>
335
+ /// <example>
336
+ /// <code>
337
+ /// // Register me types with their corresponding type identifiers
338
+ /// settings.RegisterMessageType<UserCreated>("user-created-v1")
339
+ /// .RegisterMessageType<OrderPlaced>("order-placed-v2");
340
+ /// </code>
341
+ /// </example>
342
+ public MessageTypeMappingSettings Register < T > ( string typeName ) =>
343
+ Register ( typeName , typeof ( T ) ) ;
344
+
345
+ /// <summary>
346
+ /// Registers a message type with a specific type name.
347
+ /// </summary>
348
+ /// <param name="type">The message type to register.</param>
349
+ /// <param name="typeName">The type name to register for the message type.</param>
350
+ /// <returns>The current instance for method chaining.</returns>
351
+ public MessageTypeMappingSettings Register ( string typeName , Type type ) {
352
+ TypeMap [ typeName ] = type ;
353
+
354
+ return this ;
355
+ }
356
+
357
+ /// <summary>
358
+ /// Registers multiple message types with their corresponding type names.
359
+ /// </summary>
360
+ /// <param name="typeMap">Dictionary mapping types to their type names.</param>
361
+ /// <returns>The current instance for method chaining.</returns>
362
+ public MessageTypeMappingSettings Register ( IDictionary < string , Type > typeMap ) {
363
+ foreach ( var map in typeMap ) {
364
+ TypeMap [ map . Key ] = map . Value ;
365
+ }
366
+
367
+ return this ;
368
+ }
369
+
370
+ /// <summary>
371
+ /// Configures a strongly-typed metadata class for all mes in the system.
372
+ /// This enables accessing metadata properties in a type-safe manner rather than using dynamic objects.
373
+ /// </summary>
374
+ /// <typeparam name="T">The metadata class type containing properties matching the expected metadata fields.</typeparam>
375
+ /// <returns>The current instance for method chaining.</returns>
376
+ public MessageTypeMappingSettings UseMetadataType < T > ( ) =>
377
+ UseMetadataType ( typeof ( T ) ) ;
378
+
379
+ /// <summary>
380
+ /// Configures a strongly-typed metadata class for all mes in the system.
381
+ /// This enables accessing metadata properties in a type-safe manner rather than using dynamic objects.
382
+ /// </summary>
383
+ /// <param name="type">The metadata class type containing properties matching the expected metadata fields.</param>
384
+ /// <returns>The current instance for method chaining.</returns>
385
+ public MessageTypeMappingSettings UseMetadataType ( Type type ) {
386
+ DefaultMetadataType = type ;
387
+
388
+ return this ;
389
+ }
390
+
391
+ internal MessageTypeMappingSettings Clone ( ) =>
392
+ new MessageTypeMappingSettings {
393
+ TypeMap = new Dictionary < string , Type > ( TypeMap ) ,
394
+ CategoryTypesMap = new Dictionary < string , Type [ ] > ( CategoryTypesMap ) ,
395
+ } ;
396
+ }
0 commit comments