@@ -15,6 +15,7 @@ namespace System.Runtime.Serialization
1515 using System . Runtime . CompilerServices ;
1616 using System . Linq ;
1717 using Xml . Schema ;
18+ using System . Collections . Concurrent ;
1819
1920#if USE_REFEMIT || uapaot
2021 public abstract class DataContract
@@ -64,6 +65,8 @@ internal static DataContract GetDataContractFromGeneratedAssembly(Type type)
6465 {
6566 return null ;
6667 }
68+
69+ type = GetDataContractAdapterTypeForGeneratedAssembly ( type ) ;
6770 DataContract dataContract = GetGeneratedDataContract ( type ) ;
6871 if ( dataContract == null )
6972 {
@@ -92,6 +95,20 @@ internal static DataContract GetDataContractFromGeneratedAssembly(Type type)
9295#endif
9396 }
9497
98+ #if uapaot
99+ // This method returns adapter types used to get DataContract from
100+ // generated assembly.
101+ private static Type GetDataContractAdapterTypeForGeneratedAssembly ( Type type )
102+ {
103+ if ( type == Globals . TypeOfDateTimeOffset )
104+ {
105+ return Globals . TypeOfDateTimeOffsetAdapter ;
106+ }
107+
108+ return type ;
109+ }
110+ #endif
111+
95112 internal MethodInfo ParseMethod
96113 {
97114 get { return _helper . ParseMethod ; }
@@ -124,6 +141,13 @@ internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHa
124141 {
125142 return DataContractCriticalHelper . GetDataContractSkipValidation ( id , typeHandle , type ) ;
126143 }
144+ #if uapaot
145+ internal static DataContract GetDataContractCreatedAtRuntime ( Type type , SerializationMode mode = SerializationMode . SharedContract )
146+ {
147+ DataContract dataContract = DataContractCriticalHelper . GetDataContractCreatedAtRuntime ( type ) ;
148+ return dataContract . GetValidContract ( mode ) ;
149+ }
150+ #endif
127151
128152 internal static DataContract GetGetOnlyCollectionDataContract ( int id , RuntimeTypeHandle typeHandle , Type type , SerializationMode mode )
129153 {
@@ -380,6 +404,9 @@ internal class DataContractCriticalHelper
380404 {
381405 private static Dictionary < TypeHandleRef , IntRef > s_typeToIDCache = new Dictionary < TypeHandleRef , IntRef > ( new TypeHandleRefEqualityComparer ( ) ) ;
382406 private static DataContract [ ] s_dataContractCache = new DataContract [ 32 ] ;
407+ #if uapaot
408+ private static ConcurrentDictionary < Type , DataContract > s_dataContractCacheCreatedAtRuntime = new ConcurrentDictionary < Type , DataContract > ( ) ;
409+ #endif
383410 private static int s_dataContractID ;
384411 private static Dictionary < Type , DataContract > s_typeToBuiltInContract ;
385412 private static Dictionary < XmlQualifiedName , DataContract > s_nameToBuiltInContract ;
@@ -431,6 +458,23 @@ internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHa
431458 return dataContract ;
432459 }
433460
461+ #if uapaot
462+ internal static DataContract GetDataContractCreatedAtRuntime ( Type type )
463+ {
464+ if ( type == null )
465+ {
466+ throw new ArgumentNullException ( nameof ( type ) ) ;
467+ }
468+
469+ DataContract dataContract = s_dataContractCacheCreatedAtRuntime . GetOrAdd ( type , ( t ) =>
470+ {
471+ return CreateDataContract ( t ) ;
472+ } ) ;
473+
474+ return dataContract . GetValidContract ( ) ;
475+ }
476+ #endif
477+
434478 internal static DataContract GetGetOnlyCollectionDataContractSkipValidation ( int id , RuntimeTypeHandle typeHandle , Type type )
435479 {
436480#if uapaot
@@ -534,55 +578,64 @@ private static DataContract CreateDataContract(int id, RuntimeTypeHandle typeHan
534578 type = Type . GetTypeFromHandle ( typeHandle ) ;
535579
536580 type = UnwrapNullableType ( type ) ;
537- var originalType = type ;
538581
539- type = GetDataContractAdapterTypeForGeneratedAssembly ( type ) ;
540582 dataContract = DataContract . GetDataContractFromGeneratedAssembly ( type ) ;
541583 if ( dataContract != null )
542584 {
543585 AssignDataContractToId ( dataContract , id ) ;
544586 return dataContract ;
545587 }
546588
547- type = GetDataContractAdapterType ( type ) ;
548- dataContract = GetBuiltInDataContract ( type ) ;
549- if ( dataContract == null )
589+ dataContract = CreateDataContract ( type ) ;
590+ }
591+ }
592+ }
593+
594+ return dataContract ;
595+ }
596+
597+ private static DataContract CreateDataContract ( Type type )
598+ {
599+ type = UnwrapNullableType ( type ) ;
600+ Type originalType = type ;
601+ type = GetDataContractAdapterType ( type ) ;
602+
603+ DataContract dataContract = GetBuiltInDataContract ( type ) ;
604+ if ( dataContract == null )
605+ {
606+ if ( type . IsArray )
607+ dataContract = new CollectionDataContract ( type ) ;
608+ else if ( type . IsEnum )
609+ dataContract = new EnumDataContract ( type ) ;
610+ else if ( Globals . TypeOfIXmlSerializable . IsAssignableFrom ( type ) )
611+ dataContract = new XmlDataContract ( type ) ;
612+ else if ( Globals . TypeOfScriptObject_IsAssignableFrom ( type ) )
613+ dataContract = Globals . CreateScriptObjectClassDataContract ( ) ;
614+ else
615+ {
616+ //if (type.ContainsGenericParameters)
617+ // ThrowInvalidDataContractException(SR.Format(SR.TypeMustNotBeOpenGeneric, type), type);
618+
619+ if ( ! CollectionDataContract . TryCreate ( type , out dataContract ) )
620+ {
621+ if ( ! type . IsSerializable && ! type . IsDefined ( Globals . TypeOfDataContractAttribute , false ) && ! ClassDataContract . IsNonAttributedTypeValidForSerialization ( type ) && ! ClassDataContract . IsKnownSerializableType ( type ) )
622+ {
623+ ThrowInvalidDataContractException ( SR . Format ( SR . TypeNotSerializable , type ) , type ) ;
624+ }
625+ dataContract = new ClassDataContract ( type ) ;
626+ if ( type != originalType )
550627 {
551- if ( type . IsArray )
552- dataContract = new CollectionDataContract ( type ) ;
553- else if ( type . IsEnum )
554- dataContract = new EnumDataContract ( type ) ;
555- else if ( Globals . TypeOfIXmlSerializable . IsAssignableFrom ( type ) )
556- dataContract = new XmlDataContract ( type ) ;
557- else if ( Globals . TypeOfScriptObject_IsAssignableFrom ( type ) )
558- dataContract = Globals . CreateScriptObjectClassDataContract ( ) ;
559- else
628+ var originalDataContract = new ClassDataContract ( originalType ) ;
629+ if ( dataContract . StableName != originalDataContract . StableName )
560630 {
561- //if (type.ContainsGenericParameters)
562- // ThrowInvalidDataContractException(SR.Format(SR.TypeMustNotBeOpenGeneric, type), type);
563-
564- if ( ! CollectionDataContract . TryCreate ( type , out dataContract ) )
565- {
566- if ( ! type . IsSerializable && ! type . IsDefined ( Globals . TypeOfDataContractAttribute , false ) && ! ClassDataContract . IsNonAttributedTypeValidForSerialization ( type ) && ! ClassDataContract . IsKnownSerializableType ( type ) )
567- {
568- ThrowInvalidDataContractException ( SR . Format ( SR . TypeNotSerializable , type ) , type ) ;
569- }
570- dataContract = new ClassDataContract ( type ) ;
571- if ( type != originalType )
572- {
573- var originalDataContract = new ClassDataContract ( originalType ) ;
574- if ( dataContract . StableName != originalDataContract . StableName )
575- {
576- // for non-DC types, type adapters will not have the same stable name (contract name).
577- dataContract . StableName = originalDataContract . StableName ;
578- }
579- }
580- }
631+ // for non-DC types, type adapters will not have the same stable name (contract name).
632+ dataContract . StableName = originalDataContract . StableName ;
581633 }
582634 }
583635 }
584636 }
585637 }
638+
586639 return dataContract ;
587640 }
588641
@@ -616,18 +669,6 @@ private static DataContract CreateGetOnlyCollectionDataContract(int id, RuntimeT
616669 return dataContract ;
617670 }
618671
619- // This method returns adapter types used to get DataContract from
620- // generated assembly.
621- private static Type GetDataContractAdapterTypeForGeneratedAssembly ( Type type )
622- {
623- if ( type == Globals . TypeOfDateTimeOffset )
624- {
625- return Globals . TypeOfDateTimeOffsetAdapter ;
626- }
627-
628- return type ;
629- }
630-
631672 // This method returns adapter types used at runtime to create DataContract.
632673 internal static Type GetDataContractAdapterType ( Type type )
633674 {
0 commit comments