20
20
using System . Linq . Expressions ;
21
21
using System . Reflection ;
22
22
using System . Runtime . CompilerServices ;
23
- #if NET452
24
23
using System . Runtime . Serialization ;
25
- #endif
26
24
using MongoDB . Bson . IO ;
27
25
using MongoDB . Bson . Serialization . Conventions ;
28
26
@@ -36,13 +34,8 @@ public class BsonClassMap
36
34
// private static fields
37
35
private readonly static Dictionary < Type , BsonClassMap > __classMaps = new Dictionary < Type , BsonClassMap > ( ) ;
38
36
private readonly static Queue < Type > __knownTypesQueue = new Queue < Type > ( ) ;
39
-
40
- private static readonly MethodInfo __getUninitializedObjectMethodInfo =
41
- GetFormatterServicesType ( )
42
- . GetTypeInfo ( )
43
- ? . GetMethod ( "GetUninitializedObject" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static ) ;
44
-
45
37
private static int __freezeNestingLevel = 0 ;
38
+ private static readonly MethodInfo __getUninitializedObjectMethodInfo = GetGetUninitializedObjectMethodInfo ( ) ;
46
39
47
40
// private fields
48
41
private readonly Type _classType ;
@@ -423,6 +416,55 @@ public static void RegisterClassMap(BsonClassMap classMap)
423
416
}
424
417
}
425
418
419
+ // private static methods
420
+ private static Type GetFormatterServicesType ( )
421
+ {
422
+ #if NET452
423
+ return typeof ( FormatterServices ) ;
424
+ #else
425
+ // TODO: once we depend on newer versions of .NET Standard we should be able to do this without reflection
426
+
427
+ try
428
+ {
429
+ // new approach which works on .NET Core 3.0
430
+ var formattersAssembly = Assembly . Load ( new AssemblyName ( "System.Runtime.Serialization.Formatters" ) ) ;
431
+ var formatterServicesType = formattersAssembly . GetType ( "System.Runtime.Serialization.FormatterServices" ) ;
432
+ if ( formatterServicesType != null )
433
+ {
434
+ return formatterServicesType ;
435
+ }
436
+ }
437
+ catch
438
+ {
439
+ // ignore exceptions and continue to fallback code
440
+ }
441
+
442
+ // fallback to previous approach (which worked on older versions of .NET Core)
443
+ var mscorlibAssembly = typeof ( string ) . GetTypeInfo ( ) . Assembly ;
444
+ return mscorlibAssembly . GetType ( "System.Runtime.Serialization.FormatterServices" ) ;
445
+ #endif
446
+ }
447
+
448
+ private static MethodInfo GetGetUninitializedObjectMethodInfo ( )
449
+ {
450
+ // don't let exceptions leak out of this method because it's called from the type initializer
451
+ try
452
+ {
453
+ var formatterServicesType = GetFormatterServicesType ( ) ;
454
+ if ( formatterServicesType != null )
455
+ {
456
+ var formatterServicesTypeInfo = formatterServicesType . GetTypeInfo ( ) ;
457
+ return formatterServicesTypeInfo . GetMethod ( "GetUninitializedObject" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static ) ;
458
+ }
459
+ }
460
+ catch
461
+ {
462
+ // ignore exceptions
463
+ }
464
+
465
+ return null ;
466
+ }
467
+
426
468
// public methods
427
469
/// <summary>
428
470
/// Automaps the class.
@@ -1303,21 +1345,7 @@ private void ThrowNotFrozenException()
1303
1345
var message = string . Format ( "Class map for {0} has been not been frozen yet." , _classType . FullName ) ;
1304
1346
throw new InvalidOperationException ( message ) ;
1305
1347
}
1306
-
1307
- private static Type GetFormatterServicesType ( )
1308
- {
1309
- #if NET452
1310
- return typeof ( string )
1311
- . GetTypeInfo ( )
1312
- . Assembly
1313
- . GetType ( "System.Runtime.Serialization.FormatterServices" ) ;
1314
- #else
1315
- return
1316
- Assembly . Load ( new AssemblyName ( "System.Runtime.Serialization.Formatters" ) )
1317
- . GetType ( "System.Runtime.Serialization.FormatterServices" ) ;
1318
- #endif
1319
- }
1320
- }
1348
+ }
1321
1349
1322
1350
/// <summary>
1323
1351
/// Represents a mapping between a class and a BSON document.
0 commit comments