@@ -31,11 +31,6 @@ namespace MongoDB.Bson.Serialization
31
31
/// </summary>
32
32
public class BsonClassMap
33
33
{
34
- // private static fields
35
- private readonly static Dictionary < Type , BsonClassMap > __classMaps = new Dictionary < Type , BsonClassMap > ( ) ;
36
- private readonly static Queue < Type > __knownTypesQueue = new Queue < Type > ( ) ;
37
- private static int __freezeNestingLevel = 0 ;
38
-
39
34
// private fields
40
35
private readonly Type _classType ;
41
36
private readonly List < BsonCreatorMap > _creatorMaps ;
@@ -282,103 +277,32 @@ public static Type GetMemberInfoType(MemberInfo memberInfo)
282
277
/// Gets all registered class maps.
283
278
/// </summary>
284
279
/// <returns>All registered class maps.</returns>
285
- public static IEnumerable < BsonClassMap > GetRegisteredClassMaps ( )
286
- {
287
- BsonSerializer . ConfigLock . EnterReadLock ( ) ; //TODO It would make sense to look at this after the PR by Robert is merged
288
- try
289
- {
290
- return __classMaps . Values . ToList ( ) ; // return a copy for thread safety
291
- }
292
- finally
293
- {
294
- BsonSerializer . ConfigLock . ExitReadLock ( ) ;
295
- }
296
- }
280
+ public static IEnumerable < BsonClassMap > GetRegisteredClassMaps ( ) =>
281
+ BsonSerializer . DefaultDomain . ClassMapDomain . GetRegisteredClassMaps ( ) ;
297
282
298
283
/// <summary>
299
284
/// Checks whether a class map is registered for a type.
300
285
/// </summary>
301
286
/// <param name="type">The type to check.</param>
302
287
/// <returns>True if there is a class map registered for the type.</returns>
303
- public static bool IsClassMapRegistered ( Type type )
304
- {
305
- if ( type == null )
306
- {
307
- throw new ArgumentNullException ( "type" ) ;
308
- }
309
-
310
- BsonSerializer . ConfigLock . EnterReadLock ( ) ;
311
- try
312
- {
313
- return __classMaps . ContainsKey ( type ) ;
314
- }
315
- finally
316
- {
317
- BsonSerializer . ConfigLock . ExitReadLock ( ) ;
318
- }
319
- }
288
+ public static bool IsClassMapRegistered ( Type type ) =>
289
+ BsonSerializer . DefaultDomain . ClassMapDomain . IsClassMapRegistered ( type ) ;
320
290
321
291
/// <summary>
322
292
/// Looks up a class map (will AutoMap the class if no class map is registered).
323
293
/// </summary>
324
294
/// <param name="classType">The class type.</param>
325
295
/// <returns>The class map.</returns>
326
- public static BsonClassMap LookupClassMap ( Type classType )
327
- {
328
- if ( classType == null )
329
- {
330
- throw new ArgumentNullException ( "classType" ) ;
331
- }
332
-
333
- BsonSerializer . ConfigLock . EnterReadLock ( ) ;
334
- try
335
- {
336
- if ( __classMaps . TryGetValue ( classType , out var classMap ) )
337
- {
338
- if ( classMap . IsFrozen )
339
- {
340
- return classMap ;
341
- }
342
- }
343
- }
344
- finally
345
- {
346
- BsonSerializer . ConfigLock . ExitReadLock ( ) ;
347
- }
348
-
349
- // automatically create a new classMap for classType and register it (unless another thread does first)
350
- // do the work of speculatively creating a new class map outside of holding any lock
351
- var classMapDefinition = typeof ( BsonClassMap < > ) ;
352
- var classMapType = classMapDefinition . MakeGenericType ( classType ) ;
353
- var newClassMap = ( BsonClassMap ) Activator . CreateInstance ( classMapType ) ;
354
- newClassMap . AutoMap ( ) ;
355
-
356
- BsonSerializer . ConfigLock . EnterWriteLock ( ) ;
357
- try
358
- {
359
- if ( ! __classMaps . TryGetValue ( classType , out var classMap ) )
360
- {
361
- RegisterClassMap ( newClassMap ) ;
362
- classMap = newClassMap ;
363
- }
364
-
365
- return classMap . Freeze ( ) ;
366
- }
367
- finally
368
- {
369
- BsonSerializer . ConfigLock . ExitWriteLock ( ) ;
370
- }
371
- }
296
+ public static BsonClassMap LookupClassMap ( Type classType ) =>
297
+ BsonSerializer . DefaultDomain . ClassMapDomain . LookupClassMap ( classType ) ;
372
298
373
299
/// <summary>
374
300
/// Creates and registers a class map.
375
301
/// </summary>
376
302
/// <typeparam name="TClass">The class.</typeparam>
377
303
/// <returns>The class map.</returns>
378
- public static BsonClassMap < TClass > RegisterClassMap < TClass > ( ) //TODO We should move the static methods here to IBSonSerializerDomain
379
- {
380
- return RegisterClassMap < TClass > ( cm => { cm . AutoMap ( ) ; } ) ;
381
- }
304
+ public static BsonClassMap < TClass > RegisterClassMap < TClass > ( ) =>
305
+ BsonSerializer . DefaultDomain . ClassMapDomain . RegisterClassMap < TClass > ( ) ;
382
306
383
307
/// <summary>
384
308
/// Creates and registers a class map.
@@ -387,52 +311,22 @@ public static BsonClassMap<TClass> RegisterClassMap<TClass>() //TODO We should
387
311
/// <param name="classMapInitializer">The class map initializer.</param>
388
312
/// <returns>The class map.</returns>
389
313
public static BsonClassMap < TClass > RegisterClassMap < TClass > ( Action < BsonClassMap < TClass > > classMapInitializer )
390
- {
391
- var classMap = new BsonClassMap < TClass > ( classMapInitializer ) ;
392
- RegisterClassMap ( classMap ) ;
393
- return classMap ;
394
- }
314
+ => BsonSerializer . DefaultDomain . ClassMapDomain . RegisterClassMap ( classMapInitializer ) ;
395
315
396
316
/// <summary>
397
317
/// Registers a class map.
398
318
/// </summary>
399
319
/// <param name="classMap">The class map.</param>
400
320
public static void RegisterClassMap ( BsonClassMap classMap )
401
- {
402
- if ( classMap == null )
403
- {
404
- throw new ArgumentNullException ( "classMap" ) ;
405
- }
406
-
407
- BsonSerializer . ConfigLock . EnterWriteLock ( ) ;
408
- try
409
- {
410
- // note: class maps can NOT be replaced (because derived classes refer to existing instance)
411
- __classMaps . Add ( classMap . ClassType , classMap ) ;
412
- BsonSerializer . RegisterDiscriminator ( classMap . ClassType , classMap . Discriminator ) ;
413
- }
414
- finally
415
- {
416
- BsonSerializer . ConfigLock . ExitWriteLock ( ) ;
417
- }
418
- }
321
+ => BsonSerializer . DefaultDomain . ClassMapDomain . RegisterClassMap ( classMap ) ;
419
322
420
323
/// <summary>
421
324
/// Registers a class map if it is not already registered.
422
325
/// </summary>
423
326
/// <typeparam name="TClass">The class.</typeparam>
424
327
/// <returns>True if this call registered the class map, false if the class map was already registered.</returns>
425
328
public static bool TryRegisterClassMap < TClass > ( )
426
- {
427
- return TryRegisterClassMap ( ClassMapFactory ) ;
428
-
429
- static BsonClassMap < TClass > ClassMapFactory ( )
430
- {
431
- var classMap = new BsonClassMap < TClass > ( ) ;
432
- classMap . AutoMap ( ) ;
433
- return classMap ;
434
- }
435
- }
329
+ => BsonSerializer . DefaultDomain . ClassMapDomain . TryRegisterClassMap < TClass > ( ) ;
436
330
437
331
/// <summary>
438
332
/// Registers a class map if it is not already registered.
@@ -441,19 +335,7 @@ static BsonClassMap<TClass> ClassMapFactory()
441
335
/// <param name="classMap">The class map.</param>
442
336
/// <returns>True if this call registered the class map, false if the class map was already registered.</returns>
443
337
public static bool TryRegisterClassMap < TClass > ( BsonClassMap < TClass > classMap )
444
- {
445
- if ( classMap == null )
446
- {
447
- throw new ArgumentNullException ( nameof ( classMap ) ) ;
448
- }
449
-
450
- return TryRegisterClassMap ( ClassMapFactory ) ;
451
-
452
- BsonClassMap < TClass > ClassMapFactory ( )
453
- {
454
- return classMap ;
455
- }
456
- }
338
+ => BsonSerializer . DefaultDomain . ClassMapDomain . TryRegisterClassMap ( classMap ) ;
457
339
458
340
/// <summary>
459
341
/// Registers a class map if it is not already registered.
@@ -462,19 +344,7 @@ BsonClassMap<TClass> ClassMapFactory()
462
344
/// <param name="classMapInitializer">The class map initializer (only called if the class map is not already registered).</param>
463
345
/// <returns>True if this call registered the class map, false if the class map was already registered.</returns>
464
346
public static bool TryRegisterClassMap < TClass > ( Action < BsonClassMap < TClass > > classMapInitializer )
465
- {
466
- if ( classMapInitializer == null )
467
- {
468
- throw new ArgumentNullException ( nameof ( classMapInitializer ) ) ;
469
- }
470
-
471
- return TryRegisterClassMap ( ClassMapFactory ) ;
472
-
473
- BsonClassMap < TClass > ClassMapFactory ( )
474
- {
475
- return new BsonClassMap < TClass > ( classMapInitializer ) ;
476
- }
477
- }
347
+ => BsonSerializer . DefaultDomain . ClassMapDomain . TryRegisterClassMap ( classMapInitializer ) ;
478
348
479
349
/// <summary>
480
350
/// Registers a class map if it is not already registered.
@@ -483,45 +353,7 @@ BsonClassMap<TClass> ClassMapFactory()
483
353
/// <param name="classMapFactory">The class map factory (only called if the class map is not already registered).</param>
484
354
/// <returns>True if this call registered the class map, false if the class map was already registered.</returns>
485
355
public static bool TryRegisterClassMap < TClass > ( Func < BsonClassMap < TClass > > classMapFactory )
486
- {
487
- if ( classMapFactory == null )
488
- {
489
- throw new ArgumentNullException ( nameof ( classMapFactory ) ) ;
490
- }
491
-
492
- BsonSerializer . ConfigLock . EnterReadLock ( ) ;
493
- try
494
- {
495
- if ( __classMaps . ContainsKey ( typeof ( TClass ) ) )
496
- {
497
- return false ;
498
- }
499
- }
500
- finally
501
- {
502
- BsonSerializer . ConfigLock . ExitReadLock ( ) ;
503
- }
504
-
505
- BsonSerializer . ConfigLock . EnterWriteLock ( ) ;
506
- try
507
- {
508
- if ( __classMaps . ContainsKey ( typeof ( TClass ) ) )
509
- {
510
- return false ;
511
- }
512
- else
513
- {
514
- // create a classMap for TClass and register it
515
- var classMap = classMapFactory ( ) ;
516
- RegisterClassMap ( classMap ) ;
517
- return true ;
518
- }
519
- }
520
- finally
521
- {
522
- BsonSerializer . ConfigLock . ExitWriteLock ( ) ;
523
- }
524
- }
356
+ => BsonSerializer . DefaultDomain . ClassMapDomain . TryRegisterClassMap ( classMapFactory ) ;
525
357
526
358
// public methods
527
359
/// <summary>
@@ -573,13 +405,30 @@ obj is BsonClassMap other &&
573
405
/// <inheritdoc/>
574
406
public override int GetHashCode ( ) => 0 ;
575
407
408
+ internal class FreezeContext
409
+ {
410
+ public int FreezeNestingLevel { get ; set ; } = 0 ;
411
+ public Queue < Type > KnownTypesQueue { get ; set ; } = new ( ) ;
412
+ public IBsonSerializationDomain SerializationDomain { get ; set ; }
413
+ }
414
+
576
415
/// <summary>
577
416
/// Freezes the class map.
578
417
/// </summary>
579
418
/// <returns>The frozen class map.</returns>
580
- public BsonClassMap Freeze ( )
419
+ public BsonClassMap Freeze ( ) => Freeze ( BsonSerializer . DefaultDomain ) ;
420
+
421
+
422
+ internal BsonClassMap Freeze ( IBsonSerializationDomain domain )
423
+ {
424
+ var freezeContext = new FreezeContext ( ) { SerializationDomain = domain } ;
425
+ return Freeze ( freezeContext ) ;
426
+ }
427
+
428
+ private BsonClassMap Freeze ( FreezeContext context )
581
429
{
582
- BsonSerializer . ConfigLock . EnterReadLock ( ) ;
430
+ var configLock = ( context . SerializationDomain as IBsonSerializationDomainInternal ) ! . ConfigLock ;
431
+ configLock . EnterReadLock ( ) ;
583
432
try
584
433
{
585
434
if ( _frozen )
@@ -589,15 +438,15 @@ public BsonClassMap Freeze()
589
438
}
590
439
finally
591
440
{
592
- BsonSerializer . ConfigLock . ExitReadLock ( ) ;
441
+ configLock . ExitReadLock ( ) ;
593
442
}
594
443
595
- BsonSerializer . ConfigLock . EnterWriteLock ( ) ;
444
+ configLock . EnterWriteLock ( ) ;
596
445
try
597
446
{
598
447
if ( ! _frozen )
599
448
{
600
- __freezeNestingLevel ++ ;
449
+ context . FreezeNestingLevel ++ ;
601
450
try
602
451
{
603
452
var baseType = _classType . GetTypeInfo ( ) . BaseType ;
@@ -607,7 +456,7 @@ public BsonClassMap Freeze()
607
456
{
608
457
_baseClassMap = LookupClassMap ( baseType ) ;
609
458
}
610
- _baseClassMap . Freeze ( ) ;
459
+ _baseClassMap . Freeze ( context ) ; //TODO This is not necessary, because LookupClassMap will only return a frozen class map
611
460
_discriminatorIsRequired |= _baseClassMap . _discriminatorIsRequired ;
612
461
_hasRootClass |= ( _isRootClass || _baseClassMap . HasRootClass ) ;
613
462
_allMemberMaps . AddRange ( _baseClassMap . AllMemberMaps ) ;
@@ -699,28 +548,28 @@ public BsonClassMap Freeze()
699
548
// this avoids infinite recursion when going back down the inheritance tree while processing known types
700
549
foreach ( var knownType in _knownTypes )
701
550
{
702
- __knownTypesQueue . Enqueue ( knownType ) ;
551
+ context . KnownTypesQueue . Enqueue ( knownType ) ;
703
552
}
704
553
705
554
// if we are back to the first level go ahead and process any queued known types
706
- if ( __freezeNestingLevel == 1 )
555
+ if ( context . FreezeNestingLevel == 1 )
707
556
{
708
- while ( __knownTypesQueue . Count != 0 )
557
+ while ( context . KnownTypesQueue . Count != 0 )
709
558
{
710
- var knownType = __knownTypesQueue . Dequeue ( ) ;
559
+ var knownType = context . KnownTypesQueue . Dequeue ( ) ;
711
560
LookupClassMap ( knownType ) ; // will AutoMap and/or Freeze knownType if necessary
712
561
}
713
562
}
714
563
}
715
564
finally
716
565
{
717
- __freezeNestingLevel -- ;
566
+ context . FreezeNestingLevel -- ;
718
567
}
719
568
}
720
569
}
721
570
finally
722
571
{
723
- BsonSerializer . ConfigLock . ExitWriteLock ( ) ;
572
+ configLock . ExitWriteLock ( ) ;
724
573
}
725
574
return this ;
726
575
}
0 commit comments