2020using System . Linq . Expressions ;
2121using System . Reflection ;
2222using System . Runtime . CompilerServices ;
23- #if NET452
2423using System . Runtime . Serialization ;
25- #endif
2624using MongoDB . Bson . IO ;
2725using MongoDB . Bson . Serialization . Conventions ;
2826
@@ -36,13 +34,8 @@ public class BsonClassMap
3634 // private static fields
3735 private readonly static Dictionary < Type , BsonClassMap > __classMaps = new Dictionary < Type , BsonClassMap > ( ) ;
3836 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-
4537 private static int __freezeNestingLevel = 0 ;
38+ private static readonly MethodInfo __getUninitializedObjectMethodInfo = GetGetUninitializedObjectMethodInfo ( ) ;
4639
4740 // private fields
4841 private readonly Type _classType ;
@@ -423,6 +416,55 @@ public static void RegisterClassMap(BsonClassMap classMap)
423416 }
424417 }
425418
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+
426468 // public methods
427469 /// <summary>
428470 /// Automaps the class.
@@ -1303,21 +1345,7 @@ private void ThrowNotFrozenException()
13031345 var message = string . Format ( "Class map for {0} has been not been frozen yet." , _classType . FullName ) ;
13041346 throw new InvalidOperationException ( message ) ;
13051347 }
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+ }
13211349
13221350 /// <summary>
13231351 /// Represents a mapping between a class and a BSON document.
0 commit comments