Support more collections in STJ source generator (#55566)
authorLayomi Akinrinade <laakinri@microsoft.com>
Thu, 15 Jul 2021 18:41:56 +0000 (11:41 -0700)
committerGitHub <noreply@github.com>
Thu, 15 Jul 2021 18:41:56 +0000 (11:41 -0700)
* Support more collections in STJ source generator

* Fix tests

* Revert redundant MLC change and address feedback

71 files changed:
src/libraries/System.Text.Json/Common/ReflectionExtensions.cs
src/libraries/System.Text.Json/gen/CollectionType.cs
src/libraries/System.Text.Json/gen/ContextGenerationSpec.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
src/libraries/System.Text.Json/gen/Reflection/CustomAttributeDataWrapper.cs
src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs
src/libraries/System.Text.Json/gen/Reflection/TypeExtensions.cs
src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs
src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs
src/libraries/System.Text.Json/ref/System.Text.Json.cs
src/libraries/System.Text.Json/ref/System.Text.Json.csproj
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IAsyncEnumerableConverterFactory.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactory.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableConverterFactoryHelpers.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IEnumerableWithAddMethodConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/ImmutableDictionaryOfTKeyTValueConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/ImmutableEnumerableOfTConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/KeyValuePairConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.AsyncEnumerable.cs with 78% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Concurrent.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs with 71% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs with 100% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Dictionary.cs with 67% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Generic.Read.cs with 55% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Write.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Generic.Write.cs with 69% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Immutable.Read.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Immutable.Write.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Immutable.Write.cs with 64% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.KeyValuePair.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.KeyValuePair.cs with 68% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.NonGeneric.Read.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.NonGeneric.Read.cs with 59% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.NonGeneric.Write.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.NonGeneric.Write.cs with 64% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.ObjectModel.Read.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.ObjectModel.Write.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.ObjectModel.Write.cs with 51% similarity]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Read.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Write.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapperForStream.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs
src/libraries/System.Text.Json/tests/Common/SerializerTests.cs
src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/JsonSerializerWrapper.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/JsonSerializerWrapperForString_SourceGen.cs with 70% similarity]
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.csproj
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonTestHelper.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.Write.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Immutable.Read.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.ObjectModel.Read.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Read.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Write.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapperForStream.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializationWrapperForStream.cs with 77% similarity]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapperForString_Dynamic.cs [deleted file]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyNameTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyVisibilityTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.Collections.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.DeserializeAsyncEnumerable.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/StreamTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj

index 5d9ef54..623aa48 100644 (file)
 
 using System.Diagnostics;
 using System.Reflection;
+#if !BUILDING_SOURCE_GENERATOR
+using System.Diagnostics.CodeAnalysis;
+#endif
 
 namespace System.Text.Json.Reflection
 {
     internal static partial class ReflectionExtensions
     {
+        // Immutable collection types.
+        private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
+        private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
+        private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
+        private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
+        private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
+        private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
+        private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
+        private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
+        private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
+        private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
+        private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
+        private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2";
+        private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2";
+
+        // Immutable collection builder types.
+        private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
+        private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
+        private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
+        private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
+        private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
+        private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
+        private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
+        private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary";
+
+        public const string CreateRangeMethodName = "CreateRange";
+
+        public static Type? GetCompatibleGenericBaseClass(
+            this Type type,
+            Type baseType,
+            Type? objectType = null,
+            bool sourceGenType = false)
+        {
+            Debug.Assert(baseType.IsGenericType);
+            Debug.Assert(!baseType.IsInterface);
+            Debug.Assert(baseType == baseType.GetGenericTypeDefinition());
+
+            // Work around not being able to use typeof(object) directly during compile-time src gen type analysis.
+            objectType ??= typeof(object);
+
+            Type? baseTypeToCheck = type;
+
+            while (baseTypeToCheck != null && baseTypeToCheck != typeof(object))
+            {
+                if (baseTypeToCheck.IsGenericType)
+                {
+                    Type genericTypeToCheck = baseTypeToCheck.GetGenericTypeDefinition();
+                    if (genericTypeToCheck == baseType ||
+                        (sourceGenType && (OpenGenericTypesHaveSamePrefix(baseType, genericTypeToCheck))))
+                    {
+                        return baseTypeToCheck;
+                    }
+                }
+
+                baseTypeToCheck = baseTypeToCheck.BaseType;
+            }
+
+            return null;
+        }
+
+#if !BUILDING_SOURCE_GENERATOR
+        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
+            Justification = "The 'interfaceType' must exist and so trimmer kept it. In which case " +
+                "It also kept it on any type which implements it. The below call to GetInterfaces " +
+                "may return fewer results when trimmed but it will return the 'interfaceType' " +
+                "if the type implemented it, even after trimming.")]
+#endif
+        public static Type? GetCompatibleGenericInterface(this Type type, Type interfaceType)
+        {
+            Debug.Assert(interfaceType.IsGenericType);
+            Debug.Assert(interfaceType.IsInterface);
+            Debug.Assert(interfaceType == interfaceType.GetGenericTypeDefinition());
+
+            Type interfaceToCheck = type;
+
+            if (interfaceToCheck.IsGenericType)
+            {
+                interfaceToCheck = interfaceToCheck.GetGenericTypeDefinition();
+            }
+
+            if (interfaceToCheck == interfaceType)
+            {
+                return type;
+            }
+
+            foreach (Type typeToCheck in type.GetInterfaces())
+            {
+                if (typeToCheck.IsGenericType)
+                {
+                    Type genericInterfaceToCheck = typeToCheck.GetGenericTypeDefinition();
+                    if (genericInterfaceToCheck == interfaceType)
+                    {
+                        return typeToCheck;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        public static bool IsImmutableDictionaryType(this Type type, bool sourceGenType = false)
+        {
+            if (!type.IsGenericType || !type.Assembly.FullName!.StartsWith("System.Collections.Immutable", StringComparison.Ordinal))
+            {
+                return false;
+            }
+
+            switch (GetBaseNameFromGenericType(type, sourceGenType))
+            {
+                case ImmutableDictionaryGenericTypeName:
+                case ImmutableDictionaryGenericInterfaceTypeName:
+                case ImmutableSortedDictionaryGenericTypeName:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public static bool IsImmutableEnumerableType(this Type type, bool sourceGenType = false)
+        {
+            if (!type.IsGenericType || !type.Assembly.FullName!.StartsWith("System.Collections.Immutable", StringComparison.Ordinal))
+            {
+                return false;
+            }
+
+            switch (GetBaseNameFromGenericType(type, sourceGenType))
+            {
+                case ImmutableArrayGenericTypeName:
+                case ImmutableListGenericTypeName:
+                case ImmutableListGenericInterfaceTypeName:
+                case ImmutableStackGenericTypeName:
+                case ImmutableStackGenericInterfaceTypeName:
+                case ImmutableQueueGenericTypeName:
+                case ImmutableQueueGenericInterfaceTypeName:
+                case ImmutableSortedSetGenericTypeName:
+                case ImmutableHashSetGenericTypeName:
+                case ImmutableSetGenericInterfaceTypeName:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public static string? GetImmutableDictionaryConstructingTypeName(this Type type, bool sourceGenType = false)
+        {
+            Debug.Assert(type.IsImmutableDictionaryType(sourceGenType));
+
+            // Use the generic type definition of the immutable collection to determine
+            // an appropriate constructing type, i.e. a type that we can invoke the
+            // `CreateRange<T>` method on, which returns the desired immutable collection.
+            switch (GetBaseNameFromGenericType(type, sourceGenType))
+            {
+                case ImmutableDictionaryGenericTypeName:
+                case ImmutableDictionaryGenericInterfaceTypeName:
+                    return ImmutableDictionaryTypeName;
+                case ImmutableSortedDictionaryGenericTypeName:
+                    return ImmutableSortedDictionaryTypeName;
+                default:
+                    // We verified that the type is an immutable collection, so the
+                    // generic definition is one of the above.
+                    return null;
+            }
+        }
+
+        public static string? GetImmutableEnumerableConstructingTypeName(this Type type, bool sourceGenType = false)
+        {
+            Debug.Assert(type.IsImmutableEnumerableType(sourceGenType));
+
+            // Use the generic type definition of the immutable collection to determine
+            // an appropriate constructing type, i.e. a type that we can invoke the
+            // `CreateRange<T>` method on, which returns the desired immutable collection.
+            switch (GetBaseNameFromGenericType(type, sourceGenType))
+            {
+                case ImmutableArrayGenericTypeName:
+                    return ImmutableArrayTypeName;
+                case ImmutableListGenericTypeName:
+                case ImmutableListGenericInterfaceTypeName:
+                    return ImmutableListTypeName;
+                case ImmutableStackGenericTypeName:
+                case ImmutableStackGenericInterfaceTypeName:
+                    return ImmutableStackTypeName;
+                case ImmutableQueueGenericTypeName:
+                case ImmutableQueueGenericInterfaceTypeName:
+                    return ImmutableQueueTypeName;
+                case ImmutableSortedSetGenericTypeName:
+                    return ImmutableSortedSetTypeName;
+                case ImmutableHashSetGenericTypeName:
+                case ImmutableSetGenericInterfaceTypeName:
+                    return ImmutableHashSetTypeName;
+                default:
+                    // We verified that the type is an immutable collection, so the
+                    // generic definition is one of the above.
+                    return null;
+            }
+        }
+
+        private static bool OpenGenericTypesHaveSamePrefix(Type t1, Type t2)
+            => t1.FullName == GetBaseNameFromGenericTypeDef(t2);
+
+        private static string GetBaseNameFromGenericType(Type genericType, bool sourceGenType)
+        {
+            Type genericTypeDef = genericType.GetGenericTypeDefinition();
+            return sourceGenType ? GetBaseNameFromGenericTypeDef(genericTypeDef) : genericTypeDef.FullName!;
+        }
+
+        private static string GetBaseNameFromGenericTypeDef(Type genericTypeDef)
+        {
+            Debug.Assert(genericTypeDef.IsGenericType);
+            string fullName = genericTypeDef.FullName!;
+            int length = fullName.IndexOf("`") + 2;
+            return fullName.Substring(0, length);
+        }
+
         public static bool IsVirtual(this PropertyInfo? propertyInfo)
         {
             Debug.Assert(propertyInfo != null);
index 6f73669..26e5bca 100644 (file)
@@ -9,11 +9,28 @@ namespace System.Text.Json.SourceGeneration
 {
     internal enum CollectionType
     {
-        NotApplicable = 0,
-        Array = 1,
-        List = 2,
-        IEnumerable = 3,
-        IList = 4,
-        Dictionary = 5
+        NotApplicable,
+        // Dictionary types
+        IDictionary,
+        Dictionary,
+        ImmutableDictionary,
+        IDictionaryOfTKeyTValue,
+        IReadOnlyDictionary,
+        // Non-dictionary types
+        Array,
+        List,
+        IEnumerable,
+        IList,
+        IListOfT,
+        ISet,
+        ICollectionOfT,
+        StackOfT,
+        QueueOfT,
+        ConcurrentStack,
+        ConcurrentQueue,
+        IEnumerableOfT,
+        Stack,
+        Queue,
+        ImmutableEnumerable
     }
 }
index 8020f79..1339e4b 100644 (file)
@@ -4,6 +4,7 @@
 using System.Collections.Generic;
 using System.Text.Json.Serialization;
 using System.Text.Json.Reflection;
+using System.Diagnostics;
 
 namespace System.Text.Json.SourceGeneration
 {
@@ -11,6 +12,7 @@ namespace System.Text.Json.SourceGeneration
     /// Represents the set of input types and options needed to provide an
     /// implementation for a user-provided JsonSerializerContext-derived type.
     /// </summary>
+    [DebuggerDisplay("ContextTypeRef={ContextTypeRef}")]
     internal sealed class ContextGenerationSpec
     {
         public JsonSourceGenerationOptionsAttribute GenerationOptions { get; init; }
@@ -34,6 +36,6 @@ namespace System.Text.Json.SourceGeneration
         /// </summary>
         public HashSet<string> RuntimePropertyNames { get; } = new();
 
-        public string ContextTypeRef => $"global::{ContextType.GetUniqueCompilableTypeName()}";
+        public string ContextTypeRef => ContextType.GetCompilableName();
     }
 }
index cbab663..fe8447e 100644 (file)
@@ -328,12 +328,9 @@ namespace {_currentContext.ContextType.Namespace}
 
             private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec)
             {
-                string typeCompilableName = typeGenerationSpec.TypeRef;
-                string typeFriendlyName = typeGenerationSpec.TypeInfoPropertyName;
-
                 // Key metadata
                 TypeGenerationSpec? collectionKeyTypeMetadata = typeGenerationSpec.CollectionKeyTypeMetadata;
-                Debug.Assert(!(typeGenerationSpec.CollectionType == CollectionType.Dictionary && collectionKeyTypeMetadata == null));
+                Debug.Assert(!(typeGenerationSpec.ClassType == ClassType.Dictionary && collectionKeyTypeMetadata == null));
                 string? keyTypeCompilableName = collectionKeyTypeMetadata?.TypeRef;
                 string? keyTypeReadableName = collectionKeyTypeMetadata?.TypeInfoPropertyName;
 
@@ -361,11 +358,8 @@ namespace {_currentContext.ContextType.Namespace}
 
                 string numberHandlingArg = $"{GetNumberHandlingAsStr(typeGenerationSpec.NumberHandling)}";
 
-                string serializeMethodName = $"{typeFriendlyName}{SerializeMethodNameSuffix}";
                 string serializeFuncNamedArg;
 
-                CollectionType collectionType = typeGenerationSpec.CollectionType;
-
                 string? serializeFuncSource;
                 if (!typeGenerationSpec.GenerateSerializationLogic)
                 {
@@ -374,81 +368,149 @@ namespace {_currentContext.ContextType.Namespace}
                 }
                 else
                 {
-                    bool canBeNull = typeGenerationSpec.CanBeNull;
-
-                    switch (collectionType)
-                    {
-                        case CollectionType.Array:
-                            serializeFuncSource = GenerateFastPathFuncForEnumerable(typeCompilableName, serializeMethodName, canBeNull, isArray: true, collectionValueTypeMetadata);
-                            break;
-                        case CollectionType.List:
-                            serializeFuncSource = GenerateFastPathFuncForEnumerable(typeCompilableName, serializeMethodName, canBeNull, isArray: false, collectionValueTypeMetadata);
-                            break;
-                        case CollectionType.Dictionary:
-                            serializeFuncSource = GenerateFastPathFuncForDictionary(typeCompilableName, serializeMethodName, canBeNull, collectionKeyTypeMetadata, collectionValueTypeMetadata);
-                            break;
-                        default:
-                            serializeFuncSource = null;
-                            break;
-                    }
+                    serializeFuncSource = typeGenerationSpec.ClassType == ClassType.Enumerable
+                        ? GenerateFastPathFuncForEnumerable(typeGenerationSpec)
+                        : GenerateFastPathFuncForDictionary(typeGenerationSpec);
 
-                    serializeFuncNamedArg = $"serializeFunc: {serializeMethodName}";
+                    serializeFuncNamedArg = $"serializeFunc: {typeGenerationSpec.FastPathSerializeMethodName}";
                 }
 
-                string collectionTypeInfoValue = collectionType switch
+                CollectionType collectionType = typeGenerationSpec.CollectionType;
+
+                string typeRef = typeGenerationSpec.TypeRef;
+                string createObjectFuncArg = typeGenerationSpec.ConstructionStrategy == ObjectConstructionStrategy.ParameterlessConstructor
+                    ? $"createObjectFunc: () => new {typeRef}()"
+                    : "createObjectFunc: null";
+
+                string collectionInfoCreationPrefix = collectionType switch
                 {
-                    CollectionType.Array => $"{JsonMetadataServicesTypeRef}.CreateArrayInfo<{valueTypeCompilableName}>({OptionsInstanceVariableName}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})",
-                    CollectionType.List => $"{JsonMetadataServicesTypeRef}.CreateListInfo<{typeCompilableName}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, () => new {ListTypeRef}<{valueTypeCompilableName}>(), {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})",
-                    CollectionType.Dictionary => $"{JsonMetadataServicesTypeRef}.CreateDictionaryInfo<{typeCompilableName}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, () => new {DictionaryTypeRef}<{keyTypeCompilableName}, {valueTypeCompilableName}>(), {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})",
-                    _ => throw new NotSupportedException()
+                    CollectionType.IListOfT => $"{JsonMetadataServicesTypeRef}.CreateIListInfo<",
+                    CollectionType.ICollectionOfT => $"{JsonMetadataServicesTypeRef}.CreateICollectionInfo<",
+                    CollectionType.StackOfT => $"{JsonMetadataServicesTypeRef}.CreateStackInfo<",
+                    CollectionType.QueueOfT => $"{JsonMetadataServicesTypeRef}.CreateQueueInfo<",
+                    CollectionType.Stack => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<",
+                    CollectionType.Queue => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<",
+                    CollectionType.IEnumerableOfT => $"{JsonMetadataServicesTypeRef}.CreateIEnumerableInfo<",
+                    CollectionType.IDictionaryOfTKeyTValue => $"{JsonMetadataServicesTypeRef}.CreateIDictionaryInfo<",
+                    _ => $"{JsonMetadataServicesTypeRef}.Create{collectionType}Info<"
                 };
 
-                string metadataInitSource = @$"_{typeFriendlyName} = {collectionTypeInfoValue};";
+                string dictInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}";
+                string enumerableInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}";
+                string immutableCollectionCreationSuffix = $"createRangeFunc: {typeGenerationSpec.ImmutableCollectionBuilderName}";
+
+                string collectionTypeInfoValue;
+
+                switch (collectionType)
+                {
+                    case CollectionType.Array:
+                        collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{valueTypeCompilableName}>({OptionsInstanceVariableName}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+                        break;
+                    case CollectionType.IEnumerable:
+                    case CollectionType.IList:
+                        collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+                        break;
+                    case CollectionType.Stack:
+                    case CollectionType.Queue:
+                        string addMethod = collectionType == CollectionType.Stack ? "Push" : "Enqueue";
+                        string addFuncNamedArg = $"addFunc: (collection, {ValueVarName}) => collection.{addMethod}({ValueVarName})";
+                        collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}, {addFuncNamedArg})";
+                        break;
+                    case CollectionType.ImmutableEnumerable:
+                        collectionTypeInfoValue = $"{enumerableInfoCreationPrefix}, {immutableCollectionCreationSuffix})";
+                        break;
+                    case CollectionType.IDictionary:
+                        collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+                        break;
+                    case CollectionType.Dictionary:
+                    case CollectionType.IDictionaryOfTKeyTValue:
+                    case CollectionType.IReadOnlyDictionary:
+                        collectionTypeInfoValue = $"{dictInfoCreationPrefix})";
+                        break;
+                    case CollectionType.ImmutableDictionary:
+                        collectionTypeInfoValue = $"{dictInfoCreationPrefix}, {immutableCollectionCreationSuffix})";
+                        break;
+                    default:
+                        collectionTypeInfoValue = $"{enumerableInfoCreationPrefix})";
+                        break;
+                }
+
+                string metadataInitSource = @$"_{typeGenerationSpec.TypeInfoPropertyName} = {collectionTypeInfoValue};";
 
                 return GenerateForType(typeGenerationSpec, metadataInitSource, serializeFuncSource);
             }
 
-            private string GenerateFastPathFuncForEnumerable(string typeInfoRef, string serializeMethodName, bool canBeNull, bool isArray, TypeGenerationSpec valueTypeGenerationSpec)
+            private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerationSpec)
             {
-                string? writerMethodToCall = GetWriterMethod(valueTypeGenerationSpec.Type);
-                string valueToWrite = $"{ValueVarName}[i]";
-                string lengthPropName = isArray ? "Length" : "Count";
+                TypeGenerationSpec valueTypeGenerationSpec = typeGenerationSpec.CollectionValueTypeMetadata;
 
-                string elementSerializationLogic;
-                if (writerMethodToCall != null)
+                Type elementType = valueTypeGenerationSpec.Type;
+                string? writerMethodToCall = GetWriterMethod(elementType);
+                
+                string iterationLogic;
+                string valueToWrite;
+
+                switch (typeGenerationSpec.CollectionType)
                 {
-                    elementSerializationLogic = $"{writerMethodToCall}Value({valueToWrite});";
-                }
-                else
+                    case CollectionType.Array:
+                        iterationLogic = $"for (int i = 0; i < {ValueVarName}.Length; i++)";
+                        valueToWrite = $"{ValueVarName}[i]";
+                        break;
+                    case CollectionType.IListOfT:
+                    case CollectionType.List:
+                    case CollectionType.IList:
+                        iterationLogic = $"for (int i = 0; i < {ValueVarName}.Count; i++)";
+                        valueToWrite = $"{ValueVarName}[i]";
+                        break;
+                    default:
+                        const string elementVarName = "element";
+                        iterationLogic = $"foreach ({valueTypeGenerationSpec.TypeRef} {elementVarName} in {ValueVarName})";
+                        valueToWrite = elementVarName;
+                        break;
+                };
+
+                if (elementType == _generationSpec.CharType)
                 {
-                    elementSerializationLogic = GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec.TypeInfoPropertyName, valueToWrite, valueTypeGenerationSpec.GenerateSerializationLogic);
+                    valueToWrite = $"{valueToWrite}.ToString()";
                 }
 
+                string elementSerializationLogic = writerMethodToCall == null
+                    ? GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec.TypeInfoPropertyName, valueToWrite, valueTypeGenerationSpec.GenerateSerializationLogic)
+                    : $"{writerMethodToCall}Value({valueToWrite});";
+
                 string serializationLogic = $@"{WriterVarName}.WriteStartArray();
 
-    for (int i = 0; i < {ValueVarName}.{lengthPropName}; i++)
+    {iterationLogic}
     {{
         {elementSerializationLogic}
     }}
 
     {WriterVarName}.WriteEndArray();";
 
-                return GenerateFastPathFuncForType(serializeMethodName, typeInfoRef, serializationLogic, canBeNull);
+                return GenerateFastPathFuncForType(
+                    typeGenerationSpec.FastPathSerializeMethodName,
+                    typeGenerationSpec.TypeRef,
+                    serializationLogic,
+                    typeGenerationSpec.CanBeNull);
             }
 
-            private string GenerateFastPathFuncForDictionary(
-                string typeInfoRef,
-                string serializeMethodName,
-                bool canBeNull,
-                TypeGenerationSpec keyTypeGenerationSpec,
-                TypeGenerationSpec valueTypeGenerationSpec)
+            private string GenerateFastPathFuncForDictionary(TypeGenerationSpec typeGenerationSpec)
             {
+                TypeGenerationSpec keyTypeGenerationSpec = typeGenerationSpec.CollectionKeyTypeMetadata;
+                TypeGenerationSpec valueTypeGenerationSpec = typeGenerationSpec.CollectionValueTypeMetadata;
+
+                Type elementType = valueTypeGenerationSpec.Type;
+                string? writerMethodToCall = GetWriterMethod(elementType);
+                string elementSerializationLogic;
+
                 const string pairVarName = "pair";
                 string keyToWrite = $"{pairVarName}.Key";
                 string valueToWrite = $"{pairVarName}.Value";
 
-                string? writerMethodToCall = GetWriterMethod(valueTypeGenerationSpec.Type);
-                string elementSerializationLogic;
+                if (elementType == _generationSpec.CharType)
+                {
+                    valueToWrite = $"{valueToWrite}.ToString()";
+                }
 
                 if (writerMethodToCall != null)
                 {
@@ -469,7 +531,11 @@ namespace {_currentContext.ContextType.Namespace}
 
     {WriterVarName}.WriteEndObject();";
 
-                return GenerateFastPathFuncForType(serializeMethodName, typeInfoRef, serializationLogic, canBeNull);
+                return GenerateFastPathFuncForType(
+                    typeGenerationSpec.FastPathSerializeMethodName,
+                    typeGenerationSpec.TypeRef,
+                    serializationLogic,
+                    typeGenerationSpec.CanBeNull);
             }
 
             private string GenerateForObject(TypeGenerationSpec typeMetadata)
index 727d80c..2290738 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
@@ -21,42 +22,53 @@ namespace System.Text.Json.SourceGeneration
         private sealed class Parser
         {
             private const string SystemTextJsonNamespace = "System.Text.Json";
-
             private const string JsonConverterAttributeFullName = "System.Text.Json.Serialization.JsonConverterAttribute";
-
+            private const string JsonElementFullName = "System.Text.Json.JsonElement";
             private const string JsonIgnoreAttributeFullName = "System.Text.Json.Serialization.JsonIgnoreAttribute";
-
             private const string JsonIgnoreConditionFullName = "System.Text.Json.Serialization.JsonIgnoreCondition";
-
             private const string JsonIncludeAttributeFullName = "System.Text.Json.Serialization.JsonIncludeAttribute";
-
             private const string JsonNumberHandlingAttributeFullName = "System.Text.Json.Serialization.JsonNumberHandlingAttribute";
-
             private const string JsonPropertyNameAttributeFullName = "System.Text.Json.Serialization.JsonPropertyNameAttribute";
 
             private const string JsonPropertyOrderAttributeFullName = "System.Text.Json.Serialization.JsonPropertyOrderAttribute";
 
             private readonly GeneratorExecutionContext _executionContext;
-
             private readonly MetadataLoadContextInternal _metadataLoadContext;
 
+            private readonly Type _ilistOfTType;
+            private readonly Type _icollectionOfTType;
             private readonly Type _ienumerableType;
-            private readonly Type _listOfTType;
-            private readonly Type _dictionaryType;
+            private readonly Type _ienumerableOfTType;
+
+            private readonly Type? _listOfTType;
+            private readonly Type? _dictionaryType;
+            private readonly Type? _idictionaryOfTKeyTValueType;
+            private readonly Type? _ireadonlyDictionaryType;
+            private readonly Type? _isetType; 
+            private readonly Type? _stackOfTType;
+            private readonly Type? _queueOfTType;
+            private readonly Type? _concurrentStackType;
+            private readonly Type? _concurrentQueueType;
+            private readonly Type? _idictionaryType;
+            private readonly Type? _ilistType;
+            private readonly Type? _stackType;
+            private readonly Type? _queueType;
 
             private readonly Type _booleanType;
-            private readonly Type _byteArrayType;
             private readonly Type _charType;
             private readonly Type _dateTimeType;
-            private readonly Type _dateTimeOffsetType;
-            private readonly Type _guidType;
             private readonly Type _nullableOfTType;
+            private readonly Type _objectType;
             private readonly Type _stringType;
-            private readonly Type _uriType;
-            private readonly Type _versionType;
 
-            private readonly HashSet<Type> _numberTypes = new();
+            private readonly Type? _dateTimeOffsetType;
+            private readonly Type? _byteArrayType;
+            private readonly Type? _guidType;
+            private readonly Type? _uriType;
+            private readonly Type? _versionType;
+            private readonly Type? _jsonElementType;
 
+            private readonly HashSet<Type> _numberTypes = new();
             private readonly HashSet<Type> _knownTypes = new();
 
             /// <summary>
@@ -81,20 +93,38 @@ namespace System.Text.Json.SourceGeneration
                 _executionContext = executionContext;
                 _metadataLoadContext = new MetadataLoadContextInternal(executionContext.Compilation);
 
-                _ienumerableType = _metadataLoadContext.Resolve(typeof(IEnumerable));
-                _listOfTType = _metadataLoadContext.Resolve(typeof(List<>));
-                _dictionaryType = _metadataLoadContext.Resolve(typeof(Dictionary<,>));
-
-                _booleanType = _metadataLoadContext.Resolve(typeof(bool));
-                _byteArrayType = _metadataLoadContext.Resolve(typeof(byte[]));
-                _charType = _metadataLoadContext.Resolve(typeof(char));
-                _dateTimeType = _metadataLoadContext.Resolve(typeof(DateTime));
-                _dateTimeOffsetType = _metadataLoadContext.Resolve(typeof(DateTimeOffset));
-                _guidType = _metadataLoadContext.Resolve(typeof(Guid));
-                _nullableOfTType = _metadataLoadContext.Resolve(typeof(Nullable<>));
-                _stringType = _metadataLoadContext.Resolve(typeof(string));
-                _uriType = _metadataLoadContext.Resolve(typeof(Uri));
-                _versionType = _metadataLoadContext.Resolve(typeof(Version));
+                _ilistOfTType = ResolveType(SpecialType.System_Collections_Generic_IList_T);
+                _icollectionOfTType = ResolveType(SpecialType.System_Collections_Generic_ICollection_T);
+                _ienumerableOfTType = ResolveType(SpecialType.System_Collections_Generic_IEnumerable_T);
+                _ienumerableType = ResolveType(SpecialType.System_Collections_IEnumerable);
+
+                _listOfTType = ResolveType(typeof(List<>).FullName!);
+                _dictionaryType = ResolveType(typeof(Dictionary<,>).FullName!);
+                _idictionaryOfTKeyTValueType = ResolveType(typeof(IDictionary<,>).FullName!);
+                _ireadonlyDictionaryType = ResolveType(typeof(IReadOnlyDictionary<,>).FullName!);
+                _isetType = ResolveType(typeof(ISet<>).FullName!);
+                _stackOfTType = ResolveType(typeof(Stack<>).FullName!);
+                _queueOfTType = ResolveType(typeof(Queue<>).FullName!);
+                _concurrentStackType = ResolveType(typeof(ConcurrentStack<>).FullName!);
+                _concurrentQueueType = ResolveType(typeof(ConcurrentQueue<>).FullName!);
+                _idictionaryType = ResolveType(typeof(IDictionary).FullName!);
+                _ilistType = ResolveType(typeof(IList).FullName!);
+                _stackType = ResolveType(typeof(Stack).FullName!);
+                _queueType = ResolveType(typeof(Queue).FullName!);
+
+                _booleanType = ResolveType(SpecialType.System_Boolean);
+                _charType = ResolveType(SpecialType.System_Char);
+                _dateTimeType = ResolveType(SpecialType.System_DateTime);
+                _nullableOfTType = ResolveType(SpecialType.System_Nullable_T);
+                _objectType = ResolveType(SpecialType.System_Object);
+                _stringType = ResolveType(SpecialType.System_String);
+
+                _dateTimeOffsetType = ResolveType(typeof(DateTimeOffset).FullName!);
+                _byteArrayType = ResolveType(typeof(byte[]).FullName!);
+                _guidType = ResolveType(typeof(Guid).FullName!);
+                _uriType = ResolveType(typeof(Uri).FullName!);
+                _versionType = ResolveType(typeof(Version).FullName!);
+                _jsonElementType = ResolveType(JsonElementFullName);
 
                 PopulateKnownTypes();
             }
@@ -499,13 +529,11 @@ namespace System.Text.Json.SourceGeneration
                 Type? collectionValueType = null;
                 TypeGenerationSpec? nullableUnderlyingTypeGenSpec = null;
                 List<PropertyGenerationSpec>? propGenSpecList = null;
-                CollectionType collectionType = CollectionType.NotApplicable;
                 ObjectConstructionStrategy constructionStrategy = default;
+                CollectionType collectionType = CollectionType.NotApplicable;
                 JsonNumberHandling? numberHandling = null;
-
                 bool foundDesignTimeCustomConverter = false;
                 string? converterInstatiationLogic = null;
-
                 bool implementsIJsonOnSerialized = false;
                 bool implementsIJsonOnSerializing = false;
 
@@ -526,6 +554,15 @@ namespace System.Text.Json.SourceGeneration
                     }
                 }
 
+                if (type.Name.StartsWith("StackWrapper"))
+                {
+                }
+
+                if (type.GetConstructor(Type.EmptyTypes) != null && !type.IsAbstract && !type.IsInterface)
+                {
+                    constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor;
+                }
+
                 if (foundDesignTimeCustomConverter)
                 {
                     classType = converterInstatiationLogic != null
@@ -549,53 +586,150 @@ namespace System.Text.Json.SourceGeneration
                 }
                 else if (_ienumerableType.IsAssignableFrom(type))
                 {
-                    // Only T[], List<T>, and Dictionary<Tkey, TValue> are supported.
+                    Type actualTypeToConvert;
 
                     if (type.IsArray)
                     {
-                        classType = ClassType.Enumerable;
+                        classType = type.GetArrayRank() > 1
+                            ? ClassType.TypeUnsupportedBySourceGen // Multi-dimentional arrays are not supported in STJ.
+                            : ClassType.Enumerable;
                         collectionType = CollectionType.Array;
                         collectionValueType = type.GetElementType();
                     }
-                    else if (!type.IsGenericType)
+                    else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _listOfTType)) != null)
                     {
-                        classType = ClassType.TypeUnsupportedBySourceGen;
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.List;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
                     }
-                    else
+                    else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _dictionaryType)) != null)
                     {
-                        Type genericTypeDef = type.GetGenericTypeDefinition();
-                        Type[] genericTypeArgs = type.GetGenericArguments();
+                        classType = ClassType.Dictionary;
+                        collectionType = CollectionType.Dictionary;
 
-                        if (genericTypeDef == _listOfTType)
-                        {
-                            classType = ClassType.Enumerable;
-                            collectionType = CollectionType.List;
-                            collectionValueType = genericTypeArgs[0];
-                        }
-                        else if (genericTypeDef == _dictionaryType)
-                        {
-                            classType = ClassType.Dictionary;
-                            collectionType = CollectionType.Dictionary;
-                            collectionKeyType = genericTypeArgs[0];
-                            collectionValueType = genericTypeArgs[1];
-                        }
-                        else
-                        {
-                            classType = ClassType.TypeUnsupportedBySourceGen;
-                        }
+                        Type[] genericArgs = actualTypeToConvert.GetGenericArguments();
+                        collectionKeyType = genericArgs[0];
+                        collectionValueType = genericArgs[1];
+                    }
+                    else if (type.IsImmutableDictionaryType(sourceGenType: true))
+                    {
+                        classType = ClassType.Dictionary;
+                        collectionType = CollectionType.ImmutableDictionary;
+
+                        Type[] genericArgs = type.GetGenericArguments();
+                        collectionKeyType = genericArgs[0];
+                        collectionValueType = genericArgs[1];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_idictionaryOfTKeyTValueType)) != null)
+                    {
+                        classType = ClassType.Dictionary;
+                        collectionType = CollectionType.IDictionaryOfTKeyTValue;
+
+                        Type[] genericArgs = actualTypeToConvert.GetGenericArguments();
+                        collectionKeyType = genericArgs[0];
+                        collectionValueType = genericArgs[1];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ireadonlyDictionaryType)) != null)
+                    {
+                        classType = ClassType.Dictionary;
+                        collectionType = CollectionType.IReadOnlyDictionary;
+
+                        Type[] genericArgs = actualTypeToConvert.GetGenericArguments();
+                        collectionKeyType = genericArgs[0];
+                        collectionValueType = genericArgs[1];
+                    }
+                    else if (type.IsImmutableEnumerableType(sourceGenType: true))
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.ImmutableEnumerable;
+                        collectionValueType = type.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ilistOfTType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.IListOfT;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_isetType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.ISet;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_icollectionOfTType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.ICollectionOfT;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _stackOfTType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.StackOfT;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _queueOfTType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.QueueOfT;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericBaseClass(_concurrentStackType, _objectType, sourceGenType: true)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.ConcurrentStack;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericBaseClass(_concurrentQueueType, _objectType, sourceGenType: true)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.ConcurrentQueue;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ienumerableOfTType)) != null)
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.IEnumerableOfT;
+                        collectionValueType = actualTypeToConvert.GetGenericArguments()[0];
+                    }
+                    else if (_idictionaryType.IsAssignableFrom(type))
+                    {
+                        classType = ClassType.Dictionary;
+                        collectionType = CollectionType.IDictionary;
+                        collectionKeyType = _stringType;
+                        collectionValueType = _objectType;
+                    }
+                    else if (_ilistType.IsAssignableFrom(type))
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.IList;
+                        collectionValueType = _objectType;
+                    }
+                    else if (_stackType.IsAssignableFrom(type))
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.Stack;
+                        collectionValueType = _objectType;
+                    }
+                    else if (_queueType.IsAssignableFrom(type))
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.Queue;
+                        collectionValueType = _objectType;
+                    }
+                    else
+                    {
+                        classType = ClassType.Enumerable;
+                        collectionType = CollectionType.IEnumerable;
+                        collectionValueType = _objectType;
                     }
                 }
                 else
                 {
                     classType = ClassType.Object;
 
-                    if (type.GetConstructor(Type.EmptyTypes) != null && !type.IsAbstract && !type.IsInterface)
-                    {
-                        constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor;
-                    }
-
                     // GetInterface() is currently not implemented, so we use GetInterfaces().
-                    IEnumerable<string> interfaces = type.GetInterfaces().Select(interfaceType => interfaceType.FullName);
+                    IEnumerable<string> interfaces = type.GetInterfaces().Select(interfaceType => interfaceType.FullName!);
                     implementsIJsonOnSerialized = interfaces.FirstOrDefault(interfaceName => interfaceName == IJsonOnSerializedFullName) != null;
                     implementsIJsonOnSerializing = interfaces.FirstOrDefault(interfaceName => interfaceName == IJsonOnSerializingFullName) != null;
 
@@ -648,11 +782,8 @@ namespace System.Text.Json.SourceGeneration
 
                 typeMetadata.Initialize(
                     generationMode,
-                    typeRef: type.GetUniqueCompilableTypeName(),
-                    typeInfoPropertyName: type.GetFriendlyTypeName(),
                     type,
                     classType,
-                    isValueType: type.IsValueType,
                     numberHandling,
                     propGenSpecList,
                     collectionType,
@@ -667,6 +798,9 @@ namespace System.Text.Json.SourceGeneration
                 return typeMetadata;
             }
 
+            private Type GetCompatibleGenericBaseClass(Type type, Type baseType)
+                => type.GetCompatibleGenericBaseClass(baseType, _objectType);
+
             private void CacheMember(
                 PropertyGenerationSpec propGenSpec,
                 ref List<PropertyGenerationSpec> propGenSpecList,
@@ -860,7 +994,7 @@ namespace System.Text.Json.SourceGeneration
                     Order = order,
                     HasJsonInclude = hasJsonInclude,
                     TypeGenerationSpec = GetOrAddTypeGenerationSpec(memberCLRType, generationMode),
-                    DeclaringTypeRef = $"global::{memberInfo.DeclaringType.GetUniqueCompilableTypeName()}",
+                    DeclaringTypeRef = memberInfo.DeclaringType.GetCompilableName(),
                     ConverterInstantiationLogic = converterInstantiationLogic
                 };
             }
@@ -883,7 +1017,7 @@ namespace System.Text.Json.SourceGeneration
                     return null;
                 }
 
-                return $"new {converterType.GetUniqueCompilableTypeName()}()";
+                return $"new {converterType.GetCompilableName()}()";
             }
 
             private static string DetermineRuntimePropName(string clrPropName, string? jsonPropName, JsonKnownNamingPolicy namingPolicy)
@@ -909,23 +1043,22 @@ namespace System.Text.Json.SourceGeneration
             private void PopulateNumberTypes()
             {
                 Debug.Assert(_numberTypes != null);
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(byte)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(decimal)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(double)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(short)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(sbyte)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(int)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(long)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(float)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(ushort)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(uint)));
-                _numberTypes.Add(_metadataLoadContext.Resolve(typeof(ulong)));
+                _numberTypes.Add(ResolveType(SpecialType.System_Byte));
+                _numberTypes.Add(ResolveType(SpecialType.System_Decimal));
+                _numberTypes.Add(ResolveType(SpecialType.System_Double));
+                _numberTypes.Add(ResolveType(SpecialType.System_Int16));
+                _numberTypes.Add(ResolveType(SpecialType.System_SByte));
+                _numberTypes.Add(ResolveType(SpecialType.System_Int32));
+                _numberTypes.Add(ResolveType(SpecialType.System_Int64));
+                _numberTypes.Add(ResolveType(SpecialType.System_Single));
+                _numberTypes.Add(ResolveType(SpecialType.System_UInt64));
+                _numberTypes.Add(ResolveType(SpecialType.System_UInt32));
+                _numberTypes.Add(ResolveType(SpecialType.System_UInt64));
             }
 
             private void PopulateKnownTypes()
             {
                 PopulateNumberTypes();
-
                 Debug.Assert(_knownTypes != null);
                 Debug.Assert(_numberTypes != null);
 
@@ -936,16 +1069,23 @@ namespace System.Text.Json.SourceGeneration
                 _knownTypes.Add(_dateTimeType);
                 _knownTypes.Add(_dateTimeOffsetType);
                 _knownTypes.Add(_guidType);
-                _knownTypes.Add(_metadataLoadContext.Resolve(typeof(object)));
+                _knownTypes.Add(_objectType);
                 _knownTypes.Add(_stringType);
+                _knownTypes.Add(_uriType);
+                _knownTypes.Add(_versionType);
+                _knownTypes.Add(_jsonElementType);
+            }
 
-                // System.Private.Uri may not be loaded in input compilation.
-                if (_uriType != null)
-                {
-                    _knownTypes.Add(_uriType);
-                }
+            private Type ResolveType(string fullyQualifiedMetadataName)
+            {
+                INamedTypeSymbol? typeSymbol = _executionContext.Compilation.GetTypeByMetadataName(fullyQualifiedMetadataName);
+                return typeSymbol.AsType(_metadataLoadContext);
+            }
 
-                _knownTypes.Add(_metadataLoadContext.Resolve(typeof(Version)));
+            private Type ResolveType(SpecialType specialType)
+            {
+                INamedTypeSymbol? typeSymbol = _executionContext.Compilation.GetSpecialType(specialType);
+                return typeSymbol.AsType(_metadataLoadContext);
             }
         }
     }
index e518212..5835416 100644 (file)
@@ -25,10 +25,18 @@ namespace System.Text.Json.Reflection
             }
 
             var constructorArguments = new List<CustomAttributeTypedArgument>();
+
             foreach (TypedConstant ca in a.ConstructorArguments)
             {
-                constructorArguments.Add(new CustomAttributeTypedArgument(ca.Type.AsType(metadataLoadContext), ca.Value));
+                if (ca.Kind == TypedConstantKind.Error)
+                {
+                    continue;
+                }
+
+                object value = ca.Kind == TypedConstantKind.Array ? ca.Values : ca.Value;
+                constructorArguments.Add(new CustomAttributeTypedArgument(ca.Type.AsType(metadataLoadContext), value));
             }
+
             Constructor = new ConstructorInfoWrapper(a.AttributeConstructor!, metadataLoadContext);
             NamedArguments = namedArguments;
             ConstructorArguments = constructorArguments;
index d12f3f8..1d87aa8 100644 (file)
@@ -43,8 +43,6 @@ namespace System.Text.Json.Reflection
             MainAssembly = new AssemblyWrapper(compilation.Assembly, this);
         }
 
-        public Type Resolve<T>() => Resolve(typeof(T));
-
         public Type? Resolve(Type type)
         {
             string assemblyName = type.Assembly.GetName().Name;
index 6ad76f4..ba20339 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 
@@ -8,34 +9,75 @@ namespace System.Text.Json.Reflection
 {
     internal static class TypeExtensions
     {
-        public static string GetUniqueCompilableTypeName(this Type type) => GetCompilableTypeName(type, type.FullName);
+        public static string GetCompilableName(this Type type)
+        {
+            if (type.IsArray)
+            {
+                return GetCompilableName(type.GetElementType()) + "[]";
+            }
 
-        public static string GetCompilableTypeName(this Type type) => GetCompilableTypeName(type, type.Name);
+            string compilableName;
 
-        private static string GetCompilableTypeName(Type type, string name)
-        {
             if (!type.IsGenericType)
             {
-                return name.Replace('+', '.');
+                compilableName = type.FullName;
             }
+            else
+            {
+                StringBuilder sb = new();
 
-            // TODO: Guard upstream against open generics.
-            Debug.Assert(!type.ContainsGenericParameters);
+                string fullName = type.FullName;
+                int backTickIndex = fullName.IndexOf('`');
 
-            int backTickIndex = name.IndexOf('`');
-            string baseName = name.Substring(0, backTickIndex).Replace('+', '.');
+                string baseName = fullName.Substring(0, backTickIndex);
 
-            return $"{baseName}<{string.Join(",", type.GetGenericArguments().Select(arg => GetUniqueCompilableTypeName(arg)))}>";
-        }
+                sb.Append(baseName);
 
-        public static string GetFriendlyTypeName(this Type type)
-        {
-            return GetFriendlyTypeName(type.GetCompilableTypeName());
+                sb.Append("<");
+
+                Type[] genericArgs = type.GetGenericArguments();
+                int genericArgCount = genericArgs.Length;
+                List<string> genericArgNames = new(genericArgCount);
+
+                for (int i = 0; i < genericArgCount; i++)
+                {
+                    genericArgNames.Add(GetCompilableName(genericArgs[i]));
+                }
+
+                sb.Append(string.Join(", ", genericArgNames));
+
+                sb.Append(">");
+
+                compilableName = sb.ToString();
+            }
+
+            compilableName = compilableName.Replace("+", ".");
+            return "global::" + compilableName;
         }
 
-        private static string GetFriendlyTypeName(string compilableName)
+        public static string GetTypeInfoPropertyName(this Type type)
         {
-            return compilableName.Replace(".", "").Replace("<", "").Replace(">", "").Replace(",", "").Replace("[]", "Array");
+            if (type.IsArray)
+            {
+                return GetTypeInfoPropertyName(type.GetElementType()) + "Array";
+            }
+            else if (!type.IsGenericType)
+            {
+                return type.Name;
+            }
+
+            StringBuilder sb = new();
+
+            string name = ((TypeWrapper)type).SimpleName;
+
+            sb.Append(name);
+
+            foreach (Type genericArg in type.GetGenericArguments())
+            {
+                sb.Append(GetTypeInfoPropertyName(genericArg));
+            }
+
+            return sb.ToString();
         }
 
         public static bool IsNullableValueType(this Type type, Type nullableOfTType, out Type? underlyingType)
index abeed3d..db2c79a 100644 (file)
@@ -43,9 +43,38 @@ namespace System.Text.Json.Reflection
                 {
                     StringBuilder sb = new();
 
-                    AssemblyIdentity identity = _typeSymbol.ContainingAssembly.Identity;
+                    AssemblyIdentity identity;
 
-                    sb.Append(FullName);
+                    if (_arrayTypeSymbol == null)
+                    {
+                        identity = _typeSymbol.ContainingAssembly.Identity;
+                        sb.Append(FullName);
+                    }
+                    else
+                    {
+                        TypeWrapper currentType = this;
+                        int nestCount = 1;
+
+                        while (true)
+                        {
+                            currentType = (TypeWrapper)currentType.GetElementType();
+
+                            if (!currentType.IsArray)
+                            {
+                                break;
+                            }
+
+                            nestCount++;
+                        }
+
+                        identity = currentType._typeSymbol.ContainingAssembly.Identity;
+                        sb.Append(currentType.FullName);
+
+                        for (int i = 0; i < nestCount; i++)
+                        {
+                            sb.Append("[]");
+                        }
+                    }
 
                     sb.Append(", ");
                     sb.Append(identity.Name);
@@ -97,6 +126,10 @@ namespace System.Text.Json.Reflection
                         sb.Append(underlyingType.AssemblyQualifiedName);
                         sb.Append("]]");
                     }
+                    else if (IsArray)
+                    {
+                        sb.Append(GetElementType().FullName + "[]");
+                    }
                     else
                     {
                         sb.Append(Name);
@@ -110,7 +143,22 @@ namespace System.Text.Json.Reflection
                         {
                             sb.Insert(0, $"{Namespace}.");
                         }
+
+                        if (this.IsGenericType && !ContainsGenericParameters)
+                        {
+                            sb.Append("[");
+
+                            foreach (Type genericArg in GetGenericArguments())
+                            {
+                                sb.Append("[");
+                                sb.Append(genericArg.AssemblyQualifiedName);
+                                sb.Append("]");
+                            }
+
+                            sb.Append("]");
+                        }
                     }
+                    
 
                     _fullName = sb.ToString();
                 }
@@ -144,6 +192,8 @@ namespace System.Text.Json.Reflection
             }
         }
 
+        public string SimpleName => _typeSymbol.Name;
+
         private Type _enumType;
 
         public override bool IsEnum
@@ -190,11 +240,21 @@ namespace System.Text.Json.Reflection
 
         public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
         {
-            var ctors = new List<ConstructorInfo>();
+            if (_namedTypeSymbol == null)
+            {
+                return Array.Empty<ConstructorInfo>();
+            }
+
+            List<ConstructorInfo> ctors = new();
+
             foreach (IMethodSymbol c in _namedTypeSymbol.Constructors)
             {
-                ctors.Add(new ConstructorInfoWrapper(c, _metadataLoadContext));
+                if (c.DeclaredAccessibility == Accessibility.Public)
+                {
+                    ctors.Add(new ConstructorInfoWrapper(c, _metadataLoadContext));
+                }
             }
+
             return ctors.ToArray();
         }
 
@@ -268,7 +328,7 @@ namespace System.Text.Json.Reflection
         public override Type[] GetInterfaces()
         {
             var interfaces = new List<Type>();
-            foreach (INamedTypeSymbol i in _typeSymbol.Interfaces)
+            foreach (INamedTypeSymbol i in _typeSymbol.AllInterfaces)
             {
                 interfaces.Add(i.AsType(_metadataLoadContext));
             }
@@ -484,6 +544,16 @@ namespace System.Text.Json.Reflection
         public override int GetHashCode() => _typeSymbol.GetHashCode();
 #pragma warning restore RS1024 // Compare symbols correctly
 
+        public override int GetArrayRank()
+        {
+            if (_arrayTypeSymbol == null)
+            {
+                throw new ArgumentException("Must be an array type.");
+            }
+
+            return _arrayTypeSymbol.Rank;
+        }
+
         public override bool Equals(object o)
         {
             if (o is TypeWrapper tw)
index 8651348..9241d57 100644 (file)
@@ -57,13 +57,43 @@ namespace System.Text.Json.SourceGeneration
 
         public string? ConverterInstantiationLogic { get; private set; }
 
+        public string FastPathSerializeMethodName
+        {
+            get
+            {
+                Debug.Assert(GenerateSerializationLogic);
+                return $"{TypeInfoPropertyName}Serialize";
+            }
+        }
+
+        public string? ImmutableCollectionBuilderName
+        {
+            get
+            {
+                string builderName;
+
+                if (CollectionType == CollectionType.ImmutableDictionary)
+                {
+                    builderName = Type.GetImmutableDictionaryConstructingTypeName(sourceGenType: true);
+                }
+                else if (CollectionType == CollectionType.ImmutableEnumerable)
+                {
+                    builderName = Type.GetImmutableEnumerableConstructingTypeName(sourceGenType: true);
+                }
+                else
+                {
+                    return null;
+                }
+
+                Debug.Assert(builderName != null);
+                return $"global::{builderName}.{ReflectionExtensions.CreateRangeMethodName}";
+            }
+        }
+
         public void Initialize(
             JsonSourceGenerationMode generationMode,
-            string typeRef,
-            string typeInfoPropertyName,
             Type type,
             ClassType classType,
-            bool isValueType,
             JsonNumberHandling? numberHandling,
             List<PropertyGenerationSpec>? propertyGenSpecList,
             CollectionType collectionType,
@@ -76,12 +106,12 @@ namespace System.Text.Json.SourceGeneration
             bool implementsIJsonOnSerializing)
         {
             GenerationMode = generationMode;
-            TypeRef = $"global::{typeRef}";
-            TypeInfoPropertyName = typeInfoPropertyName;
+            TypeRef = type.GetCompilableName();
+            TypeInfoPropertyName = type.GetTypeInfoPropertyName();
             Type = type;
             ClassType = classType;
-            IsValueType = isValueType;
-            CanBeNull = !isValueType || nullableUnderlyingTypeMetadata != null;
+            IsValueType = type.IsValueType;
+            CanBeNull = !IsValueType || nullableUnderlyingTypeMetadata != null;
             NumberHandling = numberHandling;
             PropertyGenSpecList = propertyGenSpecList;
             CollectionType = collectionType;
@@ -178,20 +208,31 @@ ReturnFalse:
         {
             if (ClassType == ClassType.Object)
             {
-                return true;
-            }
+                foreach (PropertyGenerationSpec property in PropertyGenSpecList)
+                {
+                    if (property.TypeGenerationSpec.Type.IsObjectType())
+                    {
+                        return false;
+                    }
+                }
 
-            if (CollectionType == CollectionType.Array || CollectionType == CollectionType.List)
-            {
-                return !CollectionValueTypeMetadata!.Type.IsObjectType();
+                return true;
             }
 
-            if (CollectionType == CollectionType.Dictionary)
+            switch (CollectionType)
             {
-                return CollectionKeyTypeMetadata!.Type.IsStringType() && !CollectionValueTypeMetadata!.Type.IsObjectType();
+                case CollectionType.NotApplicable:
+                    return false;
+                case CollectionType.IDictionary:
+                case CollectionType.Dictionary:
+                case CollectionType.ImmutableDictionary:
+                case CollectionType.IDictionaryOfTKeyTValue:
+                case CollectionType.IReadOnlyDictionary:
+                    return CollectionKeyTypeMetadata!.Type.IsStringType() && !CollectionValueTypeMetadata!.Type.IsObjectType();
+                default:
+                    // Non-dictionary collections
+                    return !CollectionValueTypeMetadata!.Type.IsObjectType();
             }
-
-            return false;
         }
 
         private bool GenerationModeIsSpecified(JsonSourceGenerationMode mode) => GenerationMode == JsonSourceGenerationMode.Default || (mode & GenerationMode) != 0;
index 97e3931..58b6d52 100644 (file)
@@ -919,6 +919,7 @@ namespace System.Text.Json.Serialization.Metadata
         public static System.Text.Json.Serialization.JsonConverter<short> Int16Converter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<int> Int32Converter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<long> Int64Converter { get { throw null; } }
+        public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.JsonElement> JsonElementConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<object> ObjectConverter { get { throw null; } }
         [System.CLSCompliantAttribute(false)]
         public static System.Text.Json.Serialization.JsonConverter<sbyte> SByteConverter { get { throw null; } }
@@ -934,10 +935,26 @@ namespace System.Text.Json.Serialization.Metadata
         public static System.Text.Json.Serialization.JsonConverter<System.Uri> UriConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<System.Version> VersionConverter { get { throw null; } }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TElement[]>? serializeFunc) { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentQueue<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentStack<TElement> { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection> createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo keyInfo, System.Text.Json.Serialization.Metadata.JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Dictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static JsonTypeInfo<TCollection> CreateICollectionInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.ICollection<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, JsonTypeInfo stringInfo, JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IDictionary { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection> createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IEnumerable { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IList { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IList<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateImmutableDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection> createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Func<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static JsonTypeInfo<TCollection> CreateImmutableEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Func<System.Collections.Generic.IEnumerable<TElement>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateIReadOnlyDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection> createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static JsonTypeInfo<TCollection> CreateISetInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.ISet<TElement> { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.List<TElement> { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<T> CreateObjectInfo<T>(System.Text.Json.JsonSerializerOptions options, System.Func<T>? createObjectFunc, System.Func<System.Text.Json.Serialization.JsonSerializerContext, System.Text.Json.Serialization.Metadata.JsonPropertyInfo[]>? propInitFunc, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, T>? serializeFunc) where T : notnull { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo<T>(System.Text.Json.JsonSerializerOptions options, bool isProperty, bool isPublic, bool isVirtual, System.Type declaringType, System.Text.Json.Serialization.Metadata.JsonTypeInfo propertyTypeInfo, System.Text.Json.Serialization.JsonConverter<T>? converter, System.Func<object, T>? getter, System.Action<object, T>? setter, System.Text.Json.Serialization.JsonIgnoreCondition? ignoreCondition, bool hasJsonInclude, System.Text.Json.Serialization.JsonNumberHandling? numberHandling, string propertyName, string? jsonPropertyName) { throw null; }
+        public static JsonTypeInfo<TCollection> CreateQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Queue<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Stack<TElement> { throw null; }
+        public static JsonTypeInfo<TCollection> CreateStackOrQueueInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Action<TCollection, object?> addFunc) where TCollection : System.Collections.IEnumerable { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<T> CreateValueInfo<T>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) { throw null; }
         public static System.Text.Json.Serialization.JsonConverter<T> GetEnumConverter<T>(System.Text.Json.JsonSerializerOptions options) where T : struct { throw null; }
         public static System.Text.Json.Serialization.JsonConverter<T?> GetNullableConverter<T>(System.Text.Json.Serialization.Metadata.JsonTypeInfo<T> underlyingTypeInfo) where T : struct { throw null; }
index f015d29..5244502 100644 (file)
     <Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\RequiresUnreferencedCodeAttribute.cs" />
   </ItemGroup>
   <ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
+    <ProjectReference Include="$(LibrariesProjectRoot)System.Collections.Concurrent\ref\System.Collections.Concurrent.csproj" />
     <ProjectReference Include="$(LibrariesProjectRoot)System.Memory\ref\System.Memory.csproj" />
     <ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\ref\System.Runtime.csproj" />
   </ItemGroup>
   <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
     <Reference Include="System.Collections" />
+    <Reference Include="System.Collections.Concurrent" />
     <Reference Include="System.Memory" />
     <Reference Include="System.Runtime" />
     <Reference Include="netstandard" />
index d9ad161..9de2b82 100644 (file)
@@ -3,7 +3,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
+using System.Text.Json.Reflection;
 using System.Text.Json.Serialization.Converters;
 
 namespace System.Text.Json.Serialization
@@ -26,6 +26,6 @@ namespace System.Text.Json.Serialization
         }
 
         private static Type? GetAsyncEnumerableInterface(Type type)
-            => IEnumerableConverterFactoryHelpers.GetCompatibleGenericInterface(type, typeof(IAsyncEnumerable<>));
+            => type.GetCompatibleGenericInterface(typeof(IAsyncEnumerable<>));
     }
 }
index 819de1f..d015f7f 100644 (file)
@@ -4,7 +4,7 @@
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
-using System.Text.Json.Serialization.Metadata;
+using System.Text.Json.Reflection;
 
 namespace System.Text.Json.Serialization
 {
@@ -14,142 +14,9 @@ namespace System.Text.Json.Serialization
         // any netstandard2.0 consumers don't need to reference System.Collections.Immutable.
         // So instead, implement a "weak reference" by using strings to check for Immutable types.
 
-        // Immutable collection types.
-        private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
-        private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
-        private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
-        private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
-        private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
-        private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
-        private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
-        private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
-        private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
-        private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
-        private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
-        private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2";
-        private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2";
-
-        // Immutable collection builder types.
-        private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
-        private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
-        private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
-        private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
-        private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
-        private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
-        private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
-        private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary";
-
-        private const string CreateRangeMethodName = "CreateRange";
-
         // Don't use DynamicDependency attributes to the Immutable Collection types so they can be trimmed in applications that don't use Immutable Collections.
         internal const string ImmutableConvertersUnreferencedCodeMessage = "System.Collections.Immutable converters use Reflection to find and create Immutable Collection types, which requires unreferenced code.";
 
-        internal static Type? GetCompatibleGenericBaseClass(this Type type, Type baseType)
-        {
-            Debug.Assert(baseType.IsGenericType);
-            Debug.Assert(!baseType.IsInterface);
-            Debug.Assert(baseType == baseType.GetGenericTypeDefinition());
-
-            Type? baseTypeToCheck = type;
-
-            while (baseTypeToCheck != null && baseTypeToCheck != JsonTypeInfo.ObjectType)
-            {
-                if (baseTypeToCheck.IsGenericType)
-                {
-                    Type genericTypeToCheck = baseTypeToCheck.GetGenericTypeDefinition();
-                    if (genericTypeToCheck == baseType)
-                    {
-                        return baseTypeToCheck;
-                    }
-                }
-
-                baseTypeToCheck = baseTypeToCheck.BaseType;
-            }
-
-            return null;
-        }
-
-        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
-            Justification = "The 'interfaceType' must exist and so trimmer kept it. In which case " +
-                "It also kept it on any type which implements it. The below call to GetInterfaces " +
-                "may return fewer results when trimmed but it will return the 'interfaceType' " +
-                "if the type implemented it, even after trimming.")]
-        internal static Type? GetCompatibleGenericInterface(this Type type, Type interfaceType)
-        {
-            Debug.Assert(interfaceType.IsGenericType);
-            Debug.Assert(interfaceType.IsInterface);
-            Debug.Assert(interfaceType == interfaceType.GetGenericTypeDefinition());
-
-            Type interfaceToCheck = type;
-
-            if (interfaceToCheck.IsGenericType)
-            {
-                interfaceToCheck = interfaceToCheck.GetGenericTypeDefinition();
-            }
-
-            if (interfaceToCheck == interfaceType)
-            {
-                return type;
-            }
-
-            foreach (Type typeToCheck in type.GetInterfaces())
-            {
-                if (typeToCheck.IsGenericType)
-                {
-                    Type genericInterfaceToCheck = typeToCheck.GetGenericTypeDefinition();
-                    if (genericInterfaceToCheck == interfaceType)
-                    {
-                        return typeToCheck;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static bool IsImmutableDictionaryType(this Type type)
-        {
-            if (!type.IsGenericType || !type.Assembly.FullName!.StartsWith("System.Collections.Immutable,", StringComparison.Ordinal))
-            {
-                return false;
-            }
-
-            switch (type.GetGenericTypeDefinition().FullName)
-            {
-                case ImmutableDictionaryGenericTypeName:
-                case ImmutableDictionaryGenericInterfaceTypeName:
-                case ImmutableSortedDictionaryGenericTypeName:
-                    return true;
-                default:
-                    return false;
-            }
-        }
-
-        public static bool IsImmutableEnumerableType(this Type type)
-        {
-            if (!type.IsGenericType|| !type.Assembly.FullName!.StartsWith("System.Collections.Immutable,", StringComparison.Ordinal))
-            {
-                return false;
-            }
-
-            switch (type.GetGenericTypeDefinition().FullName)
-            {
-                case ImmutableArrayGenericTypeName:
-                case ImmutableListGenericTypeName:
-                case ImmutableListGenericInterfaceTypeName:
-                case ImmutableStackGenericTypeName:
-                case ImmutableStackGenericInterfaceTypeName:
-                case ImmutableQueueGenericTypeName:
-                case ImmutableQueueGenericInterfaceTypeName:
-                case ImmutableSortedSetGenericTypeName:
-                case ImmutableHashSetGenericTypeName:
-                case ImmutableSetGenericInterfaceTypeName:
-                    return true;
-                default:
-                    return false;
-            }
-        }
-
         [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
         public static MethodInfo GetImmutableEnumerableCreateRangeMethod(this Type type, Type elementType)
         {
@@ -159,7 +26,7 @@ namespace System.Text.Json.Serialization
                 MethodInfo[] constructingTypeMethods = constructingType.GetMethods();
                 foreach (MethodInfo method in constructingTypeMethods)
                 {
-                    if (method.Name == CreateRangeMethodName &&
+                    if (method.Name == ReflectionExtensions.CreateRangeMethodName &&
                         method.GetParameters().Length == 1 &&
                         method.IsGenericMethod &&
                         method.GetGenericArguments().Length == 1)
@@ -182,7 +49,7 @@ namespace System.Text.Json.Serialization
                 MethodInfo[] constructingTypeMethods = constructingType.GetMethods();
                 foreach (MethodInfo method in constructingTypeMethods)
                 {
-                    if (method.Name == CreateRangeMethodName &&
+                    if (method.Name == ReflectionExtensions.CreateRangeMethodName &&
                         method.GetParameters().Length == 1 &&
                         method.IsGenericMethod &&
                         method.GetGenericArguments().Length == 2)
@@ -201,43 +68,11 @@ namespace System.Text.Json.Serialization
         {
             Debug.Assert(type.IsImmutableEnumerableType());
 
-            // Use the generic type definition of the immutable collection to determine
-            // an appropriate constructing type, i.e. a type that we can invoke the
-            // `CreateRange<T>` method on, which returns the desired immutable collection.
-            Type underlyingType = type.GetGenericTypeDefinition();
-            string constructingTypeName;
-
-            switch (underlyingType.FullName)
-            {
-                case ImmutableArrayGenericTypeName:
-                    constructingTypeName = ImmutableArrayTypeName;
-                    break;
-                case ImmutableListGenericTypeName:
-                case ImmutableListGenericInterfaceTypeName:
-                    constructingTypeName = ImmutableListTypeName;
-                    break;
-                case ImmutableStackGenericTypeName:
-                case ImmutableStackGenericInterfaceTypeName:
-                    constructingTypeName = ImmutableStackTypeName;
-                    break;
-                case ImmutableQueueGenericTypeName:
-                case ImmutableQueueGenericInterfaceTypeName:
-                    constructingTypeName = ImmutableQueueTypeName;
-                    break;
-                case ImmutableSortedSetGenericTypeName:
-                    constructingTypeName = ImmutableSortedSetTypeName;
-                    break;
-                case ImmutableHashSetGenericTypeName:
-                case ImmutableSetGenericInterfaceTypeName:
-                    constructingTypeName = ImmutableHashSetTypeName;
-                    break;
-                default:
-                    // We verified that the type is an immutable collection, so the
-                    // generic definition is one of the above.
-                    return null;
-            }
+            string? constructingTypeName = type.GetImmutableEnumerableConstructingTypeName();
 
-            return underlyingType.Assembly.GetType(constructingTypeName);
+            return constructingTypeName == null
+                ? null
+                : type.Assembly.GetType(constructingTypeName);
         }
 
         [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
@@ -245,28 +80,11 @@ namespace System.Text.Json.Serialization
         {
             Debug.Assert(type.IsImmutableDictionaryType());
 
-            // Use the generic type definition of the immutable collection to determine
-            // an appropriate constructing type, i.e. a type that we can invoke the
-            // `CreateRange<T>` method on, which returns the desired immutable collection.
-            Type underlyingType = type.GetGenericTypeDefinition();
-            string constructingTypeName;
-
-            switch (underlyingType.FullName)
-            {
-                case ImmutableDictionaryGenericTypeName:
-                case ImmutableDictionaryGenericInterfaceTypeName:
-                    constructingTypeName = ImmutableDictionaryTypeName;
-                    break;
-                case ImmutableSortedDictionaryGenericTypeName:
-                    constructingTypeName = ImmutableSortedDictionaryTypeName;
-                    break;
-                default:
-                    // We verified that the type is an immutable collection, so the
-                    // generic definition is one of the above.
-                    return null;
-            }
+            string? constructingTypeName = type.GetImmutableDictionaryConstructingTypeName();
 
-            return underlyingType.Assembly.GetType(constructingTypeName);
+            return constructingTypeName == null
+                ? null
+                : type.Assembly.GetType(constructingTypeName);
         }
 
         public static bool IsNonGenericStackOrQueue(this Type type)
index 6aa72b3..6363e8a 100644 (file)
@@ -15,6 +15,9 @@ namespace System.Text.Json.Serialization.Converters
         [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
         public IEnumerableWithAddMethodConverter() { }
 
+        // Used by source-gen initialization for reflection-free serialization.
+        public IEnumerableWithAddMethodConverter(bool dummy) { }
+
         protected override void Add(in object? value, ref ReadStack state)
         {
             var addMethodDelegate = ((Action<TCollection, object?>?)state.Current.JsonTypeInfo.AddMethodDelegate);
@@ -22,8 +25,6 @@ namespace System.Text.Json.Serialization.Converters
             addMethodDelegate((TCollection)state.Current.ReturnValue!, value);
         }
 
-        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:UnrecognizedReflectionPattern",
-            Justification = "The ctor is marked RequiresUnreferencedCode.")]
         protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
         {
             JsonTypeInfo typeInfo = state.Current.JsonTypeInfo;
@@ -36,12 +37,7 @@ namespace System.Text.Json.Serialization.Converters
 
             state.Current.ReturnValue = constructorDelegate();
 
-            // Initialize add method used to populate the collection.
-            if (typeInfo.AddMethodDelegate == null)
-            {
-                // We verified this exists when we created the converter in the enumerable converter factory.
-                typeInfo.AddMethodDelegate = options.MemberAccessorStrategy.CreateAddMethodDelegate<TCollection>();
-            }
+            Debug.Assert(typeInfo.AddMethodDelegate != null);
         }
 
         protected override bool OnWriteResume(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, ref WriteStack state)
@@ -79,5 +75,15 @@ namespace System.Text.Json.Serialization.Converters
 
             return true;
         }
+
+        internal override bool RequiresDynamicMemberAccessors => true;
+
+        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:UnrecognizedReflectionPattern",
+            Justification = "The ctor is marked RequiresUnreferencedCode.")]
+        internal override void Initialize(JsonSerializerOptions options, JsonTypeInfo? jsonTypeInfo = null)
+        {
+            Debug.Assert(jsonTypeInfo != null);
+            jsonTypeInfo.AddMethodDelegate = options.MemberAccessorStrategy.CreateAddMethodDelegate<TCollection>();
+        }
     }
 }
index 7923890..316a9a3 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Text.Json.Serialization.Metadata;
 
@@ -17,6 +18,9 @@ namespace System.Text.Json.Serialization.Converters
         {
         }
 
+        // Used by source-gen initialization for reflection-free serialization.
+        public ImmutableDictionaryOfTKeyTValueConverter(bool dummy) { }
+
         protected override void Add(TKey key, in TValue value, JsonSerializerOptions options, ref ReadStack state)
         {
             ((Dictionary<TKey, TValue>)state.Current.ReturnValue!)[key] = value;
@@ -24,24 +28,18 @@ namespace System.Text.Json.Serialization.Converters
 
         internal override bool CanHaveIdMetadata => false;
 
+        internal override bool RequiresDynamicMemberAccessors => true;
+
         protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state)
         {
             state.Current.ReturnValue = new Dictionary<TKey, TValue>();
         }
 
-        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
-            Justification = "The ctor is marked RequiresUnreferencedCode.")]
         protected override void ConvertCollection(ref ReadStack state, JsonSerializerOptions options)
         {
-            JsonTypeInfo typeInfo = state.Current.JsonTypeInfo;
-
-            Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>? creator = (Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>?)typeInfo.CreateObjectWithArgs;
-            if (creator == null)
-            {
-                creator = options.MemberAccessorStrategy.CreateImmutableDictionaryCreateRangeDelegate<TCollection, TKey, TValue>();
-                typeInfo.CreateObjectWithArgs = creator;
-            }
-
+            Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>? creator =
+                (Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection>?)state.Current.JsonTypeInfo.CreateObjectWithArgs;
+            Debug.Assert(creator != null);
             state.Current.ReturnValue = creator((Dictionary<TKey, TValue>)state.Current.ReturnValue!);
         }
 
@@ -95,5 +93,13 @@ namespace System.Text.Json.Serialization.Converters
             enumerator.Dispose();
             return true;
         }
+
+        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+            Justification = "The ctor is marked RequiresUnreferencedCode.")]
+        internal override void Initialize(JsonSerializerOptions options, JsonTypeInfo? jsonTypeInfo = null)
+        {
+            Debug.Assert(jsonTypeInfo != null);
+            jsonTypeInfo.CreateObjectWithArgs = options.MemberAccessorStrategy.CreateImmutableDictionaryCreateRangeDelegate<TCollection, TKey, TValue>();
+        }
     }
 }
index d65807b..f2f2810 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Text.Json.Serialization.Metadata;
 
@@ -16,6 +17,9 @@ namespace System.Text.Json.Serialization.Converters
         {
         }
 
+        // Used by source-gen initialization for reflection-free serialization.
+        public ImmutableEnumerableOfTConverter(bool dummy) { }
+
         protected override void Add(in TElement value, ref ReadStack state)
         {
             ((List<TElement>)state.Current.ReturnValue!).Add(value);
@@ -23,24 +27,19 @@ namespace System.Text.Json.Serialization.Converters
 
         internal override bool CanHaveIdMetadata => false;
 
+        internal override bool RequiresDynamicMemberAccessors => true;
+
         protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
         {
             state.Current.ReturnValue = new List<TElement>();
         }
 
-        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
-            Justification = "The ctor is marked RequiresUnreferencedCode.")]
         protected override void ConvertCollection(ref ReadStack state, JsonSerializerOptions options)
         {
             JsonTypeInfo typeInfo = state.Current.JsonTypeInfo;
 
             Func<IEnumerable<TElement>, TCollection>? creator = (Func<IEnumerable<TElement>, TCollection>?)typeInfo.CreateObjectWithArgs;
-            if (creator == null)
-            {
-                creator = options.MemberAccessorStrategy.CreateImmutableEnumerableCreateRangeDelegate<TCollection, TElement>();
-                typeInfo.CreateObjectWithArgs = creator;
-            }
-
+            Debug.Assert(creator != null);
             state.Current.ReturnValue = creator((List<TElement>)state.Current.ReturnValue!);
         }
 
@@ -81,5 +80,13 @@ namespace System.Text.Json.Serialization.Converters
             enumerator.Dispose();
             return true;
         }
+
+        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+            Justification = "The ctor is marked RequiresUnreferencedCode.")]
+        internal override void Initialize(JsonSerializerOptions options, JsonTypeInfo? jsonTypeInfo = null)
+        {
+            Debug.Assert(jsonTypeInfo != null);
+            jsonTypeInfo.CreateObjectWithArgs = options.MemberAccessorStrategy.CreateImmutableEnumerableCreateRangeDelegate<TCollection, TElement>();
+        }
     }
 }
index 016702c..f769427 100644 (file)
@@ -23,7 +23,7 @@ namespace System.Text.Json.Serialization.Converters
         private static readonly ConstructorInfo s_constructorInfo =
             typeof(KeyValuePair<TKey, TValue>).GetConstructor(new[] { typeof(TKey), typeof(TValue) })!;
 
-        internal override void Initialize(JsonSerializerOptions options)
+        internal override void Initialize(JsonSerializerOptions options, JsonTypeInfo? jsonTypeInfo = null)
         {
             JsonNamingPolicy? namingPolicy = options.PropertyNamingPolicy;
             if (namingPolicy == null)
index f324f67..f590292 100644 (file)
@@ -114,7 +114,9 @@ namespace System.Text.Json.Serialization
 
         internal ConstructorInfo? ConstructorInfo { get; set; }
 
-        internal virtual void Initialize(JsonSerializerOptions options) { }
+        internal virtual bool RequiresDynamicMemberAccessors { get; }
+
+        internal virtual void Initialize(JsonSerializerOptions options, JsonTypeInfo? jsonTypeInfo = null) { }
 
         /// <summary>
         /// Creates the instance and assigns it to state.Current.ReturnValue.
index a302d92..e953bdf 100644 (file)
@@ -51,6 +51,7 @@ namespace System.Text.Json.Serialization
                             Options.IgnoreReadOnlyProperties == _defaultOptions.IgnoreReadOnlyProperties &&
                             Options.IncludeFields == _defaultOptions.IncludeFields &&
                             Options.PropertyNamingPolicy == _defaultOptions.PropertyNamingPolicy &&
+                            Options.DictionaryKeyPolicy == _defaultOptions.DictionaryKeyPolicy &&
                             Options.WriteIndented == _defaultOptions.WriteIndented;
                     }
                 }
index e0f846d..ef2b4d1 100644 (file)
@@ -1,6 +1,8 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Collections;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Text.Json.Serialization.Converters;
 
@@ -90,5 +92,471 @@ namespace System.Text.Json.Serialization.Metadata
                 serializeFunc,
                 typeof(TKey),
                 typeof(TValue));
+
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
+        /// <summary>
+        /// Creates metadata for <see cref="System.Collections.Immutable.ImmutableDictionary{TKey, TValue}"/> and
+        /// types assignable to <see cref="System.Collections.Immutable.IImmutableDictionary{TKey, TValue}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
+        /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
+        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="createRangeFunc">A method to create an immutable dictionary instance.</param>
+        /// <returns></returns>
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+        public static JsonTypeInfo<TCollection> CreateImmutableDictionaryInfo<TCollection, TKey, TValue>(
+            JsonSerializerOptions options,
+            Func<TCollection> createObjectFunc,
+            JsonTypeInfo keyInfo,
+            JsonTypeInfo valueInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection> createRangeFunc)
+            where TCollection : IReadOnlyDictionary<TKey, TValue>
+            where TKey : notnull
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ImmutableDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(dummy: false),
+                keyInfo,
+                valueInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TKey),
+                typeof(TValue),
+                createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IDictionary{TKey, TValue}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
+        /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
+        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection, TKey, TValue>(
+            JsonSerializerOptions options,
+            Func<TCollection> createObjectFunc,
+            JsonTypeInfo keyInfo,
+            JsonTypeInfo valueInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IDictionary<TKey, TValue>
+            where TKey : notnull
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
+                keyInfo,
+                valueInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TKey),
+                typeof(TValue));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IReadOnlyDictionary{TKey, TValue}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
+        /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
+        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIReadOnlyDictionaryInfo<TCollection, TKey, TValue>(
+            JsonSerializerOptions options,
+            Func<TCollection> createObjectFunc,
+            JsonTypeInfo keyInfo,
+            JsonTypeInfo valueInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IReadOnlyDictionary<TKey, TValue>
+            where TKey : notnull
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IReadOnlyDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
+                keyInfo,
+                valueInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TKey),
+                typeof(TValue));
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
+        /// <summary>
+        /// Creates metadata for non-dictionary immutable collection types.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="createRangeFunc">A method to create an immutable dictionary instance.</param>
+        /// <returns></returns>
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+        public static JsonTypeInfo<TCollection> CreateImmutableEnumerableInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            Func<IEnumerable<TElement>, TCollection> createRangeFunc)
+            where TCollection : IEnumerable<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ImmutableEnumerableOfTConverter<TCollection, TElement>(dummy: false),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement),
+                createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="objectInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo objectInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IList
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IListConverter<TCollection>(),
+                objectInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(object));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IList{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IList<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IListOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="ISet{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateISetInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : ISet<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ISetOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="ICollection{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateICollectionInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : ICollection<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ICollectionOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="Stack{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateStackInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : Stack<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new StackOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="Queue{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateQueueInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : Queue<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new QueueOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="ConcurrentStack{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateConcurrentStackInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : ConcurrentStack<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ConcurrentStackOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="Queue{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateConcurrentQueueInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : ConcurrentQueue<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new ConcurrentQueueOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IEnumerable{T}"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection, TElement>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IEnumerable<TElement>
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IEnumerableOfTConverter<TCollection, TElement>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(TElement));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IDictionary"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="stringInfo">A <see cref="JsonTypeInfo"/> instance representing <see cref="string"/> instances.</param>
+        /// <param name="objectInfo">A <see cref="JsonTypeInfo"/> instance representing <see cref="object"/> instances.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo stringInfo,
+            JsonTypeInfo objectInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IDictionary
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IDictionaryConverter<TCollection>(),
+                keyInfo: stringInfo,
+                valueInfo: objectInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(string),
+                typeof(object));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="addFunc">A method for adding elements to the collection when using the serializer's code-paths.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateStackOrQueueInfo<TCollection>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            Action<TCollection, object?> addFunc)
+            where TCollection : IEnumerable
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IEnumerableWithAddMethodConverter<TCollection>(dummy: false),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(object),
+                createObjectWithArgs: null,
+                addFunc: addFunc ?? throw new ArgumentNullException(nameof(addFunc)));
+
+        /// <summary>
+        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
+        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
+        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
+        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <returns></returns>
+        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection>(
+            JsonSerializerOptions options,
+            Func<TCollection>? createObjectFunc,
+            JsonTypeInfo elementInfo,
+            JsonNumberHandling numberHandling,
+            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            where TCollection : IEnumerable
+            => new JsonTypeInfoInternal<TCollection>(
+                options,
+                createObjectFunc,
+                () => new IEnumerableConverter<TCollection>(),
+                elementInfo,
+                numberHandling,
+                serializeFunc,
+                typeof(object));
     }
 }
index f51bc85..2a4078f 100644 (file)
@@ -82,7 +82,7 @@ namespace System.Text.Json.Serialization.Metadata
         /// <summary>
         /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonElement"/> values.
         /// </summary>
-        internal static JsonConverter<JsonElement> JsonElementConverter => s_jsonElementConverter ??= new JsonElementConverter();
+        public static JsonConverter<JsonElement> JsonElementConverter => s_jsonElementConverter ??= new JsonElementConverter();
         private static JsonConverter<JsonElement>? s_jsonElementConverter;
 
         /// <summary>
index 956fefe..a88cbd3 100644 (file)
@@ -303,12 +303,22 @@ namespace System.Text.Json.Serialization.Metadata
                 case ConverterStrategy.Enumerable:
                     {
                         CreateObject = Options.MemberAccessorStrategy.CreateConstructor(runtimeType);
+
+                        if (converter.RequiresDynamicMemberAccessors)
+                        {
+                            converter.Initialize(Options, this);
+                        }
                     }
                     break;
                 case ConverterStrategy.Dictionary:
                     {
                         KeyType = converter.KeyType;
                         CreateObject = Options.MemberAccessorStrategy.CreateConstructor(runtimeType);
+
+                        if (converter.RequiresDynamicMemberAccessors)
+                        {
+                            converter.Initialize(Options, this);
+                        }
                     }
                     break;
                 case ConverterStrategy.Value:
index b016ef9..6b59b13 100644 (file)
@@ -58,7 +58,10 @@ namespace System.Text.Json.Serialization.Metadata
             JsonTypeInfo? elementInfo,
             JsonNumberHandling numberHandling,
             Action<Utf8JsonWriter, T>? serializeFunc,
-            Type elementType) : base(typeof(T), options, ConverterStrategy.Enumerable)
+            Type elementType,
+            object? createObjectWithArgs = null,
+            object? addFunc = null)
+            : base(typeof(T), options, ConverterStrategy.Enumerable)
         {
             JsonConverter<T> converter = new JsonMetadataServicesConverter<T>(converterCreator, ConverterStrategy.Enumerable, keyType: null, elementType);
 
@@ -67,6 +70,8 @@ namespace System.Text.Json.Serialization.Metadata
             NumberHandling = numberHandling;
             PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options);
             Serialize = serializeFunc;
+            CreateObjectWithArgs = createObjectWithArgs;
+            AddMethodDelegate = addFunc;
             SetCreateObjectFunc(createObjectFunc);
         }
 
@@ -82,7 +87,9 @@ namespace System.Text.Json.Serialization.Metadata
             JsonNumberHandling numberHandling,
             Action<Utf8JsonWriter, T>? serializeFunc,
             Type keyType,
-            Type elementType) : base(typeof(T), options, ConverterStrategy.Dictionary)
+            Type elementType,
+            object? createObjectWithArgs = null)
+            : base(typeof(T), options, ConverterStrategy.Dictionary)
         {
             JsonConverter<T> converter = new JsonMetadataServicesConverter<T>(converterCreator, ConverterStrategy.Dictionary, keyType, elementType);
 
@@ -94,6 +101,7 @@ namespace System.Text.Json.Serialization.Metadata
             NumberHandling = numberHandling;
             PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options);
             Serialize = serializeFunc;
+            CreateObjectWithArgs = createObjectWithArgs;
             SetCreateObjectFunc(createObjectFunc);
         }
 
@@ -9,24 +9,25 @@ using System.Threading;
 using System.Threading.Tasks;
 using Xunit;
 
-namespace System.Text.Json.Tests.Serialization
+namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+#if !BUILDING_SOURCE_GENERATOR_TESTS
+    public abstract partial class CollectionTests
     {
         [Theory]
         [MemberData(nameof(GetAsyncEnumerableSources))]
-        public static async Task WriteRootLevelAsyncEnumerable<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
+        public async Task WriteRootLevelAsyncEnumerable<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
         {
             JsonSerializerOptions options = new JsonSerializerOptions
             {
                 DefaultBufferSize = bufferSize
             };
 
-            string expectedJson = JsonSerializer.Serialize(source);
+            string expectedJson = await JsonSerializerWrapperForString.SerializeWrapper(source);
 
             using var stream = new Utf8MemoryStream();
             var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
-            await JsonSerializer.SerializeAsync(stream, asyncEnumerable, options);
+            await JsonSerializerWrapperForStream.SerializeWrapper(stream, asyncEnumerable, options);
 
             JsonTestHelper.AssertJsonEqual(expectedJson, stream.ToString());
             Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators);
@@ -35,18 +36,18 @@ namespace System.Text.Json.Tests.Serialization
 
         [Theory]
         [MemberData(nameof(GetAsyncEnumerableSources))]
-        public static async Task WriteNestedAsyncEnumerable<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
+        public async Task WriteNestedAsyncEnumerable<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
         {
             JsonSerializerOptions options = new JsonSerializerOptions
             {
                 DefaultBufferSize = bufferSize
             };
 
-            string expectedJson = JsonSerializer.Serialize(new { Data = source });
+            string expectedJson = await JsonSerializerWrapperForString.SerializeWrapper(new { Data = source });
 
             using var stream = new Utf8MemoryStream();
             var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
-            await JsonSerializer.SerializeAsync(stream, new { Data = asyncEnumerable }, options);
+            await JsonSerializerWrapperForStream.SerializeWrapper(stream, new { Data = asyncEnumerable }, options);
 
             JsonTestHelper.AssertJsonEqual(expectedJson, stream.ToString());
             Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators);
@@ -55,18 +56,18 @@ namespace System.Text.Json.Tests.Serialization
 
         [Theory]
         [MemberData(nameof(GetAsyncEnumerableSources))]
-        public static async Task WriteNestedAsyncEnumerable_DTO<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
+        public async Task WriteNestedAsyncEnumerable_DTO<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
         {
             JsonSerializerOptions options = new JsonSerializerOptions
             {
                 DefaultBufferSize = bufferSize
             };
 
-            string expectedJson = JsonSerializer.Serialize(new { Data = source });
+            string expectedJson = await JsonSerializerWrapperForString.SerializeWrapper(new { Data = source });
 
             using var stream = new Utf8MemoryStream();
             var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
-            await JsonSerializer.SerializeAsync(stream, new AsyncEnumerableDto<TElement> { Data = asyncEnumerable }, options);
+            await JsonSerializerWrapperForStream.SerializeWrapper(stream, new AsyncEnumerableDto<TElement> { Data = asyncEnumerable }, options);
 
             JsonTestHelper.AssertJsonEqual(expectedJson, stream.ToString());
             Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators);
@@ -74,7 +75,7 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact, OuterLoop]
-        public static async Task WriteAsyncEnumerable_LongRunningEnumeration_Cancellation()
+        public async Task WriteAsyncEnumerable_LongRunningEnumeration_Cancellation()
         {
             var longRunningEnumerable = new MockedAsyncEnumerable<int>(
                 source: Enumerable.Range(1, 100),
@@ -97,18 +98,18 @@ namespace System.Text.Json.Tests.Serialization
 
         [Theory]
         [MemberData(nameof(GetAsyncEnumerableSources))]
-        public static async Task WriteSequentialNestedAsyncEnumerables<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
+        public async Task WriteSequentialNestedAsyncEnumerables<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
         {
             JsonSerializerOptions options = new JsonSerializerOptions
             {
                 DefaultBufferSize = bufferSize
             };
 
-            string expectedJson = JsonSerializer.Serialize(new { Data1 = source, Data2 = source });
+            string expectedJson = await JsonSerializerWrapperForString.SerializeWrapper(new { Data1 = source, Data2 = source });
 
             using var stream = new Utf8MemoryStream();
             var asyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
-            await JsonSerializer.SerializeAsync(stream, new { Data1 = asyncEnumerable, Data2 = asyncEnumerable }, options);
+            await JsonSerializerWrapperForStream.SerializeWrapper(stream, new { Data1 = asyncEnumerable, Data2 = asyncEnumerable }, options);
 
             JsonTestHelper.AssertJsonEqual(expectedJson, stream.ToString());
             Assert.Equal(2, asyncEnumerable.TotalCreatedEnumerators);
@@ -117,7 +118,7 @@ namespace System.Text.Json.Tests.Serialization
 
         [Theory]
         [MemberData(nameof(GetAsyncEnumerableSources))]
-        public static async Task WriteAsyncEnumerableOfAsyncEnumerables<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
+        public async Task WriteAsyncEnumerableOfAsyncEnumerables<TElement>(IEnumerable<TElement> source, int delayInterval, int bufferSize)
         {
             JsonSerializerOptions options = new JsonSerializerOptions
             {
@@ -125,7 +126,7 @@ namespace System.Text.Json.Tests.Serialization
             };
 
             const int OuterEnumerableCount = 5;
-            string expectedJson = JsonSerializer.Serialize(Enumerable.Repeat(source, OuterEnumerableCount));
+            string expectedJson = await JsonSerializerWrapperForString.SerializeWrapper(Enumerable.Repeat(source, OuterEnumerableCount));
 
             var innerAsyncEnumerable = new MockedAsyncEnumerable<TElement>(source, delayInterval);
             var outerAsyncEnumerable =
@@ -133,7 +134,7 @@ namespace System.Text.Json.Tests.Serialization
                     Enumerable.Repeat(innerAsyncEnumerable, OuterEnumerableCount), delayInterval);
 
             using var stream = new Utf8MemoryStream();
-            await JsonSerializer.SerializeAsync(stream, outerAsyncEnumerable, options);
+            await JsonSerializerWrapperForStream.SerializeWrapper(stream, outerAsyncEnumerable, options);
 
             JsonTestHelper.AssertJsonEqual(expectedJson, stream.ToString());
             Assert.Equal(1, outerAsyncEnumerable.TotalCreatedEnumerators);
@@ -143,26 +144,26 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact]
-        public static void WriteRootLevelAsyncEnumerableSync_ThrowsNotSupportedException()
+        public async Task WriteRootLevelAsyncEnumerableSync_ThrowsNotSupportedException()
         {
             IAsyncEnumerable<int> asyncEnumerable = new MockedAsyncEnumerable<int>(Enumerable.Range(1, 10));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(asyncEnumerable));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(asyncEnumerable));
         }
 
         [Fact]
-        public static void WriteNestedAsyncEnumerableSync_ThrowsNotSupportedException()
+        public async Task WriteNestedAsyncEnumerableSync_ThrowsNotSupportedException()
         {
             IAsyncEnumerable<int> asyncEnumerable = new MockedAsyncEnumerable<int>(Enumerable.Range(1, 10));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(new { Data = asyncEnumerable }));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(new { Data = asyncEnumerable }));
         }
 
         [Fact]
-        public static async Task WriteAsyncEnumerable_ElementSerializationThrows_ShouldDisposeEnumerator()
+        public async Task WriteAsyncEnumerable_ElementSerializationThrows_ShouldDisposeEnumerator()
         {
             using var stream = new Utf8MemoryStream();
             var asyncEnumerable = new MockedAsyncEnumerable<IEnumerable<int>>(Enumerable.Repeat(ThrowingEnumerable(), 2));
 
-            await Assert.ThrowsAsync<DivideByZeroException>(() => JsonSerializer.SerializeAsync(stream, new { Data = asyncEnumerable }));
+            await Assert.ThrowsAsync<DivideByZeroException>(async () => await JsonSerializerWrapperForStream.SerializeWrapper(stream, new { Data = asyncEnumerable }));
             Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators);
             Assert.Equal(1, asyncEnumerable.TotalDisposedEnumerators);
 
@@ -174,7 +175,7 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact]
-        public static async Task ReadRootLevelAsyncEnumerable()
+        public async Task ReadRootLevelAsyncEnumerable()
         {
             var utf8Stream = new Utf8MemoryStream("[0,1,2,3,4]");
 
@@ -183,7 +184,7 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact]
-        public static async Task ReadNestedAsyncEnumerable()
+        public async Task ReadNestedAsyncEnumerable()
         {
             var utf8Stream = new Utf8MemoryStream(@"{ ""Data"" : [0,1,2,3,4] }");
 
@@ -192,7 +193,7 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact]
-        public static async Task ReadAsyncEnumerableOfAsyncEnumerables()
+        public async Task ReadAsyncEnumerableOfAsyncEnumerables()
         {
             var utf8Stream = new Utf8MemoryStream("[[0,1,2,3,4], []]");
 
@@ -205,7 +206,7 @@ namespace System.Text.Json.Tests.Serialization
         }
 
         [Fact]
-        public static async Task ReadRootLevelAsyncEnumerableDerivative_ThrowsNotSupportedException()
+        public async Task ReadRootLevelAsyncEnumerableDerivative_ThrowsNotSupportedException()
         {
             var utf8Stream = new Utf8MemoryStream("[0,1,2,3,4]");
             await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializer.DeserializeAsync<MockedAsyncEnumerable<int>>(utf8Stream));
@@ -224,16 +225,6 @@ namespace System.Text.Json.Tests.Serialization
             static object[] WrapArgs<TSource>(IEnumerable<TSource> source, int delayInterval, int bufferSize) => new object[]{ source, delayInterval, bufferSize };
         }
 
-        private static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source)
-        {
-            var list = new List<T>();
-            await foreach (T item in source)
-            {
-                list.Add(item);
-            }
-            return list;
-        }
-
         private class MockedAsyncEnumerable<TElement> : IAsyncEnumerable<TElement>, IEnumerable<TElement>
         {
             private readonly IEnumerable<TElement> _source;
@@ -314,7 +305,8 @@ namespace System.Text.Json.Tests.Serialization
             {
             }
 
-            public override string ToString() => Encoding.UTF8.GetString(ToArray());
+            public override string ToString () => Encoding.UTF8.GetString(ToArray());
         }
     }
+#endif
 }
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Concurrent.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Concurrent.cs
new file mode 100644 (file)
index 0000000..2b4f202
--- /dev/null
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Concurrent;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests
+    {
+        [Fact]
+        public async Task Read_ConcurrentCollection()
+        {
+            ConcurrentDictionary<string, string> cd = await JsonSerializerWrapperForString.DeserializeWrapper<ConcurrentDictionary<string, string>>(@"{""key"":""value""}");
+            Assert.Equal(1, cd.Count);
+            Assert.Equal("value", cd["key"]);
+
+            ConcurrentQueue<string> qc = await JsonSerializerWrapperForString.DeserializeWrapper<ConcurrentQueue<string>>(@"[""1""]");
+            Assert.Equal(1, qc.Count);
+            bool found = qc.TryPeek(out string val);
+            Assert.True(found);
+            Assert.Equal("1", val);
+
+            ConcurrentStack<string> qs = await JsonSerializerWrapperForString.DeserializeWrapper<ConcurrentStack<string>>(@"[""1""]");
+            Assert.Equal(1, qs.Count);
+            found = qs.TryPeek(out val);
+            Assert.True(found);
+            Assert.Equal("1", val);
+        }
+
+        [Theory]
+        [InlineData(typeof(BlockingCollection<string>), @"[""1""]")] // Not supported. Not IList, and we don't detect the add method for this collection.
+        [InlineData(typeof(ConcurrentBag<string>), @"[""1""]")] // Not supported. Not IList, and we don't detect the add method for this collection.
+        public async Task Read_ConcurrentCollection_Throws(Type type, string json)
+        {
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
+            Assert.Contains(type.ToString(), ex.Message);
+        }
+
+        [Theory]
+        [InlineData(typeof(GenericConcurrentQueuePrivateConstructor<string>), @"[""1""]")]
+        [InlineData(typeof(GenericConcurrentQueueInternalConstructor<string>), @"[""1""]")]
+        [InlineData(typeof(GenericConcurrentStackPrivateConstructor<string>), @"[""1""]")]
+        [InlineData(typeof(GenericConcurrentStackInternalConstructor<string>), @"[""1""]")]
+        public async Task Read_ConcurrentCollection_NoPublicConstructor_Throws(Type type, string json)
+        {
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
+            Assert.Contains(type.ToString(), ex.Message);
+        }
+
+        [Fact]
+        public async Task Write_ConcurrentCollection()
+        {
+            Assert.Equal(@"[""1""]", await JsonSerializerWrapperForString.SerializeWrapper(new BlockingCollection<string> { "1" }));
+
+            Assert.Equal(@"[""1""]", await JsonSerializerWrapperForString.SerializeWrapper(new ConcurrentBag<string> { "1" }));
+
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper(new ConcurrentDictionary<string, string> { ["key"] = "value" }));
+
+            ConcurrentQueue<string> qc = new ConcurrentQueue<string>();
+            qc.Enqueue("1");
+            Assert.Equal(@"[""1""]", await JsonSerializerWrapperForString.SerializeWrapper(qc));
+
+            ConcurrentStack<string> qs = new ConcurrentStack<string>();
+            qs.Push("1");
+            Assert.Equal(@"[""1""]", await JsonSerializerWrapperForString.SerializeWrapper(qs));
+        }
+    }
+}
@@ -2,14 +2,15 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static class DictionaryKeyPolicyTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void CamelCaseDeserialize()
+        public async Task CamelCaseDeserialize()
         {
             var options = new JsonSerializerOptions
             {
@@ -19,7 +20,7 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonString = @"[{""Key1"":1,""Key2"":2},{""Key1"":3,""Key2"":4}]";
 
             // Without key policy, deserialize keys as they are.
-            Dictionary<string, int>[] obj = JsonSerializer.Deserialize<Dictionary<string, int>[]>(JsonString);
+            Dictionary<string, int>[] obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>[]>(JsonString);
 
             Assert.Equal(2, obj.Length);
 
@@ -32,7 +33,7 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(4, obj[1]["Key2"]);
 
             // Ensure we ignore key policy and deserialize keys as they are.
-            obj = JsonSerializer.Deserialize<Dictionary<string, int>[]>(JsonString, options);
+            obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>[]>(JsonString, options);
 
             Assert.Equal(2, obj.Length);
 
@@ -46,7 +47,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void IgnoreKeyPolicyForExtensionData()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Need extension data support.")]
+#endif
+        public async Task IgnoreKeyPolicyForExtensionData()
         {
             var options = new JsonSerializerOptions
             {
@@ -54,12 +58,12 @@ namespace System.Text.Json.Serialization.Tests
             };
 
             // Ensure we ignore key policy for extension data and deserialize keys as they are.
-            ClassWithExtensionData myClass = JsonSerializer.Deserialize<ClassWithExtensionData>(@"{""Key1"":1, ""Key2"":2}", options);
+            ClassWithExtensionData myClass = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithExtensionData>(@"{""Key1"":1, ""Key2"":2}", options);
             Assert.Equal(1, (myClass.ExtensionData["Key1"]).GetInt32());
             Assert.Equal(2, (myClass.ExtensionData["Key2"]).GetInt32());
 
             // Ensure we ignore key policy for extension data and serialize keys as they are.
-            Assert.Equal(@"{""Key1"":1,""Key2"":2}", JsonSerializer.Serialize(myClass, options));
+            Assert.Equal(@"{""Key1"":1,""Key2"":2}", await JsonSerializerWrapperForString.SerializeWrapper(myClass, options));
         }
 
         public class ClassWithExtensionData
@@ -69,7 +73,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void CamelCaseSerialize()
+        public async Task CamelCaseSerialize()
         {
             var options = new JsonSerializerOptions()
             {
@@ -86,16 +90,16 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonCamel = @"[{""key1"":1,""key2"":2},{""key1"":3,""key2"":4}]";
 
             // Without key policy option, serialize keys as they are.
-            string json = JsonSerializer.Serialize<object>(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(Json, json);
 
             // With key policy option, serialize keys with camel casing.
-            json = JsonSerializer.Serialize<object>(obj, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj, options);
             Assert.Equal(JsonCamel, json);
         }
 
         [Fact]
-        public static void CamelCaseSerialize_Null_Values()
+        public async Task CamelCaseSerialize_Null_Values()
         {
             var options = new JsonSerializerOptions()
             {
@@ -111,16 +115,16 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonCamel = @"[{""key1"":null,""key2"":null}]";
 
             // Without key policy option, serialize keys as they are.
-            string json = JsonSerializer.Serialize<object>(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(Json, json);
 
             // With key policy option, serialize keys with camel casing.
-            json = JsonSerializer.Serialize<object>(obj, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj, options);
             Assert.Equal(JsonCamel, json);
         }
 
         [Fact]
-        public static void CamelCaseSerialize_Null_Nullable_Values()
+        public async Task CamelCaseSerialize_Null_Nullable_Values()
         {
             var options = new JsonSerializerOptions()
             {
@@ -136,16 +140,16 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonCamel = @"[{""key1"":null,""key2"":null}]";
 
             // Without key policy option, serialize keys as they are.
-            string json = JsonSerializer.Serialize<object>(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(Json, json);
 
             // With key policy option, serialize keys with camel casing.
-            json = JsonSerializer.Serialize<object>(obj, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj, options);
             Assert.Equal(JsonCamel, json);
         }
 
         [Fact]
-        public static void CustomNameDeserialize()
+        public async Task CustomNameDeserialize()
         {
             var options = new JsonSerializerOptions
             {
@@ -154,16 +158,16 @@ namespace System.Text.Json.Serialization.Tests
 
 
             // Without key policy, deserialize keys as they are.
-            Dictionary<string, int> obj = JsonSerializer.Deserialize<Dictionary<string, int>>(@"{""myint"":1}");
+            Dictionary<string, int> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(@"{""myint"":1}");
             Assert.Equal(1, obj["myint"]);
 
             // Ensure we ignore key policy and deserialize keys as they are.
-            obj = JsonSerializer.Deserialize<Dictionary<string, int>>(@"{""myint"":1}", options);
+            obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(@"{""myint"":1}", options);
             Assert.Equal(1, obj["myint"]);
         }
 
         [Fact]
-        public static void CustomNameSerialize()
+        public async Task CustomNameSerialize()
         {
             var options = new JsonSerializerOptions
             {
@@ -176,16 +180,16 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonCustomKey = @"{""MYINT1"":1,""MYINT2"":2}";
 
             // Without key policy option, serialize keys as they are.
-            string json = JsonSerializer.Serialize<object>(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(Json, json);
 
             // With key policy option, serialize keys honoring the custom key policy.
-            json = JsonSerializer.Serialize<object>(obj, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj, options);
             Assert.Equal(JsonCustomKey, json);
         }
 
         [Fact]
-        public static void NullNamePolicy()
+        public async Task NullNamePolicy()
         {
             var options = new JsonSerializerOptions
             {
@@ -193,17 +197,17 @@ namespace System.Text.Json.Serialization.Tests
             };
 
             // A naming policy that returns null is not allowed.
-            Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(new Dictionary<string, int> { { "onlyKey", 1 } }, options));
+            await Assert.ThrowsAsync<InvalidOperationException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(new Dictionary<string, int> { { "onlyKey", 1 } }, options));
 
             // We don't use policy on deserialize, so we populate dictionary.
-            Dictionary<string, int> obj = JsonSerializer.Deserialize<Dictionary<string, int>>(@"{""onlyKey"": 1}", options);
+            Dictionary<string, int> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(@"{""onlyKey"": 1}", options);
 
             Assert.Equal(1, obj.Count);
             Assert.Equal(1, obj["onlyKey"]);
         }
 
         [Fact]
-        public static void CustomNameSerialize_NullableValue()
+        public async Task CustomNameSerialize_NullableValue()
         {
             var options = new JsonSerializerOptions
             {
@@ -216,16 +220,16 @@ namespace System.Text.Json.Serialization.Tests
             const string JsonCustomKey = @"{""MYINT1"":1,""MYINT2"":2}";
 
             // Without key policy option, serialize keys as they are.
-            string json = JsonSerializer.Serialize<object>(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(Json, json);
 
             // With key policy option, serialize keys honoring the custom key policy.
-            json = JsonSerializer.Serialize<object>(obj, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj, options);
             Assert.Equal(JsonCustomKey, json);
         }
 
         [Fact]
-        public static void NullNamePolicy_NullableValue()
+        public async Task NullNamePolicy_NullableValue()
         {
             var options = new JsonSerializerOptions
             {
@@ -233,17 +237,17 @@ namespace System.Text.Json.Serialization.Tests
             };
 
             // A naming policy that returns null is not allowed.
-            Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(new Dictionary<string, int?> { { "onlyKey", 1 } }, options));
+            await Assert.ThrowsAsync<InvalidOperationException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(new Dictionary<string, int?> { { "onlyKey", 1 } }, options));
 
             // We don't use policy on deserialize, so we populate dictionary.
-            Dictionary<string, int?> obj = JsonSerializer.Deserialize<Dictionary<string, int?>>(@"{""onlyKey"": 1}", options);
+            Dictionary<string, int?> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int?>>(@"{""onlyKey"": 1}", options);
 
             Assert.Equal(1, obj.Count);
             Assert.Equal(1, obj["onlyKey"]);
         }
 
         [Fact]
-        public static void KeyConflict_Serialize_WriteAll()
+        public async Task KeyConflict_Serialize_WriteAll()
         {
             var options = new JsonSerializerOptions
             {
@@ -252,14 +256,14 @@ namespace System.Text.Json.Serialization.Tests
 
             // The camel case policy resolves two keys to the same output key.
             Dictionary<string, int> obj = new Dictionary<string, int> { { "myInt", 1 }, { "MyInt", 2 } };
-            string json = JsonSerializer.Serialize(obj, options);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options);
 
             // Check that we write all.
             Assert.Equal(@"{""myInt"":1,""myInt"":2}", json);
         }
         
         [Fact]
-        public static void CamelCaseSerialize_ApplyDictionaryKeyPolicy()
+        public async Task CamelCaseSerialize_ApplyDictionaryKeyPolicy()
         {
             const string JsonCamel = @"{""keyDict"":{""keyString"":""text"",""keyNumber"":1000,""keyBool"":true},""keyList"":[1,2,3]}";
             var options = new JsonSerializerOptions
@@ -276,7 +280,7 @@ namespace System.Text.Json.Serialization.Tests
             };
             obj["KeyList"] = new List<int>() { 1, 2, 3 };
             
-            var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -285,7 +289,10 @@ namespace System.Text.Json.Serialization.Tests
         }
         
         [Fact]
-        public static void SerializationWithJsonExtensionDataAttribute_IgoneDictionaryKeyPolicy()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Need extension data support.")]
+#endif
+        public async Task SerializationWithJsonExtensionDataAttribute_IgoneDictionaryKeyPolicy()
         {
             var expectedJson = @"{""KeyInt"":1000,""KeyString"":""text"",""KeyBool"":true,""KeyObject"":{},""KeyList"":[],""KeyDictionary"":{}}";
             var obj = new ClassWithExtensionDataProperty();
@@ -298,7 +305,7 @@ namespace System.Text.Json.Serialization.Tests
                 { "KeyList", new List<string>() },
                 { "KeyDictionary", new Dictionary<string, string>() }
             };
-            string json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -312,14 +319,14 @@ namespace System.Text.Json.Serialization.Tests
         }
         
         [Fact]
-        public static void CamelCaseSerialize_ForTypedDictionary_ApplyDictionaryKeyPolicy()
+        public async Task CamelCaseSerialize_ForTypedDictionary_ApplyDictionaryKeyPolicy()
         {
             const string JsonCamel = @"{""keyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}";
             var obj = new Dictionary<string, CustomClass>()
             {
                 { "KeyDict", CreateCustomObject() }
             };
-            var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -327,7 +334,7 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(JsonCamel, json);
         }
 
-        private class CustomClass
+        public class CustomClass
         {
             public string Name { get; set; }
             public int Number { get; set; }
@@ -341,7 +348,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void CamelCaseSerialize_ForNestedTypedDictionary_ApplyDictionaryKeyPolicy()
+        public async Task CamelCaseSerialize_ForNestedTypedDictionary_ApplyDictionaryKeyPolicy()
         {
             const string JsonCamel = @"{""keyDict"":{""nestedKeyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}";
             var options = new JsonSerializerOptions
@@ -352,7 +359,7 @@ namespace System.Text.Json.Serialization.Tests
                 { "KeyDict", new  Dictionary<string,CustomClass>()
                 {{ "NestedKeyDict", CreateCustomObject() }}
             }};
-            var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -360,20 +367,20 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(JsonCamel, json);
         }
 
-        private class TestClassWithDictionary
+        public class TestClassWithDictionary
         {
            public Dictionary<string, CustomClass> Data { get; set; }
                }
 
         [Fact]
-        public static void CamelCaseSerialize_ForClassWithDictionaryProperty_ApplyDictionaryKeyPolicy()
+        public async Task CamelCaseSerialize_ForClassWithDictionaryProperty_ApplyDictionaryKeyPolicy()
         {
             const string JsonCamel = @"{""Data"":{""keyObj"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}";
             var obj = new TestClassWithDictionary();
             obj.Data = new Dictionary<string, CustomClass> {
                 {"KeyObj", CreateCustomObject() }
             };
-            var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -381,7 +388,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void CamelCaseSerialize_ForKeyValuePairWithDictionaryValue_ApplyDictionaryKeyPolicy()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Need KVP support.")]
+#endif
+        public async Task CamelCaseSerialize_ForKeyValuePairWithDictionaryValue_ApplyDictionaryKeyPolicy()
         {
             const string JsonCamel = @"{""Key"":""KeyPair"",""Value"":{""keyDict"":{""Name"":""text"",""Number"":1000,""isValid"":true,""Values"":[1,2,3]}}}";
             var options = new JsonSerializerOptions
@@ -392,7 +402,7 @@ namespace System.Text.Json.Serialization.Tests
               ("KeyPair", new Dictionary<string, CustomClass> {
               {"KeyDict", CreateCustomObject() }
             });
-            var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions()
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions()
             {
                 DictionaryKeyPolicy = JsonNamingPolicy.CamelCase
             });
@@ -7,210 +7,211 @@ using System.Collections.Generic;
 using System.Collections.Immutable;
 using System.Collections.Specialized;
 using System.Text.Encodings.Web;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class DictionaryTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void DictionaryOfString()
+        public async Task DictionaryOfString()
         {
             const string JsonString = @"{""Hello"":""World"",""Hello2"":""World2""}";
             const string ReorderedJsonString = @"{""Hello2"":""World2"",""Hello"":""World""}";
 
             {
-                IDictionary obj = JsonSerializer.Deserialize<IDictionary>(JsonString);
+                IDictionary obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                Dictionary<string, string> obj = JsonSerializer.Deserialize<Dictionary<string, string>>(JsonString);
+                Dictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                SortedDictionary<string, string> obj = JsonSerializer.Deserialize<SortedDictionary<string, string>>(JsonString);
+                SortedDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<SortedDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                IDictionary<string, string> obj = JsonSerializer.Deserialize<IDictionary<string, string>>(JsonString);
+                IDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                IReadOnlyDictionary<string, string> obj = JsonSerializer.Deserialize<IReadOnlyDictionary<string, string>>(JsonString);
+                IReadOnlyDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                ImmutableDictionary<string, string> obj = JsonSerializer.Deserialize<ImmutableDictionary<string, string>>(JsonString);
+                ImmutableDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                IImmutableDictionary<string, string> obj = JsonSerializer.Deserialize<IImmutableDictionary<string, string>>(JsonString);
+                IImmutableDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                ImmutableSortedDictionary<string, string> obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, string>>(JsonString);
+                ImmutableSortedDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json);
             }
 
             {
-                Hashtable obj = JsonSerializer.Deserialize<Hashtable>(JsonString);
+                Hashtable obj = await JsonSerializerWrapperForString.DeserializeWrapper<Hashtable>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                SortedList obj = JsonSerializer.Deserialize<SortedList>(JsonString);
+                SortedList obj = await JsonSerializerWrapperForString.DeserializeWrapper<SortedList>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
         }
 
         [Fact]
-        public static void ImplementsDictionary_DictionaryOfString()
+        public async Task ImplementsDictionary_DictionaryOfString()
         {
             const string JsonString = @"{""Hello"":""World"",""Hello2"":""World2""}";
             const string ReorderedJsonString = @"{""Hello2"":""World2"",""Hello"":""World""}";
 
             {
-                WrapperForIDictionary obj = JsonSerializer.Deserialize<WrapperForIDictionary>(JsonString);
+                WrapperForIDictionary obj = await JsonSerializerWrapperForString.DeserializeWrapper<WrapperForIDictionary>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                StringToStringDictionaryWrapper obj = JsonSerializer.Deserialize<StringToStringDictionaryWrapper>(JsonString);
+                StringToStringDictionaryWrapper obj = await JsonSerializerWrapperForString.DeserializeWrapper<StringToStringDictionaryWrapper>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                StringToStringSortedDictionaryWrapper obj = JsonSerializer.Deserialize<StringToStringSortedDictionaryWrapper>(JsonString);
+                StringToStringSortedDictionaryWrapper obj = await JsonSerializerWrapperForString.DeserializeWrapper<StringToStringSortedDictionaryWrapper>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                GenericIDictionaryWrapper<string, string> obj = JsonSerializer.Deserialize<GenericIDictionaryWrapper<string, string>>(JsonString);
+                GenericIDictionaryWrapper<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<GenericIDictionaryWrapper<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIReadOnlyDictionaryWrapper<string, string>>(JsonString));
+                await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIReadOnlyDictionaryWrapper<string, string>>(JsonString));
 
                 GenericIReadOnlyDictionaryWrapper<string, string> obj = new GenericIReadOnlyDictionaryWrapper<string, string>(new Dictionary<string, string>()
                 {
                     { "Hello", "World" },
                     { "Hello2", "World2" },
                 });
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringToStringIImmutableDictionaryWrapper>(JsonString));
+                await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringToStringIImmutableDictionaryWrapper>(JsonString));
 
                 StringToStringIImmutableDictionaryWrapper obj = new StringToStringIImmutableDictionaryWrapper(new Dictionary<string, string>()
                 {
@@ -218,111 +219,111 @@ namespace System.Text.Json.Serialization.Tests
                     { "Hello2", "World2" },
                 });
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                HashtableWrapper obj = JsonSerializer.Deserialize<HashtableWrapper>(JsonString);
+                HashtableWrapper obj = await JsonSerializerWrapperForString.DeserializeWrapper<HashtableWrapper>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                SortedListWrapper obj = JsonSerializer.Deserialize<SortedListWrapper>(JsonString);
+                SortedListWrapper obj = await JsonSerializerWrapperForString.DeserializeWrapper<SortedListWrapper>(JsonString);
                 Assert.Equal("World", ((JsonElement)obj["Hello"]).GetString());
                 Assert.Equal("World2", ((JsonElement)obj["Hello2"]).GetString());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                GenericStructIDictionaryWrapper<string, string> obj = JsonSerializer.Deserialize<GenericStructIDictionaryWrapper<string, string>>(JsonString);
+                GenericStructIDictionaryWrapper<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIDictionaryWrapper<string, string>>(JsonString);
                 Assert.Equal("World", obj["Hello"]);
                 Assert.Equal("World2", obj["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                GenericStructIDictionaryWrapper<string, string>? obj = JsonSerializer.Deserialize<GenericStructIDictionaryWrapper<string, string>?>(JsonString);
+                GenericStructIDictionaryWrapper<string, string>? obj = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIDictionaryWrapper<string, string>?>(JsonString);
                 Assert.True(obj.HasValue);
                 Assert.Equal("World", obj.Value["Hello"]);
                 Assert.Equal("World2", obj.Value["Hello2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                GenericStructIDictionaryWrapper<string, string>? obj = JsonSerializer.Deserialize<GenericStructIDictionaryWrapper<string, string>?>("null");
+                GenericStructIDictionaryWrapper<string, string>? obj = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIDictionaryWrapper<string, string>?>("null");
                 Assert.False(obj.HasValue);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal("null", json);
             }
 
             {
                 GenericStructIDictionaryWrapper<string, string> obj = default;
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal("{}", json);
             }
 
             {
                 StructWrapperForIDictionary obj = default;
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal("{}", json);
             }
         }
 
         [Fact]
-        public static void DictionaryOfObject()
+        public async Task DictionaryOfObject()
         {
             {
-                Dictionary<string, object> obj = JsonSerializer.Deserialize<Dictionary<string, object>>(@"{""Key1"":1}");
+                Dictionary<string, object> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, object>>(@"{""Key1"":1}");
                 Assert.Equal(1, obj.Count);
                 JsonElement element = (JsonElement)obj["Key1"];
                 Assert.Equal(JsonValueKind.Number, element.ValueKind);
                 Assert.Equal(1, element.GetInt32());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(@"{""Key1"":1}", json);
             }
 
             {
-                IDictionary<string, object> obj = JsonSerializer.Deserialize<IDictionary<string, object>>(@"{""Key1"":1}");
+                IDictionary<string, object> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, object>>(@"{""Key1"":1}");
                 Assert.Equal(1, obj.Count);
                 JsonElement element = (JsonElement)obj["Key1"];
                 Assert.Equal(JsonValueKind.Number, element.ValueKind);
                 Assert.Equal(1, element.GetInt32());
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(@"{""Key1"":1}", json);
             }
         }
 
         [Fact]
-        public static void ImplementsIDictionaryOfObject()
+        public async Task ImplementsIDictionaryOfObject()
         {
             var input = new GenericIDictionaryWrapper<string, object>(new Dictionary<string, object>
             {
@@ -330,17 +331,17 @@ namespace System.Text.Json.Serialization.Tests
                 { "Age", 32 }
             });
 
-            string json = JsonSerializer.Serialize(input, typeof(IDictionary<string, object>));
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input, typeof(IDictionary<string, object>));
             Assert.Equal(@"{""Name"":""David"",""Age"":32}", json);
 
-            IDictionary<string, object> obj = JsonSerializer.Deserialize<IDictionary<string, object>>(json);
+            IDictionary<string, object> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, object>>(json);
             Assert.Equal(2, obj.Count);
             Assert.Equal("David", ((JsonElement)obj["Name"]).GetString());
             Assert.Equal(32, ((JsonElement)obj["Age"]).GetInt32());
         }
 
         [Fact]
-        public static void ImplementsIDictionaryOfString()
+        public async Task ImplementsIDictionaryOfString()
         {
             var input = new GenericIDictionaryWrapper<string, string>(new Dictionary<string, string>
             {
@@ -348,25 +349,25 @@ namespace System.Text.Json.Serialization.Tests
                 { "Job", "Software Architect" }
             });
 
-            string json = JsonSerializer.Serialize(input, typeof(IDictionary<string, string>));
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input, typeof(IDictionary<string, string>));
             Assert.Equal(@"{""Name"":""David"",""Job"":""Software Architect""}", json);
 
-            IDictionary<string, string> obj = JsonSerializer.Deserialize<IDictionary<string, string>>(json);
+            IDictionary<string, string> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, string>>(json);
             Assert.Equal(2, obj.Count);
             Assert.Equal("David", obj["Name"]);
             Assert.Equal("Software Architect", obj["Job"]);
         }
 
         [Fact]
-        public static void PocoWithDictionaryObject()
+        public async Task PocoWithDictionaryObject()
         {
-            PocoDictionary dict = JsonSerializer.Deserialize<PocoDictionary>("{\n\t\"key\" : {\"a\" : \"b\", \"c\" : \"d\"}}");
+            PocoDictionary dict = await JsonSerializerWrapperForString.DeserializeWrapper<PocoDictionary>("{\n\t\"key\" : {\"a\" : \"b\", \"c\" : \"d\"}}");
             Assert.Equal("b", dict.key["a"]);
             Assert.Equal("d", dict.key["c"]);
         }
 
         [Fact]
-        public static void DictionaryOfObject_NonPrimitiveTypes()
+        public async Task DictionaryOfObject_NonPrimitiveTypes()
         {
             // https://github.com/dotnet/runtime/issues/29504
             Dictionary<string, object> dictionary = new Dictionary<string, object>
@@ -374,22 +375,22 @@ namespace System.Text.Json.Serialization.Tests
                 ["key"] = new Poco { Id = 10 },
             };
 
-            string json = JsonSerializer.Serialize(dictionary);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(dictionary);
             Assert.Equal(@"{""key"":{""Id"":10}}", json);
 
-            dictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, object>>(json);
             Assert.Equal(1, dictionary.Count);
             JsonElement element = (JsonElement)dictionary["key"];
             Assert.Equal(@"{""Id"":10}", element.ToString());
         }
 
         [Fact]
-        public static void DictionaryOfList()
+        public async Task DictionaryOfList()
         {
             const string JsonString = @"{""Key1"":[1,2],""Key2"":[3,4]}";
 
             {
-                IDictionary obj = JsonSerializer.Deserialize<IDictionary>(JsonString);
+                IDictionary obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(JsonString);
 
                 Assert.Equal(2, obj.Count);
 
@@ -407,12 +408,12 @@ namespace System.Text.Json.Serialization.Tests
                     Assert.Equal(expectedNumber++, value.GetInt32());
                 }
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                IDictionary<string, List<int>> obj = JsonSerializer.Deserialize<IDictionary<string, List<int>>>(JsonString);
+                IDictionary<string, List<int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, List<int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj["Key1"].Count);
@@ -422,12 +423,12 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj["Key2"][0]);
                 Assert.Equal(4, obj["Key2"][1]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                ImmutableDictionary<string, List<int>> obj = JsonSerializer.Deserialize<ImmutableDictionary<string, List<int>>>(JsonString);
+                ImmutableDictionary<string, List<int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableDictionary<string, List<int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj["Key1"].Count);
@@ -437,13 +438,13 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj["Key2"][0]);
                 Assert.Equal(4, obj["Key2"][1]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 const string ReorderedJsonString = @"{""Key2"":[3,4],""Key1"":[1,2]}";
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
 
             {
-                IImmutableDictionary<string, List<int>> obj = JsonSerializer.Deserialize<IImmutableDictionary<string, List<int>>>(JsonString);
+                IImmutableDictionary<string, List<int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableDictionary<string, List<int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj["Key1"].Count);
@@ -454,17 +455,17 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(4, obj["Key2"][1]);
 
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 const string ReorderedJsonString = @"{""Key2"":[3,4],""Key1"":[1,2]}";
                 Assert.True(JsonString == json || ReorderedJsonString == json);
             }
         }
 
         [Fact]
-        public static void DictionaryOfArray()
+        public async Task DictionaryOfArray()
         {
             const string JsonString = @"{""Key1"":[1,2],""Key2"":[3,4]}";
-            Dictionary<string, int[]> obj = JsonSerializer.Deserialize<Dictionary<string, int[]>>(JsonString);
+            Dictionary<string, int[]> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int[]>>(JsonString);
 
             Assert.Equal(2, obj.Count);
             Assert.Equal(2, obj["Key1"].Length);
@@ -474,17 +475,17 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(3, obj["Key2"][0]);
             Assert.Equal(4, obj["Key2"][1]);
 
-            string json = JsonSerializer.Serialize(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
             Assert.Equal(JsonString, json);
         }
 
         [Fact]
-        public static void ListOfDictionary()
+        public async Task ListOfDictionary()
         {
             const string JsonString = @"[{""Key1"":1,""Key2"":2},{""Key1"":3,""Key2"":4}]";
 
             {
-                List<Dictionary<string, int>> obj = JsonSerializer.Deserialize<List<Dictionary<string, int>>>(JsonString);
+                List<Dictionary<string, int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<List<Dictionary<string, int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj[0].Count);
@@ -494,14 +495,14 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj[1]["Key1"]);
                 Assert.Equal(4, obj[1]["Key2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
             {
-                List<ImmutableSortedDictionary<string, int>> obj = JsonSerializer.Deserialize<List<ImmutableSortedDictionary<string, int>>>(JsonString);
+                List<ImmutableSortedDictionary<string, int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<List<ImmutableSortedDictionary<string, int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj[0].Count);
@@ -511,21 +512,21 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj[1]["Key1"]);
                 Assert.Equal(4, obj[1]["Key2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
         }
 
         [Fact]
-        public static void ArrayOfDictionary()
+        public async Task ArrayOfDictionary()
         {
             const string JsonString = @"[{""Key1"":1,""Key2"":2},{""Key1"":3,""Key2"":4}]";
 
             {
-                Dictionary<string, int>[] obj = JsonSerializer.Deserialize<Dictionary<string, int>[]>(JsonString);
+                Dictionary<string, int>[] obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>[]>(JsonString);
 
                 Assert.Equal(2, obj.Length);
                 Assert.Equal(2, obj[0].Count);
@@ -535,15 +536,15 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj[1]["Key1"]);
                 Assert.Equal(4, obj[1]["Key2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                ImmutableSortedDictionary<string, int>[] obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, int>[]>(JsonString);
+                ImmutableSortedDictionary<string, int>[] obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, int>[]>(JsonString);
 
                 Assert.Equal(2, obj.Length);
                 Assert.Equal(2, obj[0].Count);
@@ -553,21 +554,21 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj[1]["Key1"]);
                 Assert.Equal(4, obj[1]["Key2"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
         }
 
         [Fact]
-        public static void DictionaryOfDictionary()
+        public async Task DictionaryOfDictionary()
         {
             const string JsonString = @"{""Key1"":{""Key1a"":1,""Key1b"":2},""Key2"":{""Key2a"":3,""Key2b"":4}}";
 
             {
-                Dictionary<string, Dictionary<string, int>> obj = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(JsonString);
+                Dictionary<string, Dictionary<string, int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, Dictionary<string, int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj["Key1"].Count);
@@ -577,15 +578,15 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj["Key2"]["Key2a"]);
                 Assert.Equal(4, obj["Key2"]["Key2b"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
 
             {
-                ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>> obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>>>(JsonString);
+                ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>>>(JsonString);
 
                 Assert.Equal(2, obj.Count);
                 Assert.Equal(2, obj["Key1"].Count);
@@ -595,19 +596,19 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(3, obj["Key2"]["Key2a"]);
                 Assert.Equal(4, obj["Key2"]["Key2b"]);
 
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(JsonString, json);
 
-                json = JsonSerializer.Serialize<object>(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
                 Assert.Equal(JsonString, json);
             }
         }
 
         [Fact]
-        public static void DictionaryOfDictionaryOfDictionary()
+        public async Task DictionaryOfDictionaryOfDictionary()
         {
             const string JsonString = @"{""Key1"":{""Key1"":{""Key1"":1,""Key2"":2},""Key2"":{""Key1"":3,""Key2"":4}},""Key2"":{""Key1"":{""Key1"":5,""Key2"":6},""Key2"":{""Key1"":7,""Key2"":8}}}";
-            Dictionary<string, Dictionary<string, Dictionary<string, int>>> obj = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, int>>>>(JsonString);
+            Dictionary<string, Dictionary<string, Dictionary<string, int>>> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, Dictionary<string, Dictionary<string, int>>>>(JsonString);
 
             Assert.Equal(2, obj.Count);
             Assert.Equal(2, obj["Key1"].Count);
@@ -628,19 +629,19 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(7, obj["Key2"]["Key2"]["Key1"]);
             Assert.Equal(8, obj["Key2"]["Key2"]["Key2"]);
 
-            string json = JsonSerializer.Serialize(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
             Assert.Equal(JsonString, json);
 
             // Verify that typeof(object) doesn't interfere.
-            json = JsonSerializer.Serialize<object>(obj);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(JsonString, json);
         }
 
         [Fact]
-        public static void DictionaryOfArrayOfDictionary()
+        public async Task DictionaryOfArrayOfDictionary()
         {
             const string JsonString = @"{""Key1"":[{""Key1"":1,""Key2"":2},{""Key1"":3,""Key2"":4}],""Key2"":[{""Key1"":5,""Key2"":6},{""Key1"":7,""Key2"":8}]}";
-            Dictionary<string, Dictionary<string, int>[]> obj = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>[]>>(JsonString);
+            Dictionary<string, Dictionary<string, int>[]> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, Dictionary<string, int>[]>>(JsonString);
 
             Assert.Equal(2, obj.Count);
             Assert.Equal(2, obj["Key1"].Length);
@@ -661,11 +662,11 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(7, obj["Key2"][1]["Key1"]);
             Assert.Equal(8, obj["Key2"][1]["Key2"]);
 
-            string json = JsonSerializer.Serialize(obj);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
             Assert.Equal(JsonString, json);
 
             // Verify that typeof(object) doesn't interfere.
-            json = JsonSerializer.Serialize<object>(obj);
+            json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
             Assert.Equal(JsonString, json);
         }
 
@@ -786,33 +787,39 @@ namespace System.Text.Json.Serialization.Tests
             return tests;
         }
 
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Too many dynamically generated serializable types to manually add to a serialization context.")]
+#endif
         [Fact]
-        public static void NestedDictionariesRoundtrip()
+        public async Task NestedDictionariesRoundtrip()
         {
             JsonSerializerOptions options = new JsonSerializerOptions();
             options.Converters.Add(new MyFactory());
 
             foreach ((Type dictionaryType, string testJson) in NestedDictionaryTypeData())
             {
-                object dict = JsonSerializer.Deserialize(testJson, dictionaryType, options);
-                Assert.Equal(testJson, JsonSerializer.Serialize(dict, options));
+                object dict = await JsonSerializerWrapperForString.DeserializeWrapper(testJson, dictionaryType, options);
+                Assert.Equal(testJson, await JsonSerializerWrapperForString.SerializeWrapper(dict, options));
             }
         }
 
         [Fact]
-        public static void DictionaryOfClasses()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Needs full SimpleTestClass support.")]
+#endif
+        public async Task DictionaryOfClasses()
         {
             {
                 IDictionary obj;
 
                 {
                     string json = @"{""Key1"":" + SimpleTestClass.s_json + @",""Key2"":" + SimpleTestClass.s_json + "}";
-                    obj = JsonSerializer.Deserialize<IDictionary>(json);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(json);
                     Assert.Equal(2, obj.Count);
 
                     if (obj["Key1"] is JsonElement element)
                     {
-                        SimpleTestClass result = JsonSerializer.Deserialize<SimpleTestClass>(element.GetRawText());
+                        SimpleTestClass result = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClass>(element.GetRawText());
                         result.Verify();
                     }
                     else
@@ -825,13 +832,13 @@ namespace System.Text.Json.Serialization.Tests
                 {
                     // We can't compare against the json string above because property ordering is not deterministic (based on reflection order)
                     // so just round-trip the json and compare.
-                    string json = JsonSerializer.Serialize(obj);
-                    obj = JsonSerializer.Deserialize<IDictionary>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(json);
                     Assert.Equal(2, obj.Count);
 
                     if (obj["Key1"] is JsonElement element)
                     {
-                        SimpleTestClass result = JsonSerializer.Deserialize<SimpleTestClass>(element.GetRawText());
+                        SimpleTestClass result = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClass>(element.GetRawText());
                         result.Verify();
                     }
                     else
@@ -842,13 +849,13 @@ namespace System.Text.Json.Serialization.Tests
                 }
 
                 {
-                    string json = JsonSerializer.Serialize<object>(obj);
-                    obj = JsonSerializer.Deserialize<IDictionary>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(json);
                     Assert.Equal(2, obj.Count);
 
                     if (obj["Key1"] is JsonElement element)
                     {
-                        SimpleTestClass result = JsonSerializer.Deserialize<SimpleTestClass>(element.GetRawText());
+                        SimpleTestClass result = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClass>(element.GetRawText());
                         result.Verify();
                     }
                     else
@@ -864,7 +871,7 @@ namespace System.Text.Json.Serialization.Tests
 
                 {
                     string json = @"{""Key1"":" + SimpleTestClass.s_json + @",""Key2"":" + SimpleTestClass.s_json + "}";
-                    obj = JsonSerializer.Deserialize<Dictionary<string, SimpleTestClass>>(json);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
@@ -873,16 +880,16 @@ namespace System.Text.Json.Serialization.Tests
                 {
                     // We can't compare against the json string above because property ordering is not deterministic (based on reflection order)
                     // so just round-trip the json and compare.
-                    string json = JsonSerializer.Serialize(obj);
-                    obj = JsonSerializer.Deserialize<Dictionary<string, SimpleTestClass>>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
                 }
 
                 {
-                    string json = JsonSerializer.Serialize<object>(obj);
-                    obj = JsonSerializer.Deserialize<Dictionary<string, SimpleTestClass>>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
@@ -894,7 +901,7 @@ namespace System.Text.Json.Serialization.Tests
 
                 {
                     string json = @"{""Key1"":" + SimpleTestClass.s_json + @",""Key2"":" + SimpleTestClass.s_json + "}";
-                    obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
@@ -903,16 +910,16 @@ namespace System.Text.Json.Serialization.Tests
                 {
                     // We can't compare against the json string above because property ordering is not deterministic (based on reflection order)
                     // so just round-trip the json and compare.
-                    string json = JsonSerializer.Serialize(obj);
-                    obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
                 }
 
                 {
-                    string json = JsonSerializer.Serialize<object>(obj);
-                    obj = JsonSerializer.Deserialize<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
+                    string json = await JsonSerializerWrapperForString.SerializeWrapper<object>(obj);
+                    obj = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedDictionary<string, SimpleTestClass>>(json);
                     Assert.Equal(2, obj.Count);
                     obj["Key1"].Verify();
                     obj["Key2"].Verify();
@@ -921,7 +928,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void UnicodePropertyNames()
+        public async Task UnicodePropertyNames()
         {
             var options = new JsonSerializerOptions();
             options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
@@ -929,20 +936,20 @@ namespace System.Text.Json.Serialization.Tests
             {
                 Dictionary<string, int> obj;
 
-                obj = JsonSerializer.Deserialize<Dictionary<string, int>>(@"{""A\u0467"":1}");
+                obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(@"{""A\u0467"":1}");
                 Assert.Equal(1, obj["A\u0467"]);
 
                 // Specifying encoder on options does not impact deserialize.
-                obj = JsonSerializer.Deserialize<Dictionary<string, int>>(@"{""A\u0467"":1}", options);
+                obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(@"{""A\u0467"":1}", options);
                 Assert.Equal(1, obj["A\u0467"]);
 
                 string json;
                 // Verify the name is escaped after serialize.
-                json = JsonSerializer.Serialize(obj);
+                json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
                 Assert.Equal(@"{""A\u0467"":1}", json);
 
                 // Verify with encoder.
-                json = JsonSerializer.Serialize(obj, options);
+                json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options);
                 Assert.Equal("{\"A\u0467\":1}", json);
             }
 
@@ -952,11 +959,11 @@ namespace System.Text.Json.Serialization.Tests
 
                 string longPropertyName = new string('\u0467', charsInProperty);
 
-                Dictionary<string, int> obj = JsonSerializer.Deserialize<Dictionary<string, int>>($"{{\"{longPropertyName}\":1}}");
+                Dictionary<string, int> obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>($"{{\"{longPropertyName}\":1}}");
                 Assert.Equal(1, obj[longPropertyName]);
 
                 // Verify the name is escaped after serialize.
-                string json = JsonSerializer.Serialize(obj);
+                string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
 
                 // Duplicate the unicode character 'charsInProperty' times.
                 string longPropertyNameEscaped = new StringBuilder().Insert(0, @"\u0467", charsInProperty).ToString();
@@ -965,106 +972,106 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expectedJson, json);
 
                 // Verify the name is unescaped after deserialize.
-                obj = JsonSerializer.Deserialize<Dictionary<string, int>>(json);
+                obj = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, int>>(json);
                 Assert.Equal(1, obj[longPropertyName]);
             }
         }
 
         [Fact]
-        public static void CustomEscapingOnPropertyNameAndValue()
+        public async Task CustomEscapingOnPropertyNameAndValue()
         {
             var dict = new Dictionary<string, string>();
             dict.Add("A\u046701", "Value\u0467");
 
             // Baseline with no escaping.
-            var json = JsonSerializer.Serialize(dict);
+            var json = await JsonSerializerWrapperForString.SerializeWrapper(dict);
             Assert.Equal("{\"A\\u046701\":\"Value\\u0467\"}", json);
 
             // Enable escaping.
             var options = new JsonSerializerOptions();
             options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
 
-            json = JsonSerializer.Serialize(dict, options);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(dict, options);
             Assert.Equal("{\"A\u046701\":\"Value\u0467\"}", json);
         }
 
         [Fact]
-        public static void ObjectToStringFail()
+        public async Task ObjectToStringFail()
         {
             // Baseline
             string json = @"{""MyDictionary"":{""Key"":""Value""}}";
             JsonSerializer.Deserialize<Dictionary<string, object>>(json);
 
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<Dictionary<string, string>>(json));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, string>>(json));
         }
 
         [Fact]
-        public static void ObjectToJsonElement()
+        public async Task ObjectToJsonElement()
         {
             string json = @"{""MyDictionary"":{""Key"":""Value""}}";
-            Dictionary<string, JsonElement> result = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
+            Dictionary<string, JsonElement> result = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, JsonElement>>(json);
             JsonElement element = result["MyDictionary"];
             Assert.Equal(JsonValueKind.Object, element.ValueKind);
             Assert.Equal("Value", element.GetProperty("Key").GetString());
         }
 
         [Fact]
-        public static void Hashtable()
+        public async Task Hashtable()
         {
             const string Json = @"{""Key"":""Value""}";
 
             IDictionary ht = new Hashtable();
             ht.Add("Key", "Value");
-            string json = JsonSerializer.Serialize(ht);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(ht);
 
             Assert.Equal(Json, json);
 
-            ht = JsonSerializer.Deserialize<IDictionary>(json);
+            ht = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(json);
             Assert.IsType<JsonElement>(ht["Key"]);
             Assert.Equal("Value", ((JsonElement)ht["Key"]).GetString());
 
             // Verify round-tripped JSON.
-            json = JsonSerializer.Serialize(ht);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(ht);
             Assert.Equal(Json, json);
         }
 
         [Fact]
-        public static void DeserializeDictionaryWithDuplicateKeys()
+        public async Task DeserializeDictionaryWithDuplicateKeys()
         {
             // Non-generic IDictionary case.
-            IDictionary iDictionary = JsonSerializer.Deserialize<IDictionary>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
+            IDictionary iDictionary = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
             Assert.Equal("NewValue", iDictionary["Hello"].ToString());
 
             // Generic IDictionary case.
-            IDictionary<string, string> iNonGenericDictionary = JsonSerializer.Deserialize<IDictionary<string, string>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
+            IDictionary<string, string> iNonGenericDictionary = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, string>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
             Assert.Equal("NewValue", iNonGenericDictionary["Hello"]);
 
-            IDictionary<string, object> iNonGenericObjectDictionary = JsonSerializer.Deserialize<IDictionary<string, object>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
+            IDictionary<string, object> iNonGenericObjectDictionary = await JsonSerializerWrapperForString.DeserializeWrapper<IDictionary<string, object>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
             Assert.Equal("NewValue", iNonGenericObjectDictionary["Hello"].ToString());
 
             // Strongly-typed IDictionary<,> case.
-            Dictionary<string, string> dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
+            Dictionary<string, string> dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, string>>(@"{""Hello"":""World"", ""Hello"":""NewValue""}");
             Assert.Equal("NewValue", dictionary["Hello"]);
 
-            dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(@"{""Hello"":""World"", ""myKey"" : ""myValue"", ""Hello"":""NewValue""}");
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, string>>(@"{""Hello"":""World"", ""myKey"" : ""myValue"", ""Hello"":""NewValue""}");
             Assert.Equal("NewValue", dictionary["Hello"]);
 
             // Weakly-typed IDictionary case.
-            Dictionary<string, object> dictionaryObject = JsonSerializer.Deserialize<Dictionary<string, object>>(@"{""Hello"":""World"", ""Hello"": null}");
+            Dictionary<string, object> dictionaryObject = await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, object>>(@"{""Hello"":""World"", ""Hello"": null}");
             Assert.Null(dictionaryObject["Hello"]);
         }
 
         [Fact]
-        public static void DeserializeDictionaryWithDuplicateProperties()
+        public async Task DeserializeDictionaryWithDuplicateProperties()
         {
-            PocoDuplicate foo = JsonSerializer.Deserialize<PocoDuplicate>(@"{""BoolProperty"": false, ""BoolProperty"": true}");
+            PocoDuplicate foo = await JsonSerializerWrapperForString.DeserializeWrapper<PocoDuplicate>(@"{""BoolProperty"": false, ""BoolProperty"": true}");
             Assert.True(foo.BoolProperty);
 
-            foo = JsonSerializer.Deserialize<PocoDuplicate>(@"{""BoolProperty"": false, ""IntProperty"" : 1, ""BoolProperty"": true , ""IntProperty"" : 2}");
+            foo = await JsonSerializerWrapperForString.DeserializeWrapper<PocoDuplicate>(@"{""BoolProperty"": false, ""IntProperty"" : 1, ""BoolProperty"": true , ""IntProperty"" : 2}");
             Assert.True(foo.BoolProperty);
             Assert.Equal(2, foo.IntProperty);
 
-            foo = JsonSerializer.Deserialize<PocoDuplicate>(@"{""DictProperty"" : {""a"" : ""b"", ""c"" : ""d""},""DictProperty"" : {""b"" : ""b"", ""c"" : ""e""}}");
+            foo = await JsonSerializerWrapperForString.DeserializeWrapper<PocoDuplicate>(@"{""DictProperty"" : {""a"" : ""b"", ""c"" : ""d""},""DictProperty"" : {""b"" : ""b"", ""c"" : ""e""}}");
             Assert.Equal(2, foo.DictProperty.Count); // We don't concat.
             Assert.Equal("e", foo.DictProperty["c"]);
         }
@@ -1088,20 +1095,20 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ClassWithNoSetterAndDictionary()
+        public async Task ClassWithNoSetterAndDictionary()
         {
             // We don't attempt to deserialize into dictionaries without a setter.
             string json = @"{""MyDictionary"":{""Key1"":""Value1"", ""Key2"":""Value2""}}";
-            ClassWithPopulatedDictionaryAndNoSetter obj = JsonSerializer.Deserialize<ClassWithPopulatedDictionaryAndNoSetter>(json);
+            ClassWithPopulatedDictionaryAndNoSetter obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithPopulatedDictionaryAndNoSetter>(json);
             Assert.Equal(1, obj.MyDictionary.Count);
         }
 
         [Fact]
-        public static void ClassWithNoSetterAndImmutableDictionary()
+        public async Task ClassWithNoSetterAndImmutableDictionary()
         {
             // We don't attempt to deserialize into dictionaries without a setter.
             string json = @"{""MyImmutableDictionary"":{""Key1"":""Value1"", ""Key2"":""Value2""}}";
-            ClassWithPopulatedDictionaryAndNoSetter obj = JsonSerializer.Deserialize<ClassWithPopulatedDictionaryAndNoSetter>(json);
+            ClassWithPopulatedDictionaryAndNoSetter obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithPopulatedDictionaryAndNoSetter>(json);
             Assert.Equal(1, obj.MyImmutableDictionary.Count);
         }
 
@@ -1184,10 +1191,10 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(@"{""Parsed1"":{""Key"":1},""Skipped2"":{""Key"":[1,2,3]}, ""Parsed3"":{""Key"":2}}")]
         [InlineData(@"{""Parsed1"":{""Key"":1},""Skipped2"":{""Key"":{}}, ""Parsed3"":{""Key"":2}}")]
         [InlineData(@"{""Parsed1"":{""Key"":1},""Skipped2"":{""Key"":null}, ""Parsed3"":{""Key"":2}}")]
-        public static void IgnoreDictionaryProperty(string json)
+        public async Task IgnoreDictionaryProperty(string json)
         {
             // Verify deserialization
-            ClassWithIgnoredDictionary2 obj = JsonSerializer.Deserialize<ClassWithIgnoredDictionary2>(json);
+            ClassWithIgnoredDictionary2 obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithIgnoredDictionary2>(json);
             Assert.Equal(1, obj.Parsed1.Count);
             Assert.Equal(1, obj.Parsed1["Key"]);
             Assert.Null(obj.Skipped2);
@@ -1195,8 +1202,8 @@ namespace System.Text.Json.Serialization.Tests
             Assert.Equal(2, obj.Parsed3["Key"]);
 
             // Round-trip and verify.
-            string jsonRoundTripped = JsonSerializer.Serialize(obj);
-            ClassWithIgnoredDictionary2 objRoundTripped = JsonSerializer.Deserialize<ClassWithIgnoredDictionary2>(jsonRoundTripped);
+            string jsonRoundTripped = await JsonSerializerWrapperForString.SerializeWrapper(obj);
+            ClassWithIgnoredDictionary2 objRoundTripped = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithIgnoredDictionary2>(jsonRoundTripped);
             Assert.Equal(1, objRoundTripped.Parsed1.Count);
             Assert.Equal(1, objRoundTripped.Parsed1["Key"]);
             Assert.Null(objRoundTripped.Skipped2);
@@ -1205,25 +1212,25 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void IgnoreDictionaryPropertyWithDifferentOrdering()
+        public async Task IgnoreDictionaryPropertyWithDifferentOrdering()
         {
             // Verify all combinations of 3 properties with at least one ignore.
-            VerifyIgnore<ClassWithIgnoredDictionary1>(false, false, true);
-            VerifyIgnore<ClassWithIgnoredDictionary2>(false, true, false);
-            VerifyIgnore<ClassWithIgnoredDictionary3>(false, true, true);
-            VerifyIgnore<ClassWithIgnoredDictionary4>(true, false, false);
-            VerifyIgnore<ClassWithIgnoredDictionary5>(true, false, true);
-            VerifyIgnore<ClassWithIgnoredDictionary6>(true, true, false);
-            VerifyIgnore<ClassWithIgnoredDictionary7>(true, true, true);
+            await VerifyIgnore<ClassWithIgnoredDictionary1>(false, false, true);
+            await VerifyIgnore<ClassWithIgnoredDictionary2>(false, true, false);
+            await VerifyIgnore<ClassWithIgnoredDictionary3>(false, true, true);
+            await VerifyIgnore<ClassWithIgnoredDictionary4>(true, false, false);
+            await VerifyIgnore<ClassWithIgnoredDictionary5>(true, false, true);
+            await VerifyIgnore<ClassWithIgnoredDictionary6>(true, true, false);
+            await VerifyIgnore<ClassWithIgnoredDictionary7>(true, true, true);
 
             // Verify single case for IDictionary, [Ignore] and ImmutableDictionary.
             // Also specify addMissing to add additional skipped JSON that does not have a corresponding property.
-            VerifyIgnore<ClassWithIgnoredIDictionary>(false, true, false, addMissing: true);
-            VerifyIgnore<ClassWithIgnoreAttributeDictionary>(false, true, false, addMissing: true);
-            VerifyIgnore<ClassWithIgnoredImmutableDictionary>(false, true, false, addMissing: true);
+            await VerifyIgnore<ClassWithIgnoredIDictionary>(false, true, false, addMissing: true);
+            await VerifyIgnore<ClassWithIgnoreAttributeDictionary>(false, true, false, addMissing: true);
+            await VerifyIgnore<ClassWithIgnoredImmutableDictionary>(false, true, false, addMissing: true);
         }
 
-        private static void VerifyIgnore<T>(bool skip1, bool skip2, bool skip3, bool addMissing = false)
+        private async Task VerifyIgnore<T>(bool skip1, bool skip2, bool skip3, bool addMissing = false)
         {
             static IDictionary<string, int> GetProperty(T objectToVerify, string propertyName)
             {
@@ -1307,13 +1314,13 @@ namespace System.Text.Json.Serialization.Tests
 
             // Deserialize and verify.
             string jsonString = json.ToString();
-            T obj = JsonSerializer.Deserialize<T>(jsonString);
+            T obj = await JsonSerializerWrapperForString.DeserializeWrapper<T>(jsonString);
             Verify(obj);
 
             // Round-trip and verify.
             // Any skipped properties due to lack of a setter will now be "null" when serialized instead of "{}".
-            string jsonStringRoundTripped = JsonSerializer.Serialize(obj);
-            T objRoundTripped = JsonSerializer.Deserialize<T>(jsonStringRoundTripped);
+            string jsonStringRoundTripped = await JsonSerializerWrapperForString.SerializeWrapper(obj);
+            T objRoundTripped = await JsonSerializerWrapperForString.DeserializeWrapper<T>(jsonStringRoundTripped);
             Verify(objRoundTripped);
         }
 
@@ -1329,45 +1336,51 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ClassWithPopulatedDictionary()
+        public async Task ClassWithPopulatedDictionary()
         {
             // We replace the contents.
             string json = @"{""MyDictionary"":{""Key1"":""Value1"", ""Key2"":""Value2""}}";
-            ClassWithPopulatedDictionaryAndSetter obj = JsonSerializer.Deserialize<ClassWithPopulatedDictionaryAndSetter>(json);
+            ClassWithPopulatedDictionaryAndSetter obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithPopulatedDictionaryAndSetter>(json);
             Assert.Equal(2, obj.MyDictionary.Count);
         }
 
         [Fact]
-        public static void ClassWithPopulatedImmutableDictionary()
+        public async Task ClassWithPopulatedImmutableDictionary()
         {
             // We replace the contents.
             string json = @"{""MyImmutableDictionary"":{""Key1"":""Value1"", ""Key2"":""Value2""}}";
-            ClassWithPopulatedDictionaryAndSetter obj = JsonSerializer.Deserialize<ClassWithPopulatedDictionaryAndSetter>(json);
+            ClassWithPopulatedDictionaryAndSetter obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithPopulatedDictionaryAndSetter>(json);
             Assert.Equal(2, obj.MyImmutableDictionary.Count);
         }
 
         [Fact]
-        public static void DictionaryNotSupported()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Multi-dim arrays not supported.")]
+#endif
+        public async Task DictionaryNotSupported()
         {
             string json = @"{""MyDictionary"":{""Key"":""Value""}}";
 
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<ClassWithNotSupportedDictionary>(json));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithNotSupportedDictionary>(json));
 
             // The exception contains the type.
             Assert.Contains(typeof(Dictionary<int[,], int>).ToString(), ex.Message);
         }
 
         [Fact]
-        public static void DictionaryNotSupportedButIgnored()
+#if BUILDING_SOURCE_GENERATOR_TESTS
+        [ActiveIssue("Multi-dim arrays not supported.")]
+#endif
+        public async Task DictionaryNotSupportedButIgnored()
         {
             string json = @"{""MyDictionary"":{""Key"":1}}";
-            ClassWithNotSupportedDictionaryButIgnored obj = JsonSerializer.Deserialize<ClassWithNotSupportedDictionaryButIgnored>(json);
+            ClassWithNotSupportedDictionaryButIgnored obj = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithNotSupportedDictionaryButIgnored>(json);
             Assert.Null(obj.MyDictionary);
         }
 
         // https://github.com/dotnet/runtime/issues/29933
         [Fact]
-        public static void Serialize_IDictionaryOfPoco()
+        public async Task Serialize_IDictionaryOfPoco()
         {
             // Arrange
             var value = new AllSingleUpperPropertiesParent()
@@ -1386,7 +1399,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             };
 
-            var actual = JsonSerializer.Serialize(value, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+            var actual = await JsonSerializerWrapperForString.SerializeWrapper(value, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
 
             // Assert
             Assert.NotNull(actual);
@@ -1395,12 +1408,12 @@ namespace System.Text.Json.Serialization.Tests
 
         // https://github.com/dotnet/runtime/issues/29933
         [Fact]
-        public static void Deserialize_IDictionaryOfPoco()
+        public async Task Deserialize_IDictionaryOfPoco()
         {
             // Arrange
             string json = "{\"child\":{\"1\":{\"a\":\"1\",\"b\":\"\",\"c\":[],\"d\":[],\"e\":null,\"f\":[],\"g\":null,\"h\":null,\"i\":null,\"j\":null,\"k\":[]}}}";
 
-            var actual = JsonSerializer.Deserialize<AllSingleUpperPropertiesParent>(json, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+            var actual = await JsonSerializerWrapperForString.DeserializeWrapper<AllSingleUpperPropertiesParent>(json, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
 
             // Assert
             Assert.NotNull(actual);
@@ -1412,7 +1425,7 @@ namespace System.Text.Json.Serialization.Tests
 
         // https://github.com/dotnet/runtime/issues/29893
         [Fact]
-        public static void ShouldHandleNullInDictionaries_Serialize()
+        public async Task ShouldHandleNullInDictionaries_Serialize()
         {
             var value = new ClassWithDictionaryOfString_ChildWithDictionaryOfString()
             {
@@ -1420,16 +1433,16 @@ namespace System.Text.Json.Serialization.Tests
                 Child = new ClassWithDictionaryOfString()
             };
 
-            var actual = JsonSerializer.Serialize(value);
+            var actual = await JsonSerializerWrapperForString.SerializeWrapper(value);
             Assert.Equal("{\"Test\":\"value1\",\"Dict\":null,\"Child\":{\"Test\":null,\"Dict\":null}}", actual);
         }
 
         // https://github.com/dotnet/runtime/issues/29893
         [Fact]
-        public static void ShouldHandleNullInDictionaries_Deserialize()
+        public async Task ShouldHandleNullInDictionaries_Deserialize()
         {
             var json = "{\"Test\":\"value1\",\"Dict\":null,\"Child\":{\"Test\":null,\"Dict\":null}}";
-            ClassWithDictionaryOfString_ChildWithDictionaryOfString actual = JsonSerializer.Deserialize<ClassWithDictionaryOfString_ChildWithDictionaryOfString>(json);
+            ClassWithDictionaryOfString_ChildWithDictionaryOfString actual = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryOfString_ChildWithDictionaryOfString>(json);
 
             Assert.Equal("value1", actual.Test);
             Assert.Null(actual.Dict);
@@ -1440,7 +1453,7 @@ namespace System.Text.Json.Serialization.Tests
 
         // https://github.com/dotnet/runtime/issues/29893
         [Fact]
-        public static void ShouldHandleNullInDictionaries_Serialize_IgnoreNullValues()
+        public async Task ShouldHandleNullInDictionaries_Serialize_IgnoreNullValues()
         {
             var value = new ClassWithDictionaryOfString_ChildWithDictionaryOfString()
             {
@@ -1448,16 +1461,16 @@ namespace System.Text.Json.Serialization.Tests
                 Child = new ClassWithDictionaryOfString()
             };
 
-            var actual = JsonSerializer.Serialize(value, new JsonSerializerOptions { IgnoreNullValues = true });
+            var actual = await JsonSerializerWrapperForString.SerializeWrapper(value, new JsonSerializerOptions { IgnoreNullValues = true });
             Assert.Equal("{\"Test\":\"value1\",\"Child\":{}}", actual);
         }
 
         // https://github.com/dotnet/runtime/issues/29893
         [Fact]
-        public static void ShouldHandleNullInDictionaries_Deserialize_IgnoreNullValues()
+        public async Task ShouldHandleNullInDictionaries_Deserialize_IgnoreNullValues()
         {
             var json = "{\"Test\":\"value1\",\"Child\":{}}";
-            ClassWithDictionaryOfString_ChildWithDictionaryOfString actual = JsonSerializer.Deserialize<ClassWithDictionaryOfString_ChildWithDictionaryOfString>(json);
+            ClassWithDictionaryOfString_ChildWithDictionaryOfString actual = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryOfString_ChildWithDictionaryOfString>(json);
 
             Assert.Equal("value1", actual.Test);
             Assert.Null(actual.Dict);
@@ -1468,14 +1481,14 @@ namespace System.Text.Json.Serialization.Tests
 
         // https://github.com/dotnet/runtime/issues/29888
         [Fact]
-        public static void DictionaryWithNullShouldPreserveOrder_Serialize()
+        public async Task DictionaryWithNullShouldPreserveOrder_Serialize()
         {
             var dictionaryFirst = new ClassWithDictionaryAndProperty_DictionaryFirst()
             {
                 Test = "value1"
             };
 
-            var actual = JsonSerializer.Serialize(dictionaryFirst);
+            var actual = await JsonSerializerWrapperForString.SerializeWrapper(dictionaryFirst);
             Assert.Equal("{\"Dict\":null,\"Test\":\"value1\"}", actual);
 
             var dictionaryLast = new ClassWithDictionaryAndProperty_DictionaryLast()
@@ -1483,22 +1496,22 @@ namespace System.Text.Json.Serialization.Tests
                 Test = "value1"
             };
 
-            actual = JsonSerializer.Serialize(dictionaryLast);
+            actual = await JsonSerializerWrapperForString.SerializeWrapper(dictionaryLast);
             Assert.Equal("{\"Test\":\"value1\",\"Dict\":null}", actual);
         }
 
         // https://github.com/dotnet/runtime/issues/29888
         [Fact]
-        public static void DictionaryWithNullShouldPreserveOrder_Deserialize()
+        public async Task DictionaryWithNullShouldPreserveOrder_Deserialize()
         {
             var json = "{\"Dict\":null,\"Test\":\"value1\"}";
-            ClassWithDictionaryAndProperty_DictionaryFirst dictionaryFirst = JsonSerializer.Deserialize<ClassWithDictionaryAndProperty_DictionaryFirst>(json);
+            ClassWithDictionaryAndProperty_DictionaryFirst dictionaryFirst = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryAndProperty_DictionaryFirst>(json);
 
             Assert.Equal("value1", dictionaryFirst.Test);
             Assert.Null(dictionaryFirst.Dict);
 
             json = "{\"Test\":\"value1\",\"Dict\":null}";
-            ClassWithDictionaryAndProperty_DictionaryLast dictionaryLast = JsonSerializer.Deserialize<ClassWithDictionaryAndProperty_DictionaryLast>(json);
+            ClassWithDictionaryAndProperty_DictionaryLast dictionaryLast = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryAndProperty_DictionaryLast>(json);
 
             Assert.Equal("value1", dictionaryLast.Test);
             Assert.Null(dictionaryLast.Dict);
@@ -1506,14 +1519,14 @@ namespace System.Text.Json.Serialization.Tests
 
         // https://github.com/dotnet/runtime/issues/29888
         [Fact]
-        public static void DictionaryWithNullShouldPreserveOrder_Serialize_IgnoreNullValues()
+        public async Task DictionaryWithNullShouldPreserveOrder_Serialize_IgnoreNullValues()
         {
             var dictionaryFirst = new ClassWithDictionaryAndProperty_DictionaryFirst()
             {
                 Test = "value1"
             };
 
-            var actual = JsonSerializer.Serialize(dictionaryFirst, new JsonSerializerOptions { IgnoreNullValues = true });
+            var actual = await JsonSerializerWrapperForString.SerializeWrapper(dictionaryFirst, new JsonSerializerOptions { IgnoreNullValues = true });
             Assert.Equal("{\"Test\":\"value1\"}", actual);
 
             var dictionaryLast = new ClassWithDictionaryAndProperty_DictionaryLast()
@@ -1521,29 +1534,29 @@ namespace System.Text.Json.Serialization.Tests
                 Test = "value1"
             };
 
-            actual = JsonSerializer.Serialize(dictionaryLast, new JsonSerializerOptions { IgnoreNullValues = true });
+            actual = await JsonSerializerWrapperForString.SerializeWrapper(dictionaryLast, new JsonSerializerOptions { IgnoreNullValues = true });
             Assert.Equal("{\"Test\":\"value1\"}", actual);
         }
 
         // https://github.com/dotnet/runtime/issues/29888
         [Fact]
-        public static void DictionaryWithNullShouldPreserveOrder_Deserialize_IgnoreNullValues()
+        public async Task DictionaryWithNullShouldPreserveOrder_Deserialize_IgnoreNullValues()
         {
             var json = "{\"Test\":\"value1\"}";
-            ClassWithDictionaryAndProperty_DictionaryFirst dictionaryFirst = JsonSerializer.Deserialize<ClassWithDictionaryAndProperty_DictionaryFirst>(json);
+            ClassWithDictionaryAndProperty_DictionaryFirst dictionaryFirst = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryAndProperty_DictionaryFirst>(json);
 
             Assert.Equal("value1", dictionaryFirst.Test);
             Assert.Null(dictionaryFirst.Dict);
 
             json = "{\"Test\":\"value1\"}";
-            ClassWithDictionaryAndProperty_DictionaryLast dictionaryLast = JsonSerializer.Deserialize<ClassWithDictionaryAndProperty_DictionaryLast>(json);
+            ClassWithDictionaryAndProperty_DictionaryLast dictionaryLast = await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithDictionaryAndProperty_DictionaryLast>(json);
 
             Assert.Equal("value1", dictionaryLast.Test);
             Assert.Null(dictionaryLast.Dict);
         }
 
         [Fact]
-        public static void NullDictionaryValuesShouldDeserializeAsNull()
+        public async Task NullDictionaryValuesShouldDeserializeAsNull()
         {
             const string json =
                     @"{" +
@@ -1564,7 +1577,7 @@ namespace System.Text.Json.Serialization.Tests
                         @"}" +
                     @"}";
 
-            SimpleClassWithDictionaries obj = JsonSerializer.Deserialize<SimpleClassWithDictionaries>(json);
+            SimpleClassWithDictionaries obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleClassWithDictionaries>(json);
             Assert.Null(obj.StringVals["key"]);
             Assert.Null(obj.ObjectVals["key"]);
             Assert.Null(obj.StringDictVals["key"]);
@@ -1726,32 +1739,32 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void DictionaryOfTOnlyWithStringTValueAsInt()
+        public async Task DictionaryOfTOnlyWithStringTValueAsInt()
         {
             const string Json = @"{""One"":1,""Two"":2}";
 
             DictionaryThatOnlyImplementsIDictionaryOfStringTValue<int> dictionary;
 
-            dictionary = JsonSerializer.Deserialize<DictionaryThatOnlyImplementsIDictionaryOfStringTValue<int>>(Json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<DictionaryThatOnlyImplementsIDictionaryOfStringTValue<int>>(Json);
             Assert.Equal(1, dictionary["One"]);
             Assert.Equal(2, dictionary["Two"]);
 
-            string json = JsonSerializer.Serialize(dictionary);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(dictionary);
             Assert.Equal(Json, json);
         }
 
         [Fact]
-        public static void DictionaryOfTOnlyWithStringTValueAsPoco()
+        public async Task DictionaryOfTOnlyWithStringTValueAsPoco()
         {
             const string Json = @"{""One"":{""Id"":1},""Two"":{""Id"":2}}";
 
             DictionaryThatOnlyImplementsIDictionaryOfStringTValue<Poco> dictionary;
 
-            dictionary = JsonSerializer.Deserialize<DictionaryThatOnlyImplementsIDictionaryOfStringTValue<Poco>>(Json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<DictionaryThatOnlyImplementsIDictionaryOfStringTValue<Poco>>(Json);
             Assert.Equal(1, dictionary["One"].Id);
             Assert.Equal(2, dictionary["Two"].Id);
 
-            string json = JsonSerializer.Serialize(dictionary);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(dictionary);
             Assert.Equal(Json, json);
         }
 
@@ -1760,17 +1773,17 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void DictionaryOfTOnlyWithStringPoco()
+        public async Task DictionaryOfTOnlyWithStringPoco()
         {
             const string Json = @"{""One"":{""Id"":1},""Two"":{""Id"":2}}";
 
             DictionaryThatOnlyImplementsIDictionaryOfStringPoco dictionary;
 
-            dictionary = JsonSerializer.Deserialize<DictionaryThatOnlyImplementsIDictionaryOfStringPoco>(Json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<DictionaryThatOnlyImplementsIDictionaryOfStringPoco>(Json);
             Assert.Equal(1, dictionary["One"].Id);
             Assert.Equal(2, dictionary["Two"].Id);
 
-            string json = JsonSerializer.Serialize(dictionary);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(dictionary);
             Assert.Equal(Json, json);
         }
 
@@ -1854,56 +1867,56 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void VerifyDictionaryThatHasIncomatibleEnumeratorWithInt()
+        public async Task VerifyDictionaryThatHasIncomatibleEnumeratorWithInt()
         {
             const string Json = @"{""One"":1,""Two"":2}";
 
             DictionaryThatHasIncompatibleEnumerator dictionary;
-            dictionary = JsonSerializer.Deserialize<DictionaryThatHasIncompatibleEnumerator>(Json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<DictionaryThatHasIncompatibleEnumerator>(Json);
             Assert.Equal(1, ((JsonElement)dictionary["One"]).GetInt32());
             Assert.Equal(2, ((JsonElement)dictionary["Two"]).GetInt32());
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(dictionary));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(dictionary));
         }
 
         [Fact]
-        public static void VerifyDictionaryThatHasIncomatibleEnumeratorWithPoco()
+        public async Task VerifyDictionaryThatHasIncomatibleEnumeratorWithPoco()
         {
             const string Json = @"{""One"":{""Id"":1},""Two"":{""Id"":2}}";
 
             DictionaryThatHasIncompatibleEnumerator dictionary;
-            dictionary = JsonSerializer.Deserialize<DictionaryThatHasIncompatibleEnumerator>(Json);
+            dictionary = await JsonSerializerWrapperForString.DeserializeWrapper<DictionaryThatHasIncompatibleEnumerator>(Json);
             Assert.Equal(1, ((JsonElement)dictionary["One"]).GetProperty("Id").GetInt32());
             Assert.Equal(2, ((JsonElement)dictionary["Two"]).GetProperty("Id").GetInt32());
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(dictionary));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(dictionary));
         }
 
-        private class ClassWithoutParameterlessCtor
+        public class ClassWithoutParameterlessCtor
         {
             public ClassWithoutParameterlessCtor(int num) { }
             public string Name { get; set; }
         }
 
-        private class ClassWithInternalParameterlessConstructor
+        public class ClassWithInternalParameterlessConstructor
         {
             internal ClassWithInternalParameterlessConstructor() { }
             public string Name { get; set; }
         }
 
-        private class ClassWithPrivateParameterlessConstructor
+        public class ClassWithPrivateParameterlessConstructor
         {
             private ClassWithPrivateParameterlessConstructor() { }
             public string Name { get; set; }
         }
 
         [Fact]
-        public static void DictionaryWith_ObjectWithNoParameterlessCtor_AsValue_Throws()
+        public async Task DictionaryWith_ObjectWithNoParameterlessCtor_AsValue_Throws()
         {
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<Dictionary<string, ClassWithInternalParameterlessConstructor>>(@"{""key"":{}}"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<Dictionary<string, ClassWithPrivateParameterlessConstructor>>(@"{""key"":{}}"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, ClassWithInternalParameterlessConstructor>>(@"{""key"":{}}"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<Dictionary<string, ClassWithPrivateParameterlessConstructor>>(@"{""key"":{}}"));
         }
 
         [Fact]
-        public static void DictionaryWith_ObjectWithNoParameterlessCtor_Serialize_Works()
+        public async Task DictionaryWith_ObjectWithNoParameterlessCtor_Serialize_Works()
         {
             var noParameterless = new Dictionary<string, ClassWithoutParameterlessCtor>()
             {
@@ -1913,7 +1926,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             };
 
-            string json = JsonSerializer.Serialize(noParameterless);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(noParameterless);
             Assert.Equal("{\"key\":{\"Name\":\"parameterless\"}}", json);
 
             var onlyInternal = new Dictionary<string, ClassWithInternalParameterlessConstructor>()
@@ -1924,7 +1937,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             };
 
-            json = JsonSerializer.Serialize(onlyInternal);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(onlyInternal);
             Assert.Equal("{\"key\":{\"Name\":\"internal\"}}", json);
 
             var onlyPrivate = new Dictionary<string, ClassWithPrivateParameterlessConstructor>()
@@ -1932,7 +1945,7 @@ namespace System.Text.Json.Serialization.Tests
                 ["key"] = null
             };
 
-            json = JsonSerializer.Serialize(onlyPrivate);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(onlyPrivate);
             Assert.Equal("{\"key\":null}", json);
         }
     }
@@ -3,23 +3,24 @@
 
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void ReadListOfList()
+        public async Task ReadListOfList()
         {
-            List<List<int>> result = JsonSerializer.Deserialize<List<List<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            List<List<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<List<List<int>>>(@"[[1,2],[3,4]]");
 
             Assert.Equal(1, result[0][0]);
             Assert.Equal(2, result[0][1]);
             Assert.Equal(3, result[1][0]);
             Assert.Equal(4, result[1][1]);
 
-            GenericListWrapper<StringListWrapper> result2 = JsonSerializer.Deserialize<GenericListWrapper<StringListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericListWrapper<StringListWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericListWrapper<StringListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
 
             Assert.Equal("1", result2[0][0]);
             Assert.Equal("2", result2[0][1]);
@@ -28,16 +29,16 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadListOfArray()
+        public async Task ReadListOfArray()
         {
-            List<int[]> result = JsonSerializer.Deserialize<List<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            List<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<List<int[]>>(@"[[1,2],[3,4]]");
 
             Assert.Equal(1, result[0][0]);
             Assert.Equal(2, result[0][1]);
             Assert.Equal(3, result[1][0]);
             Assert.Equal(4, result[1][1]);
 
-            GenericListWrapper<string[]> result2 = JsonSerializer.Deserialize<GenericListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericListWrapper<string[]> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
 
             Assert.Equal("1", result2[0][0]);
             Assert.Equal("2", result2[0][1]);
@@ -46,16 +47,16 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfList()
+        public async Task ReadArrayOfList()
         {
-            List<int>[] result = JsonSerializer.Deserialize<List<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            List<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<List<int>[]>(@"[[1,2],[3,4]]");
 
             Assert.Equal(1, result[0][0]);
             Assert.Equal(2, result[0][1]);
             Assert.Equal(3, result[1][0]);
             Assert.Equal(4, result[1][1]);
 
-            StringListWrapper[] result2 = JsonSerializer.Deserialize<StringListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
+            StringListWrapper[] result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
             Assert.Equal("1", result2[0][0]);
             Assert.Equal("2", result2[0][1]);
             Assert.Equal("3", result2[1][0]);
@@ -63,27 +64,27 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleList()
+        public async Task ReadSimpleList()
         {
-            List<int> i = JsonSerializer.Deserialize<List<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            List<int> i = await JsonSerializerWrapperForString.DeserializeWrapper<List<int>>(@"[1,2]");
             Assert.Equal(1, i[0]);
             Assert.Equal(2, i[1]);
 
-            i = JsonSerializer.Deserialize<List<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            i = await JsonSerializerWrapperForString.DeserializeWrapper<List<int>>(@"[]");
             Assert.Equal(0, i.Count);
 
-            StringListWrapper i2 = JsonSerializer.Deserialize<StringListWrapper>(@"[""1"",""2""]");
+            StringListWrapper i2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringListWrapper>(@"[""1"",""2""]");
             Assert.Equal("1", i2[0]);
             Assert.Equal("2", i2[1]);
 
-            i2 = JsonSerializer.Deserialize<StringListWrapper>(@"[]");
+            i2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringListWrapper>(@"[]");
             Assert.Equal(0, i2.Count);
         }
 
         [Fact]
-        public static void ReadGenericIEnumerableOfGenericIEnumerable()
+        public async Task ReadGenericIEnumerableOfGenericIEnumerable()
         {
-            IEnumerable<IEnumerable<int>> result = JsonSerializer.Deserialize<IEnumerable<IEnumerable<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable<IEnumerable<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<IEnumerable<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IEnumerable<int> ie in result)
@@ -95,13 +96,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIEnumerableWrapper<StringIEnumerableWrapper>>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIEnumerableWrapper<StringIEnumerableWrapper>>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadIEnumerableTOfArray()
+        public async Task ReadIEnumerableTOfArray()
         {
-            IEnumerable<int[]> result = JsonSerializer.Deserialize<IEnumerable<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -113,13 +114,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIEnumerableWrapper<int[]>>(@"[[1,2],[3, 4]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIEnumerableWrapper<int[]>>(@"[[1,2],[3, 4]]"));
         }
 
         [Fact]
-        public static void ReadArrayOfIEnumerableT()
+        public async Task ReadArrayOfIEnumerableT()
         {
-            IEnumerable<int>[] result = JsonSerializer.Deserialize<IEnumerable<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IEnumerable<int> arr in result)
@@ -131,13 +132,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIEnumerableWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIEnumerableWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadSimpleGenericIEnumerable()
+        public async Task ReadSimpleGenericIEnumerable()
         {
-            IEnumerable<int> result = JsonSerializer.Deserialize<IEnumerable<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IEnumerable<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -145,18 +146,18 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<IEnumerable<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
             // There is no way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIEnumerableWrapper>(@"[""1"",""2""]"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIEnumerableWrapper>(@"[]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIEnumerableWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIEnumerableWrapper>(@"[]"));
         }
 
         [Fact]
-        public static void ReadIListTOfIListT()
+        public async Task ReadIListTOfIListT()
         {
-            IList<IList<int>> result = JsonSerializer.Deserialize<IList<IList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList<IList<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<IList<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IList<int> ie in result)
@@ -167,7 +168,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericIListWrapper<StringIListWrapper> result2 = JsonSerializer.Deserialize<GenericIListWrapper<StringIListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericIListWrapper<StringIListWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericIListWrapper<StringIListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringIListWrapper il in result2)
@@ -180,9 +181,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericIListOfArray()
+        public async Task ReadGenericIListOfArray()
         {
-            IList<int[]> result = JsonSerializer.Deserialize<IList<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -193,7 +194,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericIListWrapper<string[]> result2 = JsonSerializer.Deserialize<GenericIListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericIListWrapper<string[]> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericIListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (string[] arr in result2)
@@ -206,9 +207,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfIListT()
+        public async Task ReadArrayOfIListT()
         {
-            IList<int>[] result = JsonSerializer.Deserialize<IList<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IList<int> arr in result)
@@ -219,7 +220,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            StringIListWrapper[] result2 = JsonSerializer.Deserialize<StringIListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
+            StringIListWrapper[] result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringIListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringIListWrapper il in result2)
@@ -232,9 +233,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleGenericIList()
+        public async Task ReadSimpleGenericIList()
         {
-            IList<int> result = JsonSerializer.Deserialize<IList<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IList<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -242,10 +243,10 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<IList<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
-            StringIListWrapper result2 = JsonSerializer.Deserialize<StringIListWrapper>(@"[""1"",""2""]");
+            StringIListWrapper result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringIListWrapper>(@"[""1"",""2""]");
             expected = 1;
 
             foreach (string str in result2)
@@ -253,15 +254,15 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal($"{expected++}", str);
             }
 
-            result2 = JsonSerializer.Deserialize<StringIListWrapper>(@"[]");
+            result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringIListWrapper>(@"[]");
             Assert.Equal(0, result2.Count());
         }
 
         [Fact]
-        public static void ReadGenericStructIList()
+        public async Task ReadGenericStructIList()
         {
             string json = "[10,20,30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructIListWrapper<int>>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIListWrapper<int>>(json);
             Assert.Equal(3, wrapper.Count);
             Assert.Equal(10, wrapper[0]);
             Assert.Equal(20, wrapper[1]);
@@ -269,10 +270,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructIList()
+        public async Task ReadNullableGenericStructIList()
         {
             string json = "[10,20,30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructIListWrapper<int>?>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIListWrapper<int>?>(json);
             Assert.True(wrapper.HasValue);
             Assert.Equal(3, wrapper.Value.Count);
             Assert.Equal(10, wrapper.Value[0]);
@@ -281,17 +282,17 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructIListWithNullJson()
+        public async Task ReadNullableGenericStructIListWithNullJson()
         {
-            var wrapper = JsonSerializer.Deserialize<GenericStructIListWrapper<int>?>("null");
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructIListWrapper<int>?>("null");
             Assert.False(wrapper.HasValue);
         }
 
         [Fact]
-        public static void ReadGenericStructICollection()
+        public async Task ReadGenericStructICollection()
         {
             string json = "[10,20,30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructICollectionWrapper<int>>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructICollectionWrapper<int>>(json);
             Assert.Equal(3, wrapper.Count);
             Assert.Equal(10, wrapper.ElementAt(0));
             Assert.Equal(20, wrapper.ElementAt(1));
@@ -299,10 +300,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructICollection()
+        public async Task ReadNullableGenericStructICollection()
         {
             string json = "[10,20,30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructICollectionWrapper<int>?>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructICollectionWrapper<int>?>(json);
             Assert.True(wrapper.HasValue);
             Assert.Equal(3, wrapper.Value.Count);
             Assert.Equal(10, wrapper.Value.ElementAt(0));
@@ -311,16 +312,16 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructICollectionWithNullJson()
+        public async Task ReadNullableGenericStructICollectionWithNullJson()
         {
-            var wrapper = JsonSerializer.Deserialize<GenericStructICollectionWrapper<int>?>("null");
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructICollectionWrapper<int>?>("null");
             Assert.False(wrapper.HasValue);
         }
 
         [Fact]
-        public static void ReadGenericICollectionOfGenericICollection()
+        public async Task ReadGenericICollectionOfGenericICollection()
         {
-            ICollection<ICollection<int>> result = JsonSerializer.Deserialize<ICollection<ICollection<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection<ICollection<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<ICollection<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (ICollection<int> ie in result)
@@ -345,9 +346,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericICollectionOfArray()
+        public async Task ReadGenericICollectionOfArray()
         {
-            ICollection<int[]> result = JsonSerializer.Deserialize<ICollection<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -358,7 +359,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericICollectionWrapper<string[]> result2 = JsonSerializer.Deserialize<GenericICollectionWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericICollectionWrapper<string[]> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericICollectionWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (string[] arr in result2)
@@ -371,9 +372,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfGenericICollection()
+        public async Task ReadArrayOfGenericICollection()
         {
-            ICollection<int>[] result = JsonSerializer.Deserialize<ICollection<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (ICollection<int> arr in result)
@@ -386,9 +387,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleGenericICollection()
+        public async Task ReadSimpleGenericICollection()
         {
-            ICollection<int> result = JsonSerializer.Deserialize<ICollection<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            ICollection<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -396,10 +397,10 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<ICollection<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
-            GenericICollectionWrapper<string> result2 = JsonSerializer.Deserialize<GenericICollectionWrapper<string>>(@"[""1"",""2""]");
+            GenericICollectionWrapper<string> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericICollectionWrapper<string>>(@"[""1"",""2""]");
             expected = 1;
 
             foreach (string str in result2)
@@ -407,14 +408,14 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal($"{expected++}", str);
             }
 
-            result2 = JsonSerializer.Deserialize<GenericICollectionWrapper<string>>(Encoding.UTF8.GetBytes(@"[]"));
+            result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericICollectionWrapper<string>>(@"[]");
             Assert.Equal(0, result2.Count());
         }
 
         [Fact]
-        public static void ReadGenericIReadOnlyCollectionOfGenericIReadOnlyCollection()
+        public async Task ReadGenericIReadOnlyCollectionOfGenericIReadOnlyCollection()
         {
-            IReadOnlyCollection<IReadOnlyCollection<int>> result = JsonSerializer.Deserialize<IReadOnlyCollection<IReadOnlyCollection<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyCollection<IReadOnlyCollection<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyCollection<IReadOnlyCollection<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IReadOnlyCollection<int> ie in result)
@@ -426,14 +427,14 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // There's no way to populate this collection.
-            Assert.Throws<NotSupportedException>(
-                () => JsonSerializer.Deserialize<GenericIReadOnlyCollectionWrapper<WrapperForIReadOnlyCollectionOfT<string>>>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(
+                async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIReadOnlyCollectionWrapper<WrapperForIReadOnlyCollectionOfT<string>>>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadGenericIReadOnlyCollectionOfArray()
+        public async Task ReadGenericIReadOnlyCollectionOfArray()
         {
-            IReadOnlyCollection<int[]> result = JsonSerializer.Deserialize<IReadOnlyCollection<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyCollection<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyCollection<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -444,13 +445,13 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIReadOnlyCollectionWrapper<int[]>>(@"[[1,2],[3,4]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIReadOnlyCollectionWrapper<int[]>>(@"[[1,2],[3,4]]"));
         }
 
         [Fact]
-        public static void ReadArrayOfIReadOnlyCollectionT()
+        public async Task ReadArrayOfIReadOnlyCollectionT()
         {
-            IReadOnlyCollection<int>[] result = JsonSerializer.Deserialize<IReadOnlyCollection<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyCollection<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyCollection<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IReadOnlyCollection<int> arr in result)
@@ -462,13 +463,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<WrapperForIReadOnlyCollectionOfT<string>[]>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<WrapperForIReadOnlyCollectionOfT<string>[]>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadGenericSimpleIReadOnlyCollection()
+        public async Task ReadGenericSimpleIReadOnlyCollection()
         {
-            IReadOnlyCollection<int> result = JsonSerializer.Deserialize<IReadOnlyCollection<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IReadOnlyCollection<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyCollection<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -476,17 +477,17 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<IReadOnlyCollection<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyCollection<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<WrapperForIReadOnlyCollectionOfT<string>>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<WrapperForIReadOnlyCollectionOfT<string>>(@"[""1"",""2""]"));
         }
 
         [Fact]
-        public static void ReadGenericIReadOnlyListOfGenericIReadOnlyList()
+        public async Task ReadGenericIReadOnlyListOfGenericIReadOnlyList()
         {
-            IReadOnlyList<IReadOnlyList<int>> result = JsonSerializer.Deserialize<IReadOnlyList<IReadOnlyList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyList<IReadOnlyList<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyList<IReadOnlyList<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IReadOnlyList<int> ie in result)
@@ -497,13 +498,13 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadGenericIReadOnlyListOfArray()
+        public async Task ReadGenericIReadOnlyListOfArray()
         {
-            IReadOnlyList<int[]> result = JsonSerializer.Deserialize<IReadOnlyList<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyList<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyList<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -515,13 +516,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIReadOnlyListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIReadOnlyListWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadArrayOfGenericIReadOnlyList()
+        public async Task ReadArrayOfGenericIReadOnlyList()
         {
-            IReadOnlyList<int>[] result = JsonSerializer.Deserialize<IReadOnlyList<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IReadOnlyList<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyList<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IReadOnlyList<int> arr in result)
@@ -533,13 +534,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIReadOnlyListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIReadOnlyListWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]"));
         }
 
         [Fact]
-        public static void ReadSimpleGenericIReadOnlyList()
+        public async Task ReadSimpleGenericIReadOnlyList()
         {
-            IReadOnlyList<int> result = JsonSerializer.Deserialize<IReadOnlyList<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IReadOnlyList<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyList<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -547,17 +548,17 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<IReadOnlyList<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyList<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIReadOnlyListWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIReadOnlyListWrapper>(@"[""1"",""2""]"));
         }
 
         [Fact]
-        public static void ReadGenericISetOfGenericISet()
+        public async Task ReadGenericISetOfGenericISet()
         {
-            ISet<ISet<int>> result = JsonSerializer.Deserialize<ISet<ISet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ISet<ISet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<ISet<int>>>(@"[[1,2],[3,4]]");
 
             if (result.First().Contains(1))
             {
@@ -570,7 +571,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(new HashSet<int> { 1, 2 }, result.Last());
             }
 
-            GenericISetWrapper<StringISetWrapper> result2 = JsonSerializer.Deserialize<GenericISetWrapper<StringISetWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericISetWrapper<StringISetWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericISetWrapper<StringISetWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
 
             if (result2.First().Contains("1"))
             {
@@ -585,10 +586,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericStructISet()
+        public async Task ReadGenericStructISet()
         {
             string json = "[10, 20, 30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructISetWrapper<int>>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructISetWrapper<int>>(json);
             Assert.Equal(3, wrapper.Count);
             Assert.Equal(10, wrapper.ElementAt(0));
             Assert.Equal(20, wrapper.ElementAt(1));
@@ -596,10 +597,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructISet()
+        public async Task ReadNullableGenericStructISet()
         {
             string json = "[10, 20, 30]";
-            var wrapper = JsonSerializer.Deserialize<GenericStructISetWrapper<int>?>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructISetWrapper<int>?>(json);
             Assert.True(wrapper.HasValue);
             Assert.Equal(3, wrapper.Value.Count);
             Assert.Equal(10, wrapper.Value.ElementAt(0));
@@ -608,17 +609,17 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableGenericStructISetWithNullJson()
+        public async Task ReadNullableGenericStructISetWithNullJson()
         {
-            var wrapper = JsonSerializer.Deserialize<GenericStructISetWrapper<int>?>("null");
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStructISetWrapper<int>?>("null");
             Assert.False(wrapper.HasValue);
         }
 
         [Fact]
         [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
-        public static void ReadISetTOfHashSetT()
+        public async Task ReadISetTOfHashSetT()
         {
-            ISet<HashSet<int>> result = JsonSerializer.Deserialize<ISet<HashSet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ISet<HashSet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<HashSet<int>>>(@"[[1,2],[3,4]]");
 
             if (result.First().Contains(1))
             {
@@ -633,9 +634,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadHashSetTOfISetT()
+        public async Task ReadHashSetTOfISetT()
         {
-            HashSet<ISet<int>> result = JsonSerializer.Deserialize<HashSet<ISet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            HashSet<ISet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<ISet<int>>>(@"[[1,2],[3,4]]");
 
             if (result.First().Contains(1))
             {
@@ -650,9 +651,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadISetTOfArray()
+        public async Task ReadISetTOfArray()
         {
-            ISet<int[]> result = JsonSerializer.Deserialize<ISet<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ISet<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<int[]>>(@"[[1,2],[3,4]]");
 
             if (result.First().Contains(1))
             {
@@ -667,29 +668,29 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfISetT()
+        public async Task ReadArrayOfISetT()
         {
-            ISet<int>[] result = JsonSerializer.Deserialize<ISet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ISet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<int>[]>(@"[[1,2],[3,4]]");
 
             Assert.Equal(new HashSet<int> { 1, 2 }, result.First());
             Assert.Equal(new HashSet<int> { 3, 4 }, result.Last());
         }
 
         [Fact]
-        public static void ReadSimpleISetT()
+        public async Task ReadSimpleISetT()
         {
-            ISet<int> result = JsonSerializer.Deserialize<ISet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            ISet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<int>>(@"[1,2]");
 
             Assert.Equal(new HashSet<int> { 1, 2 }, result);
 
-            result = JsonSerializer.Deserialize<ISet<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<int>>(@"[]");
             Assert.Equal(0, result.Count());
         }
 
         [Fact]
-        public static void StackTOfStackT()
+        public async Task StackTOfStackT()
         {
-            Stack<Stack<int>> result = JsonSerializer.Deserialize<Stack<Stack<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack<Stack<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<Stack<int>>>(@"[[1,2],[3,4]]");
             int expected = 4;
 
             foreach (Stack<int> st in result)
@@ -700,7 +701,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericStackWrapper<StringStackWrapper> result2 = JsonSerializer.Deserialize<GenericStackWrapper<StringStackWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericStackWrapper<StringStackWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStackWrapper<StringStackWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 4;
 
             foreach (StringStackWrapper st in result2)
@@ -713,9 +714,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericStackOfArray()
+        public async Task ReadGenericStackOfArray()
         {
-            Stack<int[]> result = JsonSerializer.Deserialize<Stack<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<int[]>>(@"[[1,2],[3,4]]");
             int expected = 3;
 
             foreach (int[] arr in result)
@@ -728,7 +729,7 @@ namespace System.Text.Json.Serialization.Tests
                 expected = 1;
             }
 
-            GenericStackWrapper<string[]> result2 = JsonSerializer.Deserialize<GenericStackWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericStackWrapper<string[]> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericStackWrapper<string[]>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 3;
 
             foreach (string[] arr in result2)
@@ -743,9 +744,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfGenericStack()
+        public async Task ReadArrayOfGenericStack()
         {
-            Stack<int>[] result = JsonSerializer.Deserialize<Stack<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<int>[]>(@"[[1,2],[3,4]]");
             int expected = 2;
 
             foreach (Stack<int> st in result)
@@ -758,7 +759,7 @@ namespace System.Text.Json.Serialization.Tests
                 expected = 4;
             }
 
-            StringStackWrapper[] result2 = JsonSerializer.Deserialize<StringStackWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
+            StringStackWrapper[] result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringStackWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 2;
 
             foreach (StringStackWrapper st in result2)
@@ -773,9 +774,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleGenericStack()
+        public async Task ReadSimpleGenericStack()
         {
-            Stack<int> result = JsonSerializer.Deserialize<Stack<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            Stack<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<int>>(@"[1,2]");
             int expected = 2;
 
             foreach (int i in result)
@@ -783,10 +784,10 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected--, i);
             }
 
-            result = JsonSerializer.Deserialize<Stack<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
-            StringStackWrapper result2 = JsonSerializer.Deserialize<StringStackWrapper>(@"[""1"",""2""]");
+            StringStackWrapper result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringStackWrapper>(@"[""1"",""2""]");
             expected = 2;
 
             foreach (string str in result2)
@@ -794,14 +795,14 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal($"{expected--}", str);
             }
 
-            result2 = JsonSerializer.Deserialize<StringStackWrapper>(@"[]");
+            result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringStackWrapper>(@"[]");
             Assert.Equal(0, result2.Count());
         }
 
         [Fact]
-        public static void ReadQueueTOfQueueT()
+        public async Task ReadQueueTOfQueueT()
         {
-            Queue<Queue<int>> result = JsonSerializer.Deserialize<Queue<Queue<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue<Queue<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<Queue<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (Queue<int> q in result)
@@ -812,7 +813,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericQueueWrapper<StringQueueWrapper> result2 = JsonSerializer.Deserialize<GenericQueueWrapper<StringQueueWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericQueueWrapper<StringQueueWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericQueueWrapper<StringQueueWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringQueueWrapper q in result2)
@@ -825,9 +826,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadQueueTOfArray()
+        public async Task ReadQueueTOfArray()
         {
-            Queue<int[]> result = JsonSerializer.Deserialize<Queue<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -840,9 +841,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfIQueueT()
+        public async Task ReadArrayOfIQueueT()
         {
-            Queue<int>[] result = JsonSerializer.Deserialize<Queue<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (Queue<int> q in result)
@@ -855,24 +856,24 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleQueueT()
+        public async Task ReadSimpleQueueT()
         {
-            Queue<int> result = JsonSerializer.Deserialize<Queue<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            Queue<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
             {
                 Assert.Equal(expected++, i);
             }
-            result = JsonSerializer.Deserialize<Queue<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<int>>(@"[]");
             Assert.Equal(0, result.Count());
 
         }
 
         [Fact]
-        public static void ReadHashSetTOfHashSetT()
+        public async Task ReadHashSetTOfHashSetT()
         {
-            HashSet<HashSet<int>> result = JsonSerializer.Deserialize<HashSet<HashSet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            HashSet<HashSet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<HashSet<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (HashSet<int> hs in result)
@@ -883,7 +884,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericHashSetWrapper<StringHashSetWrapper> result2 = JsonSerializer.Deserialize<GenericHashSetWrapper<StringHashSetWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericHashSetWrapper<StringHashSetWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericHashSetWrapper<StringHashSetWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringHashSetWrapper hs in result2)
@@ -896,9 +897,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadHashSetTOfArray()
+        public async Task ReadHashSetTOfArray()
         {
-            HashSet<int[]> result = JsonSerializer.Deserialize<HashSet<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            HashSet<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -911,9 +912,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfIHashSetT()
+        public async Task ReadArrayOfIHashSetT()
         {
-            HashSet<int>[] result = JsonSerializer.Deserialize<HashSet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            HashSet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (HashSet<int> hs in result)
@@ -926,9 +927,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleHashSetT()
+        public async Task ReadSimpleHashSetT()
         {
-            HashSet<int> result = JsonSerializer.Deserialize<HashSet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            HashSet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -936,14 +937,14 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<HashSet<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<int>>(@"[]");
             Assert.Equal(0, result.Count());
         }
 
         [Fact]
-        public static void ReadGenericLinkedListOfGenericLinkedList()
+        public async Task ReadGenericLinkedListOfGenericLinkedList()
         {
-            LinkedList<LinkedList<int>> result = JsonSerializer.Deserialize<LinkedList<LinkedList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            LinkedList<LinkedList<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<LinkedList<LinkedList<int>>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (LinkedList<int> l in result)
@@ -954,7 +955,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericLinkedListWrapper<StringLinkedListWrapper> result2 = JsonSerializer.Deserialize<GenericLinkedListWrapper<StringLinkedListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
+            GenericLinkedListWrapper<StringLinkedListWrapper> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericLinkedListWrapper<StringLinkedListWrapper>>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringLinkedListWrapper l in result2)
@@ -967,9 +968,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadLinkedListTOfArray()
+        public async Task ReadLinkedListTOfArray()
         {
-            LinkedList<int[]> result = JsonSerializer.Deserialize<LinkedList<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            LinkedList<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<LinkedList<int[]>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (int[] arr in result)
@@ -982,9 +983,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfILinkedListT()
+        public async Task ReadArrayOfILinkedListT()
         {
-            LinkedList<int>[] result = JsonSerializer.Deserialize<LinkedList<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            LinkedList<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<LinkedList<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (LinkedList<int> l in result)
@@ -997,9 +998,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleLinkedListT()
+        public async Task ReadSimpleLinkedListT()
         {
-            LinkedList<int> result = JsonSerializer.Deserialize<LinkedList<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            LinkedList<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<LinkedList<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -1007,14 +1008,14 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<LinkedList<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<LinkedList<int>>(@"[]");
             Assert.Equal(0, result.Count());
         }
 
         [Fact]
-        public static void ReadArrayOfSortedSetT()
+        public async Task ReadArrayOfSortedSetT()
         {
-            SortedSet<int>[] result = JsonSerializer.Deserialize<SortedSet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            SortedSet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<SortedSet<int>[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (SortedSet<int> s in result)
@@ -1025,7 +1026,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            StringSortedSetWrapper[] result2 = JsonSerializer.Deserialize<StringSortedSetWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
+            StringSortedSetWrapper[] result2 = await JsonSerializerWrapperForString.DeserializeWrapper<StringSortedSetWrapper[]>(@"[[""1"",""2""],[""3"",""4""]]");
             expected = 1;
 
             foreach (StringSortedSetWrapper s in result2)
@@ -1038,9 +1039,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleSortedSetT()
+        public async Task ReadSimpleSortedSetT()
         {
-            SortedSet<int> result = JsonSerializer.Deserialize<SortedSet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            SortedSet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<SortedSet<int>>(@"[1,2]");
             int expected = 1;
 
             foreach (int i in result)
@@ -1048,31 +1049,31 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i);
             }
 
-            result = JsonSerializer.Deserialize<SortedSet<int>>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<SortedSet<int>>(@"[]");
             Assert.Equal(0, result.Count());
         }
 
         [Fact]
-        public static void ReadClass_WithGenericStructCollectionWrapper_NullJson_Throws()
+        public async Task ReadClass_WithGenericStructCollectionWrapper_NullJson_Throws()
         {
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithGenericStructIListWrapper>(@"{ ""List"": null }"));
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithGenericStructICollectionWrapper>(@"{ ""Collection"": null }"));
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithGenericStructIDictionaryWrapper>(@"{ ""Dictionary"": null }"));
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithGenericStructISetWrapper>(@"{ ""Set"": null }"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithGenericStructIListWrapper>(@"{ ""List"": null }"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithGenericStructICollectionWrapper>(@"{ ""Collection"": null }"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithGenericStructIDictionaryWrapper>(@"{ ""Dictionary"": null }"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithGenericStructISetWrapper>(@"{ ""Set"": null }"));
         }
 
         [Fact]
-        public static void ReadSimpleTestClass_GenericStructCollectionWrappers()
+        public async Task ReadSimpleTestClass_GenericStructCollectionWrappers()
         {
-            SimpleTestClassWithGenericStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestClassWithGenericStructCollectionWrappers>(SimpleTestClassWithGenericStructCollectionWrappers.s_json);
+            SimpleTestClassWithGenericStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithGenericStructCollectionWrappers>(SimpleTestClassWithGenericStructCollectionWrappers.s_json);
             obj.Verify();
         }
 
         [Fact]
-        public static void ReadSimpleTestStruct_NullableGenericStructCollectionWrappers()
+        public async Task ReadSimpleTestStruct_NullableGenericStructCollectionWrappers()
         {
             {
-                SimpleTestStructWithNullableGenericStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestStructWithNullableGenericStructCollectionWrappers>(SimpleTestStructWithNullableGenericStructCollectionWrappers.s_json);
+                SimpleTestStructWithNullableGenericStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestStructWithNullableGenericStructCollectionWrappers>(SimpleTestStructWithNullableGenericStructCollectionWrappers.s_json);
                 obj.Verify();
             }
 
@@ -1084,7 +1085,7 @@ namespace System.Text.Json.Serialization.Tests
                         @"""Set"" : null," +
                         @"""Dictionary"" : null" +
                         @"}";
-                SimpleTestStructWithNullableGenericStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestStructWithNullableGenericStructCollectionWrappers>(json);
+                SimpleTestStructWithNullableGenericStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestStructWithNullableGenericStructCollectionWrappers>(json);
                 Assert.False(obj.List.HasValue);
                 Assert.False(obj.Collection.HasValue);
                 Assert.False(obj.Set.HasValue);
@@ -1093,17 +1094,17 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleTestClass_GenericCollectionWrappers()
+        public async Task ReadSimpleTestClass_GenericCollectionWrappers()
         {
-            SimpleTestClassWithGenericCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestClassWithGenericCollectionWrappers>(SimpleTestClassWithGenericCollectionWrappers.s_json);
+            SimpleTestClassWithGenericCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithGenericCollectionWrappers>(SimpleTestClassWithGenericCollectionWrappers.s_json);
             obj.Verify();
         }
 
         [Theory]
         [MemberData(nameof(ReadSimpleTestClass_GenericWrappers_NoAddMethod))]
-        public static void ReadSimpleTestClass_GenericWrappers_NoAddMethod_Throws(Type type, string json, Type exceptionMessageType)
+        public async Task ReadSimpleTestClass_GenericWrappers_NoAddMethod_Throws(Type type, string json, Type exceptionMessageType)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
             Assert.Contains(exceptionMessageType.ToString(), ex.Message);
         }
 
@@ -1145,22 +1146,22 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(typeof(ReadOnlyStringISetWrapper), @"[""1"", ""2""]")]
         [InlineData(typeof(ReadOnlyWrapperForIDictionary), @"{""Key"":""key"",""Value"":""value""}")]
         [InlineData(typeof(ReadOnlyStringToStringIDictionaryWrapper), @"{""Key"":""key"",""Value"":""value""}")]
-        public static void ReadReadOnlyCollections_Throws(Type type, string json)
+        public async Task ReadReadOnlyCollections_Throws(Type type, string json)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
             Assert.Contains(type.ToString(), ex.Message);
         }
 
         [Fact]
-        public static void Read_HigherOrderCollectionInheritance_Works()
+        public async Task Read_HigherOrderCollectionInheritance_Works()
         {
             const string json = "[\"test\"]";
-            Assert.Equal("test", JsonSerializer.Deserialize<string[]>(json)[0]);
-            Assert.Equal("test", JsonSerializer.Deserialize<List<string>>(json).First());
-            Assert.Equal("test", JsonSerializer.Deserialize<StringListWrapper>(json).First());
-            Assert.Equal("test", JsonSerializer.Deserialize<GenericListWrapper<string>>(json).First());
-            Assert.Equal("test", JsonSerializer.Deserialize<MyMyList<string>>(json).First());
-            Assert.Equal("test", JsonSerializer.Deserialize<MyListString>(json).First());
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<string[]>(json))[0]);
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<List<string>>(json)).First());
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<StringListWrapper>(json)).First());
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<GenericListWrapper<string>>(json)).First());
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<MyMyList<string>>(json)).First());
+            Assert.Equal("test", (await JsonSerializerWrapperForString.DeserializeWrapper<MyListString>(json)).First());
         }
 
         [Theory]
@@ -1184,21 +1185,21 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(typeof(GenericStackWrapperInternalConstructor<string>), @"[""1""]")]
         [InlineData(typeof(StringToGenericDictionaryWrapperPrivateConstructor<string>), @"{""Key"":""Value""}")]
         [InlineData(typeof(StringToGenericDictionaryWrapperInternalConstructor<string>), @"{""Key"":""Value""}")]
-        public static void Read_Generic_NoPublicConstructor_Throws(Type type, string json)
+        public async Task Read_Generic_NoPublicConstructor_Throws(Type type, string json)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
             Assert.Contains(type.ToString(), ex.Message);
         }
 
         [Fact]
-        public static void DoesNotCall_CollectionPropertyGetter_EveryTimeElementIsAdded()
+        public async Task DoesNotCall_CollectionPropertyGetter_EveryTimeElementIsAdded()
         {
             var networkList = new List<string> { "Network1", "Network2" };
 
-            string serialized = JsonSerializer.Serialize(new NetworkWrapper { NetworkList = networkList });
+            string serialized = await JsonSerializerWrapperForString.SerializeWrapper(new NetworkWrapper { NetworkList = networkList });
             Assert.Equal(@"{""NetworkList"":[""Network1"",""Network2""]}", serialized);
 
-            NetworkWrapper obj = JsonSerializer.Deserialize<NetworkWrapper>(serialized);
+            NetworkWrapper obj = await JsonSerializerWrapperForString.DeserializeWrapper<NetworkWrapper>(serialized);
 
             int i = 0;
             foreach (string network in obj.NetworkList)
@@ -1227,18 +1228,18 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void CollectionWith_BackingField_CanRoundtrip()
+        public async Task CollectionWith_BackingField_CanRoundtrip()
         {
             string json = "{\"AllowedGrantTypes\":[\"client_credentials\"]}";
 
-            Client obj = JsonSerializer.Deserialize<Client>(json);
+            Client obj = await JsonSerializerWrapperForString.DeserializeWrapper<Client>(json);
             Assert.Equal("client_credentials", obj.AllowedGrantTypes.First());
 
-            string serialized = JsonSerializer.Serialize(obj);
+            string serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj);
             Assert.Equal(json, serialized);
         }
 
-        private class Client
+        public class Client
         {
             private ICollection<string> _allowedGrantTypes = new HashSetWithBackingCollection();
 
@@ -1251,17 +1252,17 @@ namespace System.Text.Json.Serialization.Tests
 
         [Theory]
         [MemberData(nameof(CustomInterfaces_Enumerables))]
-        public static void CustomInterfacesNotSupported_Enumerables(Type type)
+        public async Task CustomInterfacesNotSupported_Enumerables(Type type)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize("[]", type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper("[]", type));
             Assert.Contains(type.ToString(), ex.ToString());
         }
 
         [Theory]
         [MemberData(nameof(CustomInterfaces_Dictionaries))]
-        public static void CustomInterfacesNotSupported_Dictionaries(Type type)
+        public async Task CustomInterfacesNotSupported_Dictionaries(Type type)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize("{}", type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}", type));
             Assert.Contains(type.ToString(), ex.ToString());
         }
 
@@ -1278,10 +1279,10 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void IReadOnlyDictionary_NotSupportedKey()
+        public async Task IReadOnlyDictionary_NotSupportedKey()
         {
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<IReadOnlyDictionary<Uri, int>>(@"{""http://foo"":1}"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Serialize(new GenericIReadOnlyDictionaryWrapper<Uri, int>(new Dictionary<Uri, int> { { new Uri("http://foo"), 1 } })));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<IReadOnlyDictionary<Uri, int>>(@"{""http://foo"":1}"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(new GenericIReadOnlyDictionaryWrapper<Uri, int>(new Dictionary<Uri, int> { { new Uri("http://foo"), 1 } })));
         }
     }
 }
@@ -3,14 +3,15 @@
 
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void WriteListOfList()
+        public async Task WriteListOfList()
         {
             var input = new List<List<int>>
             {
@@ -18,7 +19,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             var input2 = new GenericListWrapper<StringListWrapper>
@@ -27,12 +28,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringListWrapper() { "3", "4" }
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteListOfArray()
+        public async Task WriteListOfArray()
         {
             var input = new List<int[]>
             {
@@ -40,32 +41,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfList()
+        public async Task WriteArrayOfList()
         {
             var input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveList()
+        public async Task WritePrimitiveList()
         {
             var input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteGenericIEnumerableOfGenericIEnumerable()
+        public async Task WriteGenericIEnumerableOfGenericIEnumerable()
         {
             IEnumerable<IEnumerable<int>> input = new List<List<int>>
             {
@@ -73,7 +74,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericIEnumerableWrapper<StringIEnumerableWrapper> input2 = new GenericIEnumerableWrapper<StringIEnumerableWrapper>(new List<StringIEnumerableWrapper>
@@ -82,12 +83,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringIEnumerableWrapper(new List<string> { "3", "4" }),
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteIEnumerableTOfArray()
+        public async Task WriteIEnumerableTOfArray()
         {
             IEnumerable<int[]> input = new List<int[]>
             {
@@ -95,32 +96,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIEnumerableT()
+        public async Task WriteArrayOfIEnumerableT()
         {
             IEnumerable<int>[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIEnumerableT()
+        public async Task WritePrimitiveIEnumerableT()
         {
             IEnumerable<int> input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteGenericIListOfGenericIList()
+        public async Task WriteGenericIListOfGenericIList()
         {
             IList<IList<int>> input = new List<IList<int>>
             {
@@ -128,7 +129,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericIListWrapper<StringIListWrapper> input2 = new GenericIListWrapper<StringIListWrapper>
@@ -137,12 +138,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringIListWrapper() { "3", "4" }
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteIListTOfArray()
+        public async Task WriteIListTOfArray()
         {
             IList<int[]> input = new List<int[]>
             {
@@ -150,60 +151,60 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIListT()
+        public async Task WriteArrayOfIListT()
         {
             IList<int>[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIListT()
+        public async Task WritePrimitiveIListT()
         {
             IList<int> input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteGenericStructIListWrapperT()
+        public async Task WriteGenericStructIListWrapperT()
         {
             {
                 GenericStructIListWrapper<int> obj = new GenericStructIListWrapper<int>() { 10, 20 };
-                Assert.Equal("[10,20]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[10,20]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
                 GenericStructIListWrapper<int> obj = default;
-                Assert.Equal("[]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteGenericStructICollectionWrapperT()
+        public async Task WriteGenericStructICollectionWrapperT()
         {
             {
                 GenericStructICollectionWrapper<int> obj = new GenericStructICollectionWrapper<int>() { 10, 20 };
-                Assert.Equal("[10,20]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[10,20]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
                 GenericStructICollectionWrapper<int> obj = default;
-                Assert.Equal("[]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteGenericICollectionOfGenericICollection()
+        public async Task WriteGenericICollectionOfGenericICollection()
         {
             ICollection<ICollection<int>> input = new List<ICollection<int>>
             {
@@ -211,7 +212,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericICollectionWrapper<GenericICollectionWrapper<string>> input2 = new GenericICollectionWrapper<GenericICollectionWrapper<string>>
@@ -220,12 +221,12 @@ namespace System.Text.Json.Serialization.Tests
                 new GenericICollectionWrapper<string>() { "3", "4" }
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteICollectionTOfArray()
+        public async Task WriteICollectionTOfArray()
         {
             ICollection<int[]> input = new List<int[]>
             {
@@ -233,32 +234,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfICollectionT()
+        public async Task WriteArrayOfICollectionT()
         {
             ICollection<int>[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveICollectionT()
+        public async Task WritePrimitiveICollectionT()
         {
             ICollection<int> input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteGenericIReadOnlyCollectionOfGenericIReadOnlyCollection()
+        public async Task WriteGenericIReadOnlyCollectionOfGenericIReadOnlyCollection()
         {
             IReadOnlyCollection<IReadOnlyCollection<int>> input = new List<List<int>>
             {
@@ -266,7 +267,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericIReadOnlyCollectionWrapper<WrapperForIReadOnlyCollectionOfT<string>> input2 =
@@ -276,12 +277,12 @@ namespace System.Text.Json.Serialization.Tests
                 new WrapperForIReadOnlyCollectionOfT<string>(new List<string> { "3", "4" })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteIReadOnlyCollectionTOfArray()
+        public async Task WriteIReadOnlyCollectionTOfArray()
         {
             IReadOnlyCollection<int[]> input = new List<int[]>
             {
@@ -289,32 +290,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIReadOnlyCollectionT()
+        public async Task WriteArrayOfIReadOnlyCollectionT()
         {
             IReadOnlyCollection<int>[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIReadOnlyCollectionT()
+        public async Task WritePrimitiveIReadOnlyCollectionT()
         {
             IReadOnlyCollection<int> input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteIReadOnlyListTOfIReadOnlyListT()
+        public async Task WriteIReadOnlyListTOfIReadOnlyListT()
         {
             IReadOnlyList<IReadOnlyList<int>> input = new List<List<int>>
             {
@@ -322,7 +323,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper> input2 = new GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper>(new List<StringIReadOnlyListWrapper>
@@ -331,12 +332,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringIReadOnlyListWrapper(new List<string> { "3", "4" })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteIReadOnlyListTOfArray()
+        public async Task WriteIReadOnlyListTOfArray()
         {
             IReadOnlyList<int[]> input = new List<int[]>
             {
@@ -344,47 +345,47 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIReadOnlyListT()
+        public async Task WriteArrayOfIReadOnlyListT()
         {
             IReadOnlyList<int>[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIReadOnlyListT()
+        public async Task WritePrimitiveIReadOnlyListT()
         {
             IReadOnlyList<int> input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void GenericStructISetWrapperT()
+        public async Task GenericStructISetWrapperT()
         {
             {
                 GenericStructISetWrapper<int> obj = new GenericStructISetWrapper<int>() { 10, 20 };
-                Assert.Equal("[10,20]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[10,20]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
                 GenericStructISetWrapper<int> obj = default;
-                Assert.Equal("[]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
         [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
-        public static void WriteISetTOfISetT()
+        public async Task WriteISetTOfISetT()
         {
             ISet<ISet<int>> input = new HashSet<ISet<int>>
             {
@@ -392,10 +393,10 @@ namespace System.Text.Json.Serialization.Tests
                 new HashSet<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<ISet<ISet<int>>>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<ISet<int>>>(json);
 
             if (input.First().Contains(1))
             {
@@ -414,10 +415,10 @@ namespace System.Text.Json.Serialization.Tests
                 new StringISetWrapper() { "3", "4" },
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input2 = JsonSerializer.Deserialize<GenericISetWrapper<StringISetWrapper>>(json);
+            input2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericISetWrapper<StringISetWrapper>>(json);
 
             if (input2.First().Contains("1"))
             {
@@ -433,7 +434,7 @@ namespace System.Text.Json.Serialization.Tests
 
         [Fact]
         [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
-        public static void WriteISetTOfHashSetT()
+        public async Task WriteISetTOfHashSetT()
         {
             ISet<HashSet<int>> input = new HashSet<HashSet<int>>
             {
@@ -441,10 +442,10 @@ namespace System.Text.Json.Serialization.Tests
                 new HashSet<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<ISet<HashSet<int>>>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<HashSet<int>>>(json);
 
             if (input.First().Contains(1))
             {
@@ -459,7 +460,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void WriteHashSetTOfISetT()
+        public async Task WriteHashSetTOfISetT()
         {
             HashSet<ISet<int>> input = new HashSet<ISet<int>>
             {
@@ -467,10 +468,10 @@ namespace System.Text.Json.Serialization.Tests
                 new HashSet<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<HashSet<ISet<int>>>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<ISet<int>>>(json);
 
             if (input.First().Contains(1))
             {
@@ -485,7 +486,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void WriteISetTOfArray()
+        public async Task WriteISetTOfArray()
         {
             ISet<int[]> input = new HashSet<int[]>
             {
@@ -493,37 +494,37 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfISetT()
+        public async Task WriteArrayOfISetT()
         {
             ISet<int>[] input = new HashSet<int>[2];
             input[0] = new HashSet<int>() { 1, 2 };
             input[1] = new HashSet<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<ISet<int>[]>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<ISet<int>[]>(json);
             Assert.Equal(new HashSet<int> { 1, 2 }, input.First());
             Assert.Equal(new HashSet<int> { 3, 4 }, input.Last());
         }
 
         [Fact]
-        public static void WritePrimitiveISetT()
+        public async Task WritePrimitiveISetT()
         {
             ISet<int> input = new HashSet<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.True(json == "[1,2]" || json == "[2,1]");
         }
 
         [Fact]
-        public static void WriteStackTOfStackT()
+        public async Task WriteStackTOfStackT()
         {
             Stack<Stack<int>> input = new Stack<Stack<int>>(new List<Stack<int>>
             {
@@ -531,7 +532,7 @@ namespace System.Text.Json.Serialization.Tests
                 new Stack<int>(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[4,3],[2,1]]", json);
 
             GenericStackWrapper<StringStackWrapper> input2 = new GenericStackWrapper<StringStackWrapper>(new List<StringStackWrapper>
@@ -540,12 +541,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringStackWrapper(new List<string>() { "3", "4" })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""4"",""3""],[""2"",""1""]]", json);
         }
 
         [Fact]
-        public static void WriteStackTOfArray()
+        public async Task WriteStackTOfArray()
         {
             Stack<int[]> input = new Stack<int[]>(new List<int[]>
             {
@@ -553,32 +554,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[3,4],[1,2]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfStackT()
+        public async Task WriteArrayOfStackT()
         {
             Stack<int>[] input = new Stack<int>[2];
             input[0] = new Stack<int>(new List<int> { 1, 2 });
             input[1] = new Stack<int>(new List<int> { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[2,1],[4,3]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveStackT()
+        public async Task WritePrimitiveStackT()
         {
             Stack<int> input = new Stack<int>(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[2,1]", json);
         }
 
         [Fact]
-        public static void WriteQueueTOfQueueT()
+        public async Task WriteQueueTOfQueueT()
         {
             Queue<Queue<int>> input = new Queue<Queue<int>>(new List<Queue<int>>
             {
@@ -586,7 +587,7 @@ namespace System.Text.Json.Serialization.Tests
                 new Queue<int>(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericQueueWrapper<StringQueueWrapper> input2 = new GenericQueueWrapper<StringQueueWrapper>(new List<StringQueueWrapper>
@@ -595,12 +596,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringQueueWrapper(new List<string>() { "3", "4" })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteQueueTOfArray()
+        public async Task WriteQueueTOfArray()
         {
             Queue<int[]> input = new Queue<int[]>(new List<int[]>
             {
@@ -608,32 +609,32 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfQueueT()
+        public async Task WriteArrayOfQueueT()
         {
             Queue<int>[] input = new Queue<int>[2];
             input[0] = new Queue<int>(new List<int> { 1, 2 });
             input[1] = new Queue<int>(new List<int> { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveQueueT()
+        public async Task WritePrimitiveQueueT()
         {
             Queue<int> input = new Queue<int>(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteHashSetTOfHashSetT()
+        public async Task WriteHashSetTOfHashSetT()
         {
             HashSet<HashSet<int>> input = new HashSet<HashSet<int>>(new List<HashSet<int>>
             {
@@ -641,10 +642,10 @@ namespace System.Text.Json.Serialization.Tests
                 new HashSet<int>(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<HashSet<HashSet<int>>>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<HashSet<int>>>(json);
 
             if (input.First().Contains(1))
             {
@@ -663,10 +664,10 @@ namespace System.Text.Json.Serialization.Tests
                 new StringHashSetWrapper(new List<string>() { "3", "4" })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input2 = JsonSerializer.Deserialize<GenericHashSetWrapper<StringHashSetWrapper>>(json);
+            input2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericHashSetWrapper<StringHashSetWrapper>>(json);
 
             if (input2.First().Contains("1"))
             {
@@ -681,7 +682,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void WriteHashSetTOfArray()
+        public async Task WriteHashSetTOfArray()
         {
             HashSet<int[]> input = new HashSet<int[]>(new List<int[]>
             {
@@ -689,38 +690,38 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
         [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))]
-        public static void WriteArrayOfHashSetT()
+        public async Task WriteArrayOfHashSetT()
         {
             HashSet<int>[] input = new HashSet<int>[2];
             input[0] = new HashSet<int>(new List<int> { 1, 2 });
             input[1] = new HashSet<int>(new List<int> { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
 
             // Because order isn't guaranteed, roundtrip data to ensure write was accurate.
-            input = JsonSerializer.Deserialize<HashSet<int>[]>(json);
+            input = await JsonSerializerWrapperForString.DeserializeWrapper<HashSet<int>[]>(json);
             Assert.Equal(new HashSet<int> { 1, 2 }, input.First());
             Assert.Equal(new HashSet<int> { 3, 4 }, input.Last());
         }
 
         [Fact]
-        public static void WritePrimitiveHashSetT()
+        public async Task WritePrimitiveHashSetT()
         {
             HashSet<int> input = new HashSet<int>(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.True(json == "[1,2]" || json == "[2,1]");
         }
 
         [Fact]
-        public static void WriteLinkedListTOfLinkedListT()
+        public async Task WriteLinkedListTOfLinkedListT()
         {
             LinkedList<LinkedList<int>> input = new LinkedList<LinkedList<int>>(new List<LinkedList<int>>
             {
@@ -728,7 +729,7 @@ namespace System.Text.Json.Serialization.Tests
                 new LinkedList<int>(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericLinkedListWrapper<StringLinkedListWrapper> input2 = new GenericLinkedListWrapper<StringLinkedListWrapper>(new List<StringLinkedListWrapper>
@@ -737,12 +738,12 @@ namespace System.Text.Json.Serialization.Tests
                 new StringLinkedListWrapper(new List<string>() { "3", "4" }),
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[[""1"",""2""],[""3"",""4""]]", json);
         }
 
         [Fact]
-        public static void WriteLinkedListTOfArray()
+        public async Task WriteLinkedListTOfArray()
         {
             LinkedList<int[]> input = new LinkedList<int[]>(new List<int[]>
             {
@@ -750,52 +751,52 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfLinkedListT()
+        public async Task WriteArrayOfLinkedListT()
         {
             LinkedList<int>[] input = new LinkedList<int>[2];
             input[0] = new LinkedList<int>(new List<int> { 1, 2 });
             input[1] = new LinkedList<int>(new List<int> { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveLinkedListT()
+        public async Task WritePrimitiveLinkedListT()
         {
             LinkedList<int> input = new LinkedList<int>(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfSortedSetT()
+        public async Task WriteArrayOfSortedSetT()
         {
             SortedSet<int>[] input = new SortedSet<int>[2];
             input[0] = new SortedSet<int>(new List<int> { 1, 2 });
             input[1] = new SortedSet<int>(new List<int> { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveSortedSetT()
+        public async Task WritePrimitiveSortedSetT()
         {
             SortedSet<int> input = new SortedSet<int>(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteGenericCollectionWrappers()
+        public async Task WriteGenericCollectionWrappers()
         {
             SimpleTestClassWithGenericCollectionWrappers obj1 = new SimpleTestClassWithGenericCollectionWrappers();
             SimpleTestClassWithStringIEnumerableWrapper obj2 = new SimpleTestClassWithStringIEnumerableWrapper();
@@ -809,29 +810,29 @@ namespace System.Text.Json.Serialization.Tests
             obj4.Initialize();
             obj5.Initialize();
 
-            Assert.Equal(SimpleTestClassWithGenericCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj1));
-            Assert.Equal(SimpleTestClassWithGenericCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj1));
+            Assert.Equal(SimpleTestClassWithGenericCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj1));
+            Assert.Equal(SimpleTestClassWithGenericCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj1));
 
-            Assert.Equal(SimpleTestClassWithStringIEnumerableWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj2));
-            Assert.Equal(SimpleTestClassWithStringIEnumerableWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj2));
+            Assert.Equal(SimpleTestClassWithStringIEnumerableWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj2));
+            Assert.Equal(SimpleTestClassWithStringIEnumerableWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj2));
 
-            Assert.Equal(SimpleTestClassWithStringIReadOnlyCollectionWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj3));
-            Assert.Equal(SimpleTestClassWithStringIReadOnlyCollectionWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj3));
+            Assert.Equal(SimpleTestClassWithStringIReadOnlyCollectionWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj3));
+            Assert.Equal(SimpleTestClassWithStringIReadOnlyCollectionWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj3));
 
-            Assert.Equal(SimpleTestClassWithStringIReadOnlyListWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj4));
-            Assert.Equal(SimpleTestClassWithStringIReadOnlyListWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj4));
+            Assert.Equal(SimpleTestClassWithStringIReadOnlyListWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj4));
+            Assert.Equal(SimpleTestClassWithStringIReadOnlyListWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj4));
 
-            Assert.Equal(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj5));
-            Assert.Equal(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj5));
+            Assert.Equal(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj5));
+            Assert.Equal(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj5));
         }
 
         [Fact]
-        public static void WriteSimpleTestClassWithGenericStructCollectionWrappers()
+        public async Task WriteSimpleTestClassWithGenericStructCollectionWrappers()
         {
             {
                 SimpleTestClassWithGenericStructCollectionWrappers obj = new SimpleTestClassWithGenericStructCollectionWrappers();
                 obj.Initialize();
-                Assert.Equal(SimpleTestClassWithGenericStructCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(SimpleTestClassWithGenericStructCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
@@ -849,17 +850,17 @@ namespace System.Text.Json.Serialization.Tests
                     @"""Set"" : []," +
                     @"""Dictionary"" : {}" +
                     @"}";
-                Assert.Equal(json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteSimpleTestStructWithNullableGenericStructCollectionWrappers()
+        public async Task WriteSimpleTestStructWithNullableGenericStructCollectionWrappers()
         {
             {
                 SimpleTestStructWithNullableGenericStructCollectionWrappers obj = new SimpleTestStructWithNullableGenericStructCollectionWrappers();
                 obj.Initialize();
-                Assert.Equal(SimpleTestStructWithNullableGenericStructCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(SimpleTestStructWithNullableGenericStructCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
@@ -871,87 +872,87 @@ namespace System.Text.Json.Serialization.Tests
                     @"""Set"" : null," +
                     @"""Dictionary"" : null" +
                     @"}";
-                Assert.Equal(json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void ConvertIEnumerableValueTypesThenSerialize()
+        public async Task ConvertIEnumerableValueTypesThenSerialize()
         {
             IEnumerable<ValueA> valueAs = Enumerable.Range(0, 5).Select(x => new ValueA { Value = x }).ToList();
             IEnumerable<ValueB> valueBs = valueAs.Select(x => new ValueB { Value = x.Value });
 
             string expectedJson = @"[{""Value"":0},{""Value"":1},{""Value"":2},{""Value"":3},{""Value"":4}]";
-            Assert.Equal(expectedJson, JsonSerializer.Serialize<IEnumerable<ValueB>>(valueBs));
+            Assert.Equal(expectedJson, await JsonSerializerWrapperForString.SerializeWrapper<IEnumerable<ValueB>>(valueBs));
         }
 
         [Fact]
-        public static void WriteIEnumerableT_DisposesEnumerators()
+        public async Task WriteIEnumerableT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var items = new RefCountedList<int>(Enumerable.Range(1, count));
-                _ = JsonSerializer.Serialize(items.AsEnumerable());
+                _ = await JsonSerializerWrapperForString.SerializeWrapper(items.AsEnumerable());
 
                 Assert.Equal(0, items.RefCount);
             }
         }
 
         [Fact]
-        public static void WriteICollectionT_DisposesEnumerators()
+        public async Task WriteICollectionT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var items = new RefCountedList<int>(Enumerable.Range(1, count));
-                _ = JsonSerializer.Serialize((ICollection<int>)items);
+                _ = await JsonSerializerWrapperForString.SerializeWrapper((ICollection<int>)items);
 
                 Assert.Equal(0, items.RefCount);
             }
         }
 
         [Fact]
-        public static void WriteIListT_DisposesEnumerators()
+        public async Task WriteIListT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var items = new RefCountedList<int>(Enumerable.Range(1, count));
-                _ = JsonSerializer.Serialize((IList<int>)items);
+                _ = await JsonSerializerWrapperForString.SerializeWrapper((IList<int>)items);
 
                 Assert.Equal(0, items.RefCount);
             }
         }
 
         [Fact]
-        public static void WriteIDictionaryT_DisposesEnumerators()
+        public async Task WriteIDictionaryT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var pairs = new RefCountedDictionary<int, int>(Enumerable.Range(1, count).Select(x => new KeyValuePair<int, int>(x, x)));
-                _ = JsonSerializer.Serialize((IDictionary<int, int>)pairs);
+                _ = await JsonSerializerWrapperForString.SerializeWrapper((IDictionary<int, int>)pairs);
 
                 Assert.Equal(0, pairs.RefCount);
             }
         }
 
         [Fact]
-        public static void WriteIReadOnlyDictionaryT_DisposesEnumerators()
+        public async Task WriteIReadOnlyDictionaryT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var pairs = new RefCountedDictionary<int, int>(Enumerable.Range(1, count).Select(x => new KeyValuePair<int, int>(x, x)));
-                _ = JsonSerializer.Serialize((IReadOnlyDictionary<int, int>)pairs);
+                _ = await JsonSerializerWrapperForString.SerializeWrapper((IReadOnlyDictionary<int, int>)pairs);
 
                 Assert.Equal(0, pairs.RefCount);
             }
         }
 
         [Fact]
-        public static void WriteISetT_DisposesEnumerators()
+        public async Task WriteISetT_DisposesEnumerators()
         {
             for (int count = 0; count < 5; count++)
             {
                 var items = new RefCountedSet<int>(Enumerable.Range(1, count));
-                _ = JsonSerializer.Serialize((ISet<int>)items);
+                _ = await JsonSerializerWrapperForString.SerializeWrapper((ISet<int>)items);
 
                 Assert.Equal(0, items.RefCount);
             }
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Immutable.Read.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Immutable.Read.cs
new file mode 100644 (file)
index 0000000..ca63692
--- /dev/null
@@ -0,0 +1,637 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests
+    {
+        [Fact]
+        public async Task ReadImmutableArrayOfImmutableArray()
+        {
+            ImmutableArray<ImmutableArray<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableArray<ImmutableArray<int>>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableArray<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadImmutableArrayOfArray()
+        {
+            ImmutableArray<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableArray<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfImmutableArray()
+        {
+            ImmutableArray<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableArray<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableArray<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadSimpleImmutableArray()
+        {
+            ImmutableArray<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableArray<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableArray<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadSimpleClassWithImmutableArray()
+        {
+            SimpleTestClassWithImmutableArray obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithImmutableArray>(SimpleTestClassWithImmutableArray.s_json);
+            obj.Verify();
+        }
+
+        [Fact]
+        public async Task ReadIImmutableListTOfIImmutableListT()
+        {
+            IImmutableList<IImmutableList<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableList<IImmutableList<int>>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (IImmutableList<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadIImmutableListTOfArray()
+        {
+            IImmutableList<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableList<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIIImmutableListT()
+        {
+            IImmutableList<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableList<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (IImmutableList<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveIImmutableListT()
+        {
+            IImmutableList<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableList<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableList<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableListWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableListWrapper>(@"[]"));
+        }
+
+        [Fact]
+        public async Task ReadIImmutableStackTOfIImmutableStackT()
+        {
+            IImmutableStack<IImmutableStack<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableStack<IImmutableStack<int>>>(@"[[1,2],[3,4]]");
+            int expected = 4;
+
+            foreach (IImmutableStack<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected--, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadIImmutableStackTOfArray()
+        {
+            IImmutableStack<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableStack<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 3;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+
+                expected = 1;
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIIImmutableStackT()
+        {
+            IImmutableStack<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableStack<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 2;
+
+            foreach (IImmutableStack<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected--, i);
+                }
+
+                expected = 4;
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveIImmutableStackT()
+        {
+            IImmutableStack<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableStack<int>>(@"[1,2]");
+            int expected = 2;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected--, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableStack<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableStackWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableStackWrapper>(@"[]"));
+        }
+
+        [Fact]
+        public async Task ReadIImmutableQueueTOfIImmutableQueueT()
+        {
+            IImmutableQueue<IImmutableQueue<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableQueue<IImmutableQueue<int>>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (IImmutableQueue<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadIImmutableQueueTOfArray()
+        {
+            IImmutableQueue<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableQueue<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableQueueT()
+        {
+            IImmutableQueue<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableQueue<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (IImmutableQueue<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveIImmutableQueueT()
+        {
+            IImmutableQueue<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableQueue<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableQueue<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableQueueWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableQueueWrapper>(@"[]"));
+        }
+
+        [Fact]
+        public async Task ReadIImmutableSetTOfIImmutableSetT()
+        {
+            IImmutableSet<IImmutableSet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableSet<IImmutableSet<int>>>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (IImmutableSet<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadIImmutableSetTOfArray()
+        {
+            IImmutableSet<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableSet<int[]>>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableSetT()
+        {
+            IImmutableSet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableSet<int>[]>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (IImmutableSet<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveIImmutableSetT()
+        {
+            IImmutableSet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableSet<int>>(@"[1,2]");
+            List<int> expected = new List<int> { 1, 2 };
+
+            foreach (int i in result)
+            {
+                expected.Remove(i);
+            }
+
+            Assert.Equal(0, expected.Count);
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IImmutableSet<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableSetWrapper>(@"[""1"",""2""]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringIImmutableSetWrapper>(@"[]"));
+        }
+
+        [Fact]
+        public async Task ReadImmutableHashSetTOfImmutableHashSetT()
+        {
+            ImmutableHashSet<ImmutableHashSet<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableHashSet<ImmutableHashSet<int>>>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (ImmutableHashSet<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadImmutableHashSetTOfArray()
+        {
+            ImmutableHashSet<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableHashSet<int[]>>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableHashSetT()
+        {
+            ImmutableHashSet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableHashSet<int>[]>(@"[[1,2],[3,4]]");
+            List<int> expected = new List<int> { 1, 2, 3, 4 };
+
+            foreach (ImmutableHashSet<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    expected.Remove(i);
+                }
+            }
+
+            Assert.Equal(0, expected.Count);
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveImmutableHashSetT()
+        {
+            ImmutableHashSet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableHashSet<int>>(@"[1,2]");
+            List<int> expected = new List<int> { 1, 2 };
+
+            foreach (int i in result)
+            {
+                expected.Remove(i);
+            }
+
+            Assert.Equal(0, expected.Count);
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableHashSet<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadImmutableListTOfImmutableListT()
+        {
+            ImmutableList<ImmutableList<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableList<ImmutableList<int>>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableList<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadImmutableListTOfArray()
+        {
+            ImmutableList<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableList<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableListT()
+        {
+            ImmutableList<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableList<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableList<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveImmutableListT()
+        {
+            ImmutableList<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableList<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableList<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadImmutableStackTOfImmutableStackT()
+        {
+            ImmutableStack<ImmutableStack<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableStack<ImmutableStack<int>>>(@"[[1,2],[3,4]]");
+            int expected = 4;
+
+            foreach (ImmutableStack<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected--, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadImmutableStackTOfArray()
+        {
+            ImmutableStack<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableStack<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 3;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+
+                expected = 1;
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableStackT()
+        {
+            ImmutableStack<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableStack<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 2;
+
+            foreach (ImmutableStack<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected--, i);
+                }
+
+                expected = 4;
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveImmutableStackT()
+        {
+            ImmutableStack<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableStack<int>>(@"[1,2]");
+            int expected = 2;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected--, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableStack<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadImmutableQueueTOfImmutableQueueT()
+        {
+            ImmutableQueue<ImmutableQueue<int>> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableQueue<ImmutableQueue<int>>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableQueue<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadImmutableQueueTOfArray()
+        {
+            ImmutableQueue<int[]> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableQueue<int[]>>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (int[] arr in result)
+            {
+                foreach (int i in arr)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadArrayOfImmutableQueueT()
+        {
+            ImmutableQueue<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableQueue<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableQueue<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveImmutableQueueT()
+        {
+            ImmutableQueue<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableQueue<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableQueue<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadArrayOfIImmutableSortedSetT()
+        {
+            ImmutableSortedSet<int>[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedSet<int>[]>(@"[[1,2],[3,4]]");
+            int expected = 1;
+
+            foreach (ImmutableSortedSet<int> l in result)
+            {
+                foreach (int i in l)
+                {
+                    Assert.Equal(expected++, i);
+                }
+            }
+        }
+
+        [Fact]
+        public async Task ReadPrimitiveImmutableSortedSetT()
+        {
+            ImmutableSortedSet<int> result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedSet<int>>(@"[1,2]");
+            int expected = 1;
+
+            foreach (int i in result)
+            {
+                Assert.Equal(expected++, i);
+            }
+
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ImmutableSortedSet<int>>(@"[]");
+            Assert.Equal(0, result.Count());
+        }
+
+        [Fact]
+        public async Task ReadSimpleTestClass_ImmutableCollectionWrappers_Throws()
+        {
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithIImmutableDictionaryWrapper>(SimpleTestClassWithIImmutableDictionaryWrapper.s_json));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithImmutableListWrapper>(SimpleTestClassWithImmutableListWrapper.s_json));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithImmutableStackWrapper>(SimpleTestClassWithImmutableStackWrapper.s_json));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithImmutableQueueWrapper>(SimpleTestClassWithImmutableQueueWrapper.s_json));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithImmutableSetWrapper>(SimpleTestClassWithImmutableSetWrapper.s_json));
+        }
+    }
+}
@@ -3,26 +3,27 @@
 
 using System.Collections.Generic;
 using System.Collections.Immutable;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void WriteImmutableArrayOfImmutableArray()
+        public async Task WriteImmutableArrayOfImmutableArray()
         {
             ImmutableArray<ImmutableArray<int>> input = ImmutableArray.CreateRange(new List<ImmutableArray<int>>{
                 ImmutableArray.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableArray.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteImmutableArrayOfArray()
+        public async Task WriteImmutableArrayOfArray()
         {
             ImmutableArray<int[]> input = ImmutableArray.CreateRange(new List<int[]>
             {
@@ -30,44 +31,44 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableArray()
+        public async Task WriteArrayOfImmutableArray()
         {
             ImmutableArray<int>[] input = new ImmutableArray<int>[2];
             input[0] = ImmutableArray.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableArray.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteSimpleImmutableArray()
+        public async Task WriteSimpleImmutableArray()
         {
             ImmutableArray<int> input = ImmutableArray.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableListTOfIImmutableListT()
+        public async Task WriteIImmutableListTOfIImmutableListT()
         {
             IImmutableList<IImmutableList<int>> input = ImmutableList.CreateRange(new List<IImmutableList<int>>{
                 ImmutableList.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableList.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableListTOfArray()
+        public async Task WriteIImmutableListTOfArray()
         {
             IImmutableList<int[]> input = ImmutableList.CreateRange(new List<int[]>
             {
@@ -75,67 +76,67 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteSimpleClassWithImmutableArray()
+        public async Task WriteSimpleClassWithImmutableArray()
         {
             SimpleTestClassWithImmutableArray obj = new SimpleTestClassWithImmutableArray();
             obj.Initialize();
 
-            Assert.Equal(SimpleTestClassWithImmutableArray.s_json, JsonSerializer.Serialize(obj));
+            Assert.Equal(SimpleTestClassWithImmutableArray.s_json, await JsonSerializerWrapperForString.SerializeWrapper(obj));
         }
 
         [Fact]
-        public static void WriteSimpleClassWithObjectImmutableArray()
+        public async Task WriteSimpleClassWithObjectImmutableArray()
         {
             SimpleTestClassWithObjectImmutableArray obj = new SimpleTestClassWithObjectImmutableArray();
             obj.Initialize();
 
-            Assert.Equal(SimpleTestClassWithObjectImmutableArray.s_json, JsonSerializer.Serialize(obj));
+            Assert.Equal(SimpleTestClassWithObjectImmutableArray.s_json, await JsonSerializerWrapperForString.SerializeWrapper(obj));
         }
 
         [Fact]
-        public static void WriteArrayOfIImmutableListT()
+        public async Task WriteArrayOfIImmutableListT()
         {
             IImmutableList<int>[] input = new IImmutableList<int>[2];
             input[0] = ImmutableList.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableList.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIImmutableListT()
+        public async Task WritePrimitiveIImmutableListT()
         {
             IImmutableList<int> input = ImmutableList.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
 
             StringIImmutableListWrapper input2 = new StringIImmutableListWrapper(new List<string> { "1", "2" });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[""1"",""2""]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableStackTOfIImmutableStackT()
+        public async Task WriteIImmutableStackTOfIImmutableStackT()
         {
             IImmutableStack<IImmutableStack<int>> input = ImmutableStack.CreateRange(new List<IImmutableStack<int>>{
                 ImmutableStack.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableStack.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[4,3],[2,1]]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableStackTOfArray()
+        public async Task WriteIImmutableStackTOfArray()
         {
             IImmutableStack<int[]> input = ImmutableStack.CreateRange(new List<int[]>
             {
@@ -143,49 +144,49 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[3,4],[1,2]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIImmutableStackT()
+        public async Task WriteArrayOfIImmutableStackT()
         {
             IImmutableStack<int>[] input = new IImmutableStack<int>[2];
             input[0] = ImmutableStack.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableStack.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[2,1],[4,3]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIImmutableStackT()
+        public async Task WritePrimitiveIImmutableStackT()
         {
             IImmutableStack<int> input = ImmutableStack.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[2,1]", json);
 
             StringIImmutableStackWrapper input2 = new StringIImmutableStackWrapper(new List<string> { "1", "2" });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[""2"",""1""]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableQueueTOfIImmutableQueueT()
+        public async Task WriteIImmutableQueueTOfIImmutableQueueT()
         {
             IImmutableQueue<IImmutableQueue<int>> input = ImmutableQueue.CreateRange(new List<IImmutableQueue<int>>{
                 ImmutableQueue.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableQueue.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableQueueTOfArray()
+        public async Task WriteIImmutableQueueTOfArray()
         {
             IImmutableQueue<int[]> input = ImmutableQueue.CreateRange(new List<int[]>
             {
@@ -193,50 +194,50 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIImmutableQueueT()
+        public async Task WriteArrayOfIImmutableQueueT()
         {
             IImmutableQueue<int>[] input = new IImmutableQueue<int>[2];
             input[0] = ImmutableQueue.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableQueue.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIImmutableQueueT()
+        public async Task WritePrimitiveIImmutableQueueT()
         {
             IImmutableQueue<int> input = ImmutableQueue.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
 
             StringIImmutableQueueWrapper input2 = new StringIImmutableQueueWrapper(new List<string> { "1", "2" });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal(@"[""1"",""2""]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableSetTOfIImmutableSetT()
+        public async Task WriteIImmutableSetTOfIImmutableSetT()
         {
             IImmutableSet<IImmutableSet<int>> input = ImmutableHashSet.CreateRange(new List<IImmutableSet<int>>{
                 ImmutableHashSet.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableHashSet.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
-        public static void WriteIImmutableSetTOfArray()
+        public async Task WriteIImmutableSetTOfArray()
         {
             IImmutableSet<int[]> input = ImmutableHashSet.CreateRange(new List<int[]>
             {
@@ -244,51 +245,51 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIImmutableSetT()
+        public async Task WriteArrayOfIImmutableSetT()
         {
             IImmutableSet<int>[] input = new IImmutableSet<int>[2];
             input[0] = ImmutableHashSet.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableHashSet.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIImmutableSetT()
+        public async Task WritePrimitiveIImmutableSetT()
         {
             IImmutableSet<int> input = ImmutableHashSet.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
 
             StringIImmutableSetWrapper input2 = new StringIImmutableSetWrapper(new List<string> { "1", "2" });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.True(json == @"[""1"",""2""]" || json == @"[""2"",""1""]");
         }
 
         [Fact]
-        public static void WriteImmutableHashSetTOfImmutableHashSetT()
+        public async Task WriteImmutableHashSetTOfImmutableHashSetT()
         {
             ImmutableHashSet<ImmutableHashSet<int>> input = ImmutableHashSet.CreateRange(new List<ImmutableHashSet<int>>{
                 ImmutableHashSet.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableHashSet.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
-        public static void WriteImmutableHashSetTOfArray()
+        public async Task WriteImmutableHashSetTOfArray()
         {
             ImmutableHashSet<int[]> input = ImmutableHashSet.CreateRange(new List<int[]>
             {
@@ -296,45 +297,45 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Contains("[1,2]", json);
             Assert.Contains("[3,4]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableHashSetT()
+        public async Task WriteArrayOfImmutableHashSetT()
         {
             ImmutableHashSet<int>[] input = new ImmutableHashSet<int>[2];
             input[0] = ImmutableHashSet.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableHashSet.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveImmutableHashSetT()
+        public async Task WritePrimitiveImmutableHashSetT()
         {
             ImmutableHashSet<int> input = ImmutableHashSet.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteImmutableListTOfImmutableListT()
+        public async Task WriteImmutableListTOfImmutableListT()
         {
             ImmutableList<ImmutableList<int>> input = ImmutableList.CreateRange(new List<ImmutableList<int>>{
                 ImmutableList.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableList.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteImmutableListTOfArray()
+        public async Task WriteImmutableListTOfArray()
         {
             ImmutableList<int[]> input = ImmutableList.CreateRange(new List<int[]>
             {
@@ -342,44 +343,44 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableListT()
+        public async Task WriteArrayOfImmutableListT()
         {
             ImmutableList<int>[] input = new ImmutableList<int>[2];
             input[0] = ImmutableList.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableList.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveImmutableListT()
+        public async Task WritePrimitiveImmutableListT()
         {
             ImmutableList<int> input = ImmutableList.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteImmutableStackTOfImmutableStackT()
+        public async Task WriteImmutableStackTOfImmutableStackT()
         {
             ImmutableStack<ImmutableStack<int>> input = ImmutableStack.CreateRange(new List<ImmutableStack<int>>{
                 ImmutableStack.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableStack.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[4,3],[2,1]]", json);
         }
 
         [Fact]
-        public static void WriteImmutableStackTOfArray()
+        public async Task WriteImmutableStackTOfArray()
         {
             ImmutableStack<int[]> input = ImmutableStack.CreateRange(new List<int[]>
             {
@@ -387,44 +388,44 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[3,4],[1,2]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableStackT()
+        public async Task WriteArrayOfImmutableStackT()
         {
             ImmutableStack<int>[] input = new ImmutableStack<int>[2];
             input[0] = ImmutableStack.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableStack.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[2,1],[4,3]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveImmutableStackT()
+        public async Task WritePrimitiveImmutableStackT()
         {
             ImmutableStack<int> input = ImmutableStack.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[2,1]", json);
         }
 
         [Fact]
-        public static void WriteImmutableQueueTOfImmutableQueueT()
+        public async Task WriteImmutableQueueTOfImmutableQueueT()
         {
             ImmutableQueue<ImmutableQueue<int>> input = ImmutableQueue.CreateRange(new List<ImmutableQueue<int>>{
                 ImmutableQueue.CreateRange(new List<int>() { 1, 2 }),
                 ImmutableQueue.CreateRange(new List<int>() { 3, 4 })
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteImmutableQueueTOfArray()
+        public async Task WriteImmutableQueueTOfArray()
         {
             ImmutableQueue<int[]> input = ImmutableQueue.CreateRange(new List<int[]>
             {
@@ -432,52 +433,52 @@ namespace System.Text.Json.Serialization.Tests
                 new int[] { 3, 4 }
             });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableQueueT()
+        public async Task WriteArrayOfImmutableQueueT()
         {
             ImmutableQueue<int>[] input = new ImmutableQueue<int>[2];
             input[0] = ImmutableQueue.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableQueue.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveImmutableQueueT()
+        public async Task WritePrimitiveImmutableQueueT()
         {
             ImmutableQueue<int> input = ImmutableQueue.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfImmutableSortedSetT()
+        public async Task WriteArrayOfImmutableSortedSetT()
         {
             ImmutableSortedSet<int>[] input = new ImmutableSortedSet<int>[2];
             input[0] = ImmutableSortedSet.CreateRange(new List<int>() { 1, 2 });
             input[1] = ImmutableSortedSet.CreateRange(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveImmutableSortedSetT()
+        public async Task WritePrimitiveImmutableSortedSetT()
         {
             ImmutableSortedSet<int> input = ImmutableSortedSet.CreateRange(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteImmutableCollectionWrappers()
+        public async Task WriteImmutableCollectionWrappers()
         {
             SimpleTestClassWithIImmutableDictionaryWrapper obj1 = new SimpleTestClassWithIImmutableDictionaryWrapper();
             SimpleTestClassWithImmutableListWrapper obj2 = new SimpleTestClassWithImmutableListWrapper();
@@ -491,20 +492,20 @@ namespace System.Text.Json.Serialization.Tests
             obj4.Initialize();
             obj5.Initialize();
 
-            Assert.Equal(SimpleTestClassWithIImmutableDictionaryWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj1));
-            Assert.Equal(SimpleTestClassWithIImmutableDictionaryWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj1));
+            Assert.Equal(SimpleTestClassWithIImmutableDictionaryWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj1));
+            Assert.Equal(SimpleTestClassWithIImmutableDictionaryWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj1));
 
-            Assert.Equal(SimpleTestClassWithImmutableListWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj2));
-            Assert.Equal(SimpleTestClassWithImmutableListWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj2));
+            Assert.Equal(SimpleTestClassWithImmutableListWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj2));
+            Assert.Equal(SimpleTestClassWithImmutableListWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj2));
 
-            Assert.Equal(SimpleTestClassWithImmutableStackWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj3));
-            Assert.Equal(SimpleTestClassWithImmutableStackWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj3));
+            Assert.Equal(SimpleTestClassWithImmutableStackWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj3));
+            Assert.Equal(SimpleTestClassWithImmutableStackWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj3));
 
-            Assert.Equal(SimpleTestClassWithImmutableQueueWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj4));
-            Assert.Equal(SimpleTestClassWithImmutableQueueWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj4));
+            Assert.Equal(SimpleTestClassWithImmutableQueueWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj4));
+            Assert.Equal(SimpleTestClassWithImmutableQueueWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj4));
 
-            Assert.Equal(SimpleTestClassWithImmutableSetWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj5));
-            Assert.Equal(SimpleTestClassWithImmutableSetWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj5));
+            Assert.Equal(SimpleTestClassWithImmutableSetWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj5));
+            Assert.Equal(SimpleTestClassWithImmutableSetWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj5));
         }
     }
 }
@@ -3,29 +3,31 @@
 
 using System.Collections.Generic;
 using System.Text.Encodings.Web;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+#if !BUILDING_SOURCE_GENERATOR_TESTS
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void ReadSimpleKeyValuePairFail()
+        public async Task ReadSimpleKeyValuePairFail()
         {
             // Invalid form: no Value
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(@"{""Key"": 123}"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(@"{""Key"": 123}"));
 
             // Invalid form: extra property
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(@"{""Key"": ""Key"", ""Value"": 123, ""Value2"": 456}"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(@"{""Key"": ""Key"", ""Value"": 123, ""Value2"": 456}"));
 
             // Invalid form: does not contain both Key and Value properties
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(@"{""Key"": ""Key"", ""Val"": 123"));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(@"{""Key"": ""Key"", ""Val"": 123"));
         }
 
         [Fact]
-        public static void ReadListOfKeyValuePair()
+        public async Task ReadListOfKeyValuePair()
         {
-            List<KeyValuePair<string, int>> input = JsonSerializer.Deserialize<List<KeyValuePair<string, int>>>(@"[{""Key"": ""123"", ""Value"": 123},{""Key"": ""456"", ""Value"": 456}]");
+            List<KeyValuePair<string, int>> input = await JsonSerializerWrapperForString.DeserializeWrapper<List<KeyValuePair<string, int>>>(@"[{""Key"": ""123"", ""Value"": 123},{""Key"": ""456"", ""Value"": 456}]");
 
             Assert.Equal(2, input.Count);
             Assert.Equal("123", input[0].Key);
@@ -35,9 +37,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadKeyValuePairOfList()
+        public async Task ReadKeyValuePairOfList()
         {
-            KeyValuePair<string, List<int>> input = JsonSerializer.Deserialize<KeyValuePair<string, List<int>>>(@"{""Key"":""Key"", ""Value"":[1, 2, 3]}");
+            KeyValuePair<string, List<int>> input = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, List<int>>>(@"{""Key"":""Key"", ""Value"":[1, 2, 3]}");
 
             Assert.Equal("Key", input.Key);
             Assert.Equal(3, input.Value.Count);
@@ -51,9 +53,9 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(@"{""Key"":""Key"", ""Value"":{""Value"":2, ""Key"":1}}")]
         [InlineData(@"{""Value"":{""Key"":1, ""Value"":2}, ""Key"":""Key""}")]
         [InlineData(@"{""Value"":{""Value"":2, ""Key"":1}, ""Key"":""Key""}")]
-        public static void ReadKeyValuePairOfKeyValuePair(string json)
+        public async Task ReadKeyValuePairOfKeyValuePair(string json)
         {
-            KeyValuePair<string, KeyValuePair<int, int>> input = JsonSerializer.Deserialize<KeyValuePair<string, KeyValuePair<int, int>>>(json);
+            KeyValuePair<string, KeyValuePair<int, int>> input = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, KeyValuePair<int, int>>>(json);
 
             Assert.Equal("Key", input.Key);
             Assert.Equal(1, input.Value.Key);
@@ -61,42 +63,42 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadKeyValuePairWithNullValues()
+        public async Task ReadKeyValuePairWithNullValues()
         {
             {
-                KeyValuePair<string, string> kvp = JsonSerializer.Deserialize<KeyValuePair<string, string>>(@"{""Key"":""key"",""Value"":null}");
+                KeyValuePair<string, string> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, string>>(@"{""Key"":""key"",""Value"":null}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Null(kvp.Value);
             }
 
             {
-                KeyValuePair<string, object> kvp = JsonSerializer.Deserialize<KeyValuePair<string, object>>(@"{""Key"":""key"",""Value"":null}");
+                KeyValuePair<string, object> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, object>>(@"{""Key"":""key"",""Value"":null}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Null(kvp.Value);
             }
 
             {
-                KeyValuePair<string, SimpleClassWithKeyValuePairs> kvp = JsonSerializer.Deserialize<KeyValuePair<string, SimpleClassWithKeyValuePairs>>(@"{""Key"":""key"",""Value"":null}");
+                KeyValuePair<string, SimpleClassWithKeyValuePairs> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, SimpleClassWithKeyValuePairs>>(@"{""Key"":""key"",""Value"":null}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Null(kvp.Value);
             }
 
             {
-                KeyValuePair<string, KeyValuePair<string, string>> kvp = JsonSerializer.Deserialize<KeyValuePair<string, KeyValuePair<string, string>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
+                KeyValuePair<string, KeyValuePair<string, string>> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, KeyValuePair<string, string>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Equal("key", kvp.Value.Key);
                 Assert.Null(kvp.Value.Value);
             }
 
             {
-                KeyValuePair<string, KeyValuePair<string, object>> kvp = JsonSerializer.Deserialize<KeyValuePair<string, KeyValuePair<string, object>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
+                KeyValuePair<string, KeyValuePair<string, object>> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, KeyValuePair<string, object>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Equal("key", kvp.Value.Key);
                 Assert.Null(kvp.Value.Value);
             }
 
             {
-                KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>> kvp = JsonSerializer.Deserialize<KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
+                KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>>>(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}");
                 Assert.Equal("key", kvp.Key);
                 Assert.Equal("key", kvp.Value.Key);
                 Assert.Null(kvp.Value.Value);
@@ -104,7 +106,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadClassWithNullKeyValuePairValues()
+        public async Task ReadClassWithNullKeyValuePairValues()
         {
             string json =
                     @"{" +
@@ -142,7 +144,7 @@ namespace System.Text.Json.Serialization.Tests
                             @"}" +
                         @"}" +
                     @"}";
-            SimpleClassWithKeyValuePairs obj = JsonSerializer.Deserialize<SimpleClassWithKeyValuePairs>(json);
+            SimpleClassWithKeyValuePairs obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleClassWithKeyValuePairs>(json);
 
             Assert.Equal("key", obj.KvpWStrVal.Key);
             Assert.Equal("key", obj.KvpWObjVal.Key);
@@ -163,24 +165,24 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void Kvp_NullKeyIsFine()
+        public async Task Kvp_NullKeyIsFine()
         {
-            KeyValuePair<string, string> kvp = JsonSerializer.Deserialize<KeyValuePair<string, string>>(@"{""Key"":null,""Value"":null}");
+            KeyValuePair<string, string> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, string>>(@"{""Key"":null,""Value"":null}");
             Assert.Null(kvp.Key);
             Assert.Null(kvp.Value);
         }
 
         [Fact]
-        public static void WritePrimitiveKeyValuePair()
+        public async Task WritePrimitiveKeyValuePair()
         {
             KeyValuePair<string, int> input = new KeyValuePair<string, int>("Key", 123);
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal(@"{""Key"":""Key"",""Value"":123}", json);
         }
 
         [Fact]
-        public static void WriteListOfKeyValuePair()
+        public async Task WriteListOfKeyValuePair()
         {
             List<KeyValuePair<string, int>> input = new List<KeyValuePair<string, int>>
             {
@@ -188,65 +190,65 @@ namespace System.Text.Json.Serialization.Tests
                 new KeyValuePair<string, int>("456", 456)
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal(@"[{""Key"":""123"",""Value"":123},{""Key"":""456"",""Value"":456}]", json);
         }
 
         [Fact]
-        public static void WriteKeyValuePairOfList()
+        public async Task WriteKeyValuePairOfList()
         {
             KeyValuePair<string, List<int>> input = new KeyValuePair<string, List<int>>("Key", new List<int> { 1, 2, 3 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal(@"{""Key"":""Key"",""Value"":[1,2,3]}", json);
         }
 
         [Fact]
-        public static void WriteKeyValuePairOfKeyValuePair()
+        public async Task WriteKeyValuePairOfKeyValuePair()
         {
             KeyValuePair<string, KeyValuePair<string, int>> input = new KeyValuePair<string, KeyValuePair<string, int>>(
                 "Key", new KeyValuePair<string, int>("Key", 1));
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal(@"{""Key"":""Key"",""Value"":{""Key"":""Key"",""Value"":1}}", json);
         }
 
         [Fact]
-        public static void WriteKeyValuePairWithNullValues()
+        public async Task WriteKeyValuePairWithNullValues()
         {
             {
                 KeyValuePair<string, string> kvp = new KeyValuePair<string, string>("key", null);
-                Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":null}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
 
             {
                 KeyValuePair<string, object> kvp = new KeyValuePair<string, object>("key", null);
-                Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":null}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
 
             {
                 KeyValuePair<string, SimpleClassWithKeyValuePairs> kvp = new KeyValuePair<string, SimpleClassWithKeyValuePairs>("key", null);
-                Assert.Equal(@"{""Key"":""key"",""Value"":null}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":null}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
 
             {
                 KeyValuePair<string, KeyValuePair<string, string>> kvp = new KeyValuePair<string, KeyValuePair<string, string>>("key", new KeyValuePair<string, string>("key", null));
-                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
 
             {
                 KeyValuePair<string, KeyValuePair<string, object>> kvp = new KeyValuePair<string, KeyValuePair<string, object>>("key", new KeyValuePair<string, object>("key", null));
-                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
 
             {
                 KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>> kvp = new KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>>("key", new KeyValuePair<string, SimpleClassWithKeyValuePairs>("key", null));
-                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", JsonSerializer.Serialize(kvp));
+                Assert.Equal(@"{""Key"":""key"",""Value"":{""Key"":""key"",""Value"":null}}", await JsonSerializerWrapperForString.SerializeWrapper(kvp));
             }
         }
 
         [Fact]
-        public static void WriteClassWithNullKeyValuePairValues_NullWrittenAsEmptyObject()
+        public async Task WriteClassWithNullKeyValuePairValues_NullWrittenAsEmptyObject()
         {
             var value = new SimpleClassWithKeyValuePairs()
             {
@@ -258,10 +260,10 @@ namespace System.Text.Json.Serialization.Tests
                 KvpWClassKvpVal = new KeyValuePair<string, KeyValuePair<string, SimpleClassWithKeyValuePairs>>("key", new KeyValuePair<string, SimpleClassWithKeyValuePairs>("key", null)),
             };
 
-            string result = JsonSerializer.Serialize(value);
+            string result = await JsonSerializerWrapperForString.SerializeWrapper(value);
 
             // Roundtrip to ensure serialize was correct.
-            value = JsonSerializer.Deserialize<SimpleClassWithKeyValuePairs>(result);
+            value = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleClassWithKeyValuePairs>(result);
             Assert.Equal("key", value.KvpWStrVal.Key);
             Assert.Equal("key", value.KvpWObjVal.Key);
             Assert.Equal("key", value.KvpWClassVal.Key);
@@ -281,7 +283,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void HonorNamingPolicy()
+        public async Task HonorNamingPolicy()
         {
             var kvp = new KeyValuePair<string, int>("Hello, World!", 1);
 
@@ -290,22 +292,22 @@ namespace System.Text.Json.Serialization.Tests
                 PropertyNamingPolicy = new LeadingUnderscorePolicy()
             };
 
-            string serialized = JsonSerializer.Serialize(kvp, options);
+            string serialized = await JsonSerializerWrapperForString.SerializeWrapper(kvp, options);
             // We know serializer writes the key first.
             Assert.Equal(@"{""_Key"":""Hello, World!"",""_Value"":1}", serialized);
 
-            kvp = JsonSerializer.Deserialize<KeyValuePair<string, int>>(serialized, options);
+            kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(serialized, options);
             Assert.Equal("Hello, World!", kvp.Key);
             Assert.Equal(1, kvp.Value);
         }
 
         [Fact]
-        public static void HonorNamingPolicy_CaseInsensitive()
+        public async Task HonorNamingPolicy_CaseInsensitive()
         {
             const string json = @"{""key"":""Hello, World!"",""value"":1}";
 
             // Baseline - with case-sensitive matching, the payload doesn't have mapping properties.
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(json));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(json));
 
             // Test - with case-insensitivity on, we have property matches.
             var options = new JsonSerializerOptions
@@ -313,13 +315,13 @@ namespace System.Text.Json.Serialization.Tests
                 PropertyNameCaseInsensitive = true
             };
 
-            KeyValuePair<string, int> kvp = JsonSerializer.Deserialize<KeyValuePair<string, int>>(json, options);
+            KeyValuePair<string, int> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(json, options);
             Assert.Equal("Hello, World!", kvp.Key);
             Assert.Equal(1, kvp.Value);
         }
 
         [Fact]
-        public static void HonorCLRProperties()
+        public async Task HonorCLRProperties()
         {
             var options = new JsonSerializerOptions
             {
@@ -330,13 +332,13 @@ namespace System.Text.Json.Serialization.Tests
             // "Key" and "Value" are special cased to accomodate content serialized with previous
             // versions of the serializer (.NET Core 3.x/System.Text.Json 4.7.x).
             string json = @"{""Key"":""Hello, World!"",""Value"":1}";
-            KeyValuePair<string, int> kvp = JsonSerializer.Deserialize<KeyValuePair<string, int>>(json, options);
+            KeyValuePair<string, int> kvp = await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(json, options);
             Assert.Equal("Hello, World!", kvp.Key);
             Assert.Equal(1, kvp.Value);
 
             // "Key" and "Value" matching is case sensitive.
             json = @"{""key"":""Hello, World!"",""value"":1}";
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(json, options));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(json, options));
 
             // "Key" and "Value" matching is case sensitive, even when case insensitivity is on.
             // Case sensitivity only applies to the result of converting the CLR property names
@@ -347,7 +349,7 @@ namespace System.Text.Json.Serialization.Tests
                 PropertyNameCaseInsensitive = true
             };
 
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<string, int>>(json, options));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, int>>(json, options));
         }
 
         private class LeadingUnderscorePolicy : JsonNamingPolicy
@@ -356,7 +358,7 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void HonorCustomEncoder()
+        public async Task HonorCustomEncoder()
         {
             var kvp = new KeyValuePair<int, int>(1, 2);
 
@@ -368,7 +370,7 @@ namespace System.Text.Json.Serialization.Tests
                 PropertyNamingPolicy = namingPolicy,
             };
 
-            Assert.Equal(@"{""Key\u003C"":1,""Value\u003C"":2}", JsonSerializer.Serialize(kvp, options));
+            Assert.Equal(@"{""Key\u003C"":1,""Value\u003C"":2}", await JsonSerializerWrapperForString.SerializeWrapper(kvp, options));
 
             // Test - serializer honors custom encoder.
             options = new JsonSerializerOptions
@@ -377,7 +379,7 @@ namespace System.Text.Json.Serialization.Tests
                 Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
             };
 
-            Assert.Equal(@"{""Key<"":1,""Value<"":2}", JsonSerializer.Serialize(kvp, options));
+            Assert.Equal(@"{""Key<"":1,""Value<"":2}", await JsonSerializerWrapperForString.SerializeWrapper(kvp, options));
         }
 
         private class TrailingAngleBracketPolicy : JsonNamingPolicy
@@ -388,18 +390,18 @@ namespace System.Text.Json.Serialization.Tests
         [Theory]
         [InlineData(typeof(KeyNameNullPolicy), "Key")]
         [InlineData(typeof(ValueNameNullPolicy), "Value")]
-        public static void InvalidPropertyNameFail(Type policyType, string offendingProperty)
+        public async Task InvalidPropertyNameFail(Type policyType, string offendingProperty)
         {
             var options = new JsonSerializerOptions
             {
                 PropertyNamingPolicy = (JsonNamingPolicy)Activator.CreateInstance(policyType)
             };
 
-            InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<KeyValuePair<string, string>>("", options));
+            InvalidOperationException ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<string, string>>("", options));
             string exAsStr = ex.ToString();
             Assert.Contains(offendingProperty, exAsStr);
 
-            Assert.Throws<InvalidOperationException>(() => JsonSerializer.Serialize(new KeyValuePair<string, string>("", ""), options));
+            await Assert.ThrowsAsync<InvalidOperationException>(async () => await JsonSerializerWrapperForString.SerializeWrapper(new KeyValuePair<string, string>("", ""), options));
         }
 
         private class KeyNameNullPolicy : JsonNamingPolicy
@@ -432,9 +434,9 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(@"{""Value"":1,""Value"":1}")]
         [InlineData(@"{""Value"":1,null:1}")]
         [InlineData(@"{""Value"":1,""Value"":2}")]
-        public static void InvalidJsonFail(string json)
+        public async Task InvalidJsonFail(string json)
         {
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<int, int>>(json));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<int, int>>(json));
         }
 
         [Theory]
@@ -445,34 +447,35 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(@"{""Extra"":3,""Key"":1,""Value"":2}", "$.Extra")]
         [InlineData(@"{""Key"":1,""Extra"":3,""Value"":2}", "$.Extra")]
         [InlineData(@"{""Key"":1,""Value"":2,""Extra"":3}", "$.Extra")]
-        public static void JsonPathIsAccurate(string json, string expectedPath)
+        public async Task JsonPathIsAccurate(string json, string expectedPath)
         {
-            JsonException ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<int, int>>(json));
+            JsonException ex = await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<int, int>>(json));
             Assert.Contains(expectedPath, ex.ToString());
 
             var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
-            ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<int, int>>(json));
+            ex = await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<int, int>>(json));
             Assert.Contains(expectedPath, ex.ToString());
         }
 
         [Theory]
         [InlineData(@"{""kEy"":""1"",""vAlUe"":2}", "$.kEy")]
         [InlineData(@"{""kEy"":1,""vAlUe"":""2""}", "$.vAlUe")]
-        public static void JsonPathIsAccurate_CaseInsensitive(string json, string expectedPath)
+        public async Task JsonPathIsAccurate_CaseInsensitive(string json, string expectedPath)
         {
             var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
-            JsonException ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<int, int>>(json, options));
+            JsonException ex = await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<int, int>>(json, options));
             Assert.Contains(expectedPath, ex.ToString());
         }
 
         [Theory]
         [InlineData(@"{""_Key"":""1"",""_Value"":2}", "$._Key")]
         [InlineData(@"{""_Key"":1,""_Value"":""2""}", "$._Value")]
-        public static void JsonPathIsAccurate_PropertyNamingPolicy(string json, string expectedPath)
+        public async Task JsonPathIsAccurate_PropertyNamingPolicy(string json, string expectedPath)
         {
             var options = new JsonSerializerOptions { PropertyNamingPolicy = new LeadingUnderscorePolicy() };
-            JsonException ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<KeyValuePair<int, int>>(json, options));
+            JsonException ex = await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyValuePair<int, int>>(json, options));
             Assert.Contains(expectedPath, ex.ToString());
         }
     }
+#endif
 }
@@ -3,16 +3,17 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void ReadGenericIEnumerableOfIEnumerable()
+        public async Task ReadGenericIEnumerableOfIEnumerable()
         {
-            IEnumerable<IEnumerable> result = JsonSerializer.Deserialize<IEnumerable<IEnumerable>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable<IEnumerable> result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable<IEnumerable>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IEnumerable ie in result)
@@ -24,13 +25,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericIEnumerableWrapper<WrapperForIEnumerable>>(@"[[1,2],[3,4]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericIEnumerableWrapper<WrapperForIEnumerable>>(@"[[1,2],[3,4]]"));
         }
 
         [Fact]
-        public static void ReadIEnumerableOfArray()
+        public async Task ReadIEnumerableOfArray()
         {
-            IEnumerable result = JsonSerializer.Deserialize<IEnumerable>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (JsonElement arr in result)
@@ -43,9 +44,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfIEnumerable()
+        public async Task ReadArrayOfIEnumerable()
         {
-            IEnumerable[] result = JsonSerializer.Deserialize<IEnumerable[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IEnumerable[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IEnumerable arr in result)
@@ -58,9 +59,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadPrimitiveIEnumerable()
+        public async Task ReadPrimitiveIEnumerable()
         {
-            IEnumerable result = JsonSerializer.Deserialize<IEnumerable>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IEnumerable result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable>(@"[1,2]");
             int expected = 1;
 
             foreach (JsonElement i in result)
@@ -68,7 +69,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<IEnumerable>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IEnumerable>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -80,9 +81,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericIListOfIList()
+        public async Task ReadGenericIListOfIList()
         {
-            IList<IList> result = JsonSerializer.Deserialize<IList<IList>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList<IList> result = await JsonSerializerWrapperForString.DeserializeWrapper<IList<IList>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IList list in result)
@@ -93,7 +94,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            GenericIListWrapper<WrapperForIList> result2 = JsonSerializer.Deserialize<GenericIListWrapper<WrapperForIList>>(@"[[1,2],[3,4]]");
+            GenericIListWrapper<WrapperForIList> result2 = await JsonSerializerWrapperForString.DeserializeWrapper<GenericIListWrapper<WrapperForIList>>(@"[[1,2],[3,4]]");
             expected = 1;
 
             foreach (WrapperForIList list in result2)
@@ -106,9 +107,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadIListOfArray()
+        public async Task ReadIListOfArray()
         {
-            IList result = JsonSerializer.Deserialize<IList>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList result = await JsonSerializerWrapperForString.DeserializeWrapper<IList>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (JsonElement arr in result)
@@ -121,9 +122,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfIList()
+        public async Task ReadArrayOfIList()
         {
-            IList[] result = JsonSerializer.Deserialize<IList[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            IList[] result = await JsonSerializerWrapperForString.DeserializeWrapper<IList[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (IList arr in result)
@@ -136,20 +137,20 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadStructIList()
+        public async Task ReadStructIList()
         {
             string json = @"[""a"",20]";
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIList>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIList>(json);
             Assert.Equal(2, wrapper.Count);
             Assert.Equal("a", ((JsonElement)wrapper[0]).GetString());
             Assert.Equal(20, ((JsonElement)wrapper[1]).GetInt32());
         }
 
         [Fact]
-        public static void ReadNullableStructIList()
+        public async Task ReadNullableStructIList()
         {
             string json = @"[""a"",20]";
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIList?>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIList?>(json);
             Assert.True(wrapper.HasValue);
             Assert.Equal(2, wrapper.Value.Count);
             Assert.Equal("a", ((JsonElement)wrapper.Value[0]).GetString());
@@ -157,54 +158,54 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadNullableStructIListWithNullJson()
+        public async Task ReadNullableStructIListWithNullJson()
         {
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIList?>("null");
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIList?>("null");
             Assert.False(wrapper.HasValue);
         }
 
         [Fact]
-        public static void ReadClassWithStructIListWrapper_NullJson_Throws()
+        public async Task ReadClassWithStructIListWrapper_NullJson_Throws()
         {
             string json = @"{ ""List"" : null }";
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithStructIListWrapper>(json));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithStructIListWrapper>(json));
         }
 
         [Fact]
-        public static void ReadStructIDictionary()
+        public async Task ReadStructIDictionary()
         {
             string json = @"{""Key"":""Value""}";
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIDictionary>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIDictionary>(json);
             Assert.Equal("Value", wrapper["Key"].ToString());
         }
 
         [Fact]
-        public static void ReadNullableStructIDictionary()
+        public async Task ReadNullableStructIDictionary()
         {
             string json = @"{""Key"":""Value""}";
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIDictionary?>(json);
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIDictionary?>(json);
             Assert.True(wrapper.HasValue);
             Assert.Equal("Value", wrapper.Value["Key"].ToString());
         }
 
         [Fact]
-        public static void ReadNullableStructIDictionaryWithNullJson()
+        public async Task ReadNullableStructIDictionaryWithNullJson()
         {
-            var wrapper = JsonSerializer.Deserialize<StructWrapperForIDictionary?>("null");
+            var wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<StructWrapperForIDictionary?>("null");
             Assert.False(wrapper.HasValue);
         }
 
         [Fact]
-        public static void ReadClassWithStructIDictionaryWrapper_NullJson_Throws()
+        public async Task ReadClassWithStructIDictionaryWrapper_NullJson_Throws()
         {
             string json = @"{ ""Dictionary"" : null }";
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<ClassWithStructIDictionaryWrapper>(json));
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithStructIDictionaryWrapper>(json));
         }
 
         [Fact]
-        public static void ReadPrimitiveIList()
+        public async Task ReadPrimitiveIList()
         {
-            IList result = JsonSerializer.Deserialize<IList>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            IList result = await JsonSerializerWrapperForString.DeserializeWrapper<IList>(@"[1,2]");
             int expected = 1;
 
             foreach (JsonElement i in result)
@@ -212,7 +213,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<IList>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<IList>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -222,7 +223,7 @@ namespace System.Text.Json.Serialization.Tests
             }
             Assert.Equal(0, count);
 
-            WrapperForIList result2 = JsonSerializer.Deserialize<WrapperForIList>(@"[1,2]");
+            WrapperForIList result2 = await JsonSerializerWrapperForString.DeserializeWrapper<WrapperForIList>(@"[1,2]");
             expected = 1;
 
             foreach (JsonElement i in result2)
@@ -232,9 +233,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericICollectionOfICollection()
+        public async Task ReadGenericICollectionOfICollection()
         {
-            ICollection<ICollection> result = JsonSerializer.Deserialize<ICollection<ICollection>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection<ICollection> result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection<ICollection>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (ICollection ie in result)
@@ -246,13 +247,13 @@ namespace System.Text.Json.Serialization.Tests
             }
 
             // No way to populate this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<GenericICollectionWrapper<WrapperForICollection>>(@"[[1,2],[3,4]]"));
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<GenericICollectionWrapper<WrapperForICollection>>(@"[[1,2],[3,4]]"));
         }
 
         [Fact]
-        public static void ReadICollectionOfArray()
+        public async Task ReadICollectionOfArray()
         {
-            ICollection result = JsonSerializer.Deserialize<ICollection>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (JsonElement arr in result)
@@ -265,9 +266,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfICollection()
+        public async Task ReadArrayOfICollection()
         {
-            ICollection[] result = JsonSerializer.Deserialize<ICollection[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ICollection[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (ICollection arr in result)
@@ -280,9 +281,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadPrimitiveICollection()
+        public async Task ReadPrimitiveICollection()
         {
-            ICollection result = JsonSerializer.Deserialize<ICollection>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            ICollection result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection>(@"[1,2]");
             int expected = 1;
 
             foreach (JsonElement i in result)
@@ -290,7 +291,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<ICollection>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ICollection>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -302,9 +303,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericStackOfStack()
+        public async Task ReadGenericStackOfStack()
         {
-            Stack<Stack> result = JsonSerializer.Deserialize<Stack<Stack>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack<Stack> result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack<Stack>>(@"[[1,2],[3,4]]");
             int expected = 4;
 
             foreach (Stack stack in result)
@@ -317,9 +318,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadStackOfArray()
+        public async Task ReadStackOfArray()
         {
-            Stack result = JsonSerializer.Deserialize<Stack>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack>(@"[[1,2],[3,4]]");
             int expected = 3;
 
             foreach (JsonElement arr in result)
@@ -333,9 +334,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfStack()
+        public async Task ReadArrayOfStack()
         {
-            Stack[] result = JsonSerializer.Deserialize<Stack[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Stack[] result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack[]>(@"[[1,2],[3,4]]");
             int expected = 2;
 
             foreach (Stack arr in result)
@@ -349,9 +350,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadPrimitiveStack()
+        public async Task ReadPrimitiveStack()
         {
-            Stack result = JsonSerializer.Deserialize<Stack>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            Stack result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack>(@"[1,2]");
             int expected = 2;
 
             foreach (JsonElement i in result)
@@ -359,7 +360,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected--, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<Stack>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<Stack>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -379,9 +380,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadGenericQueueOfQueue()
+        public async Task ReadGenericQueueOfQueue()
         {
-            Queue<Queue> result = JsonSerializer.Deserialize<Queue<Queue>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue<Queue> result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue<Queue>>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (Queue ie in result)
@@ -394,9 +395,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadQueueOfArray()
+        public async Task ReadQueueOfArray()
         {
-            Queue result = JsonSerializer.Deserialize<Queue>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (JsonElement arr in result)
@@ -409,9 +410,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfQueue()
+        public async Task ReadArrayOfQueue()
         {
-            Queue[] result = JsonSerializer.Deserialize<Queue[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            Queue[] result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (Queue arr in result)
@@ -424,9 +425,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadPrimitiveQueue()
+        public async Task ReadPrimitiveQueue()
         {
-            Queue result = JsonSerializer.Deserialize<Queue>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            Queue result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue>(@"[1,2]");
             int expected = 1;
 
             foreach (JsonElement i in result)
@@ -434,7 +435,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<Queue>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<Queue>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -444,7 +445,7 @@ namespace System.Text.Json.Serialization.Tests
             }
             Assert.Equal(0, count);
             
-            QueueWrapper wrapper = JsonSerializer.Deserialize<QueueWrapper>(@"[1,2]");
+            QueueWrapper wrapper = await JsonSerializerWrapperForString.DeserializeWrapper<QueueWrapper>(@"[1,2]");
             expected = 1;
 
             foreach (JsonElement i in wrapper)
@@ -454,9 +455,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayListOfArray()
+        public async Task ReadArrayListOfArray()
         {
-            ArrayList result = JsonSerializer.Deserialize<ArrayList>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ArrayList result = await JsonSerializerWrapperForString.DeserializeWrapper<ArrayList>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (JsonElement arr in result)
@@ -467,7 +468,7 @@ namespace System.Text.Json.Serialization.Tests
                 }
             }
 
-            ArrayListWrapper result2 = JsonSerializer.Deserialize<ArrayListWrapper>(@"[[1,2],[3,4]]");
+            ArrayListWrapper result2 = await JsonSerializerWrapperForString.DeserializeWrapper<ArrayListWrapper>(@"[[1,2],[3,4]]");
             expected = 1;
 
             foreach (JsonElement arr in result2)
@@ -480,9 +481,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadArrayOfArrayList()
+        public async Task ReadArrayOfArrayList()
         {
-            ArrayList[] result = JsonSerializer.Deserialize<ArrayList[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
+            ArrayList[] result = await JsonSerializerWrapperForString.DeserializeWrapper<ArrayList[]>(@"[[1,2],[3,4]]");
             int expected = 1;
 
             foreach (ArrayList arr in result)
@@ -495,9 +496,9 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadPrimitiveArrayList()
+        public async Task ReadPrimitiveArrayList()
         {
-            ArrayList result = JsonSerializer.Deserialize<ArrayList>(Encoding.UTF8.GetBytes(@"[1,2]"));
+            ArrayList result = await JsonSerializerWrapperForString.DeserializeWrapper<ArrayList>(@"[1,2]");
             int expected = 1;
 
             foreach (JsonElement i in result)
@@ -505,7 +506,7 @@ namespace System.Text.Json.Serialization.Tests
                 Assert.Equal(expected++, i.GetInt32());
             }
 
-            result = JsonSerializer.Deserialize<ArrayList>(Encoding.UTF8.GetBytes(@"[]"));
+            result = await JsonSerializerWrapperForString.DeserializeWrapper<ArrayList>(@"[]");
 
             int count = 0;
             IEnumerator e = result.GetEnumerator();
@@ -517,24 +518,24 @@ namespace System.Text.Json.Serialization.Tests
         }
 
         [Fact]
-        public static void ReadSimpleTestClass_NonGenericCollectionWrappers()
+        public async Task ReadSimpleTestClass_NonGenericCollectionWrappers()
         {
-            SimpleTestClassWithNonGenericCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestClassWithNonGenericCollectionWrappers>(SimpleTestClassWithNonGenericCollectionWrappers.s_json);
+            SimpleTestClassWithNonGenericCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithNonGenericCollectionWrappers>(SimpleTestClassWithNonGenericCollectionWrappers.s_json);
             obj.Verify();
         }
 
         [Fact]
-        public static void ReadSimpleTestClass_StructCollectionWrappers()
+        public async Task ReadSimpleTestClass_StructCollectionWrappers()
         {
-            SimpleTestClassWithStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestClassWithStructCollectionWrappers>(SimpleTestClassWithStructCollectionWrappers.s_json);
+            SimpleTestClassWithStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestClassWithStructCollectionWrappers>(SimpleTestClassWithStructCollectionWrappers.s_json);
             obj.Verify();
         }
 
         [Fact]
-        public static void ReadSimpleTestStruct_NullableStructCollectionWrappers()
+        public async Task ReadSimpleTestStruct_NullableStructCollectionWrappers()
         {
             {
-                SimpleTestStructWithNullableStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestStructWithNullableStructCollectionWrappers>(SimpleTestStructWithNullableStructCollectionWrappers.s_json);
+                SimpleTestStructWithNullableStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestStructWithNullableStructCollectionWrappers>(SimpleTestStructWithNullableStructCollectionWrappers.s_json);
                 obj.Verify();
             }
 
@@ -545,7 +546,7 @@ namespace System.Text.Json.Serialization.Tests
                         @"""Dictionary"" : null" +
                         @"}";
 
-                SimpleTestStructWithNullableStructCollectionWrappers obj = JsonSerializer.Deserialize<SimpleTestStructWithNullableStructCollectionWrappers>(json);
+                SimpleTestStructWithNullableStructCollectionWrappers obj = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleTestStructWithNullableStructCollectionWrappers>(json);
                 Assert.False(obj.List.HasValue);
                 Assert.False(obj.Dictionary.HasValue);
             }
@@ -553,9 +554,9 @@ namespace System.Text.Json.Serialization.Tests
 
         [Theory]
         [MemberData(nameof(ReadSimpleTestClass_NonGenericWrappers_NoAddMethod))]
-        public static void ReadSimpleTestClass_NonGenericWrappers_NoAddMethod_Throws(Type type, string json, Type exceptionMessageType)
+        public async Task ReadSimpleTestClass_NonGenericWrappers_NoAddMethod_Throws(Type type, string json, Type exceptionMessageType)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
             Assert.Contains(exceptionMessageType.ToString(), ex.Message);
         }
 
@@ -587,9 +588,9 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(typeof(WrapperForIListInternalConstructor), @"[""1""]")]
         [InlineData(typeof(WrapperForIDictionaryPrivateConstructor), @"{""Key"":""Value""}")]
         [InlineData(typeof(WrapperForIDictionaryInternalConstructor), @"{""Key"":""Value""}")]
-        public static void Read_NonGeneric_NoPublicConstructor_Throws(Type type, string json)
+        public async Task Read_NonGeneric_NoPublicConstructor_Throws(Type type, string json)
         {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
+            NotSupportedException ex = await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, type));
             Assert.Contains(type.ToString(), ex.Message);
         }
     }
@@ -3,14 +3,15 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void WriteIEnumerableOfIEnumerable()
+        public async Task WriteIEnumerableOfIEnumerable()
         {
             IEnumerable input = new List<List<int>>
             {
@@ -18,7 +19,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             WrapperForIEnumerable input2 = new WrapperForIEnumerable(new List<object>
@@ -27,12 +28,12 @@ namespace System.Text.Json.Serialization.Tests
                 new List<object>() { 3, 4 },
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteGenericIEnumerableOfIEnumerable()
+        public async Task WriteGenericIEnumerableOfIEnumerable()
         {
             IEnumerable<IEnumerable> input = new List<IEnumerable>
             {
@@ -40,46 +41,46 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIEnumerable()
+        public async Task WriteArrayOfIEnumerable()
         {
             IEnumerable[] input = new IEnumerable[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIEnumerable()
+        public async Task WritePrimitiveIEnumerable()
         {
             IEnumerable input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteStructWrapperForIList()
+        public async Task WriteStructWrapperForIList()
         {
             {
                 StructWrapperForIList obj = new StructWrapperForIList() { 1, "Hello" };
-                Assert.Equal(@"[1,""Hello""]", JsonSerializer.Serialize(obj));
+                Assert.Equal(@"[1,""Hello""]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
                 StructWrapperForIList obj = default;
-                Assert.Equal("[]", JsonSerializer.Serialize(obj));
+                Assert.Equal("[]", await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteIListOfIList()
+        public async Task WriteIListOfIList()
         {
             IList input = new List<IList>
             {
@@ -87,7 +88,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             WrapperForIList input2 = new WrapperForIList
@@ -96,12 +97,12 @@ namespace System.Text.Json.Serialization.Tests
                 new List<object>() { 3, 4 },
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteIListGenericOfIList()
+        public async Task WriteIListGenericOfIList()
         {
             IList<IList> input = new List<IList>
             {
@@ -109,32 +110,32 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfIList()
+        public async Task WriteArrayOfIList()
         {
             IList[] input = new IList[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveIList()
+        public async Task WritePrimitiveIList()
         {
             IList input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteICollectionOfICollection()
+        public async Task WriteICollectionOfICollection()
         {
             ICollection input = new List<ICollection>
             {
@@ -142,12 +143,12 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteGenericICollectionOfICollection()
+        public async Task WriteGenericICollectionOfICollection()
         {
             ICollection<ICollection> input = new List<ICollection>
             {
@@ -155,7 +156,7 @@ namespace System.Text.Json.Serialization.Tests
                 new List<int>() { 3, 4 }
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericICollectionWrapper<WrapperForICollection> input2 = new GenericICollectionWrapper<WrapperForICollection>
@@ -164,130 +165,130 @@ namespace System.Text.Json.Serialization.Tests
                 new WrapperForICollection(new List<object> { 3, 4 }),
             };
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfICollection()
+        public async Task WriteArrayOfICollection()
         {
             ICollection[] input = new List<int>[2];
             input[0] = new List<int>() { 1, 2 };
             input[1] = new List<int>() { 3, 4 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveICollection()
+        public async Task WritePrimitiveICollection()
         {
             ICollection input = new List<int> { 1, 2 };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteStackOfStack()
+        public async Task WriteStackOfStack()
         {
             Stack input = new Stack();
             input.Push(new Stack(new List<int>() { 1, 2 }));
             input.Push(new Stack(new List<int>() { 3, 4 }));
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[4,3],[2,1]]", json);
         }
 
         [Fact]
-        public static void WriteGenericStackOfStack()
+        public async Task WriteGenericStackOfStack()
         {
             Stack<Stack> input = new Stack<Stack>();
             input.Push(new Stack(new List<int>() { 1, 2 }));
             input.Push(new Stack(new List<int>() { 3, 4 }));
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[4,3],[2,1]]", json);
 
             GenericStackWrapper<StackWrapper> input2 = new GenericStackWrapper<StackWrapper>();
             input2.Push(new StackWrapper(new List<object> { 1, 2 }));
             input2.Push(new StackWrapper(new List<object> { 3, 4 }));
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[4,3],[2,1]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfStack()
+        public async Task WriteArrayOfStack()
         {
             Stack[] input = new Stack[2];
             input[0] = new Stack(new List<int>() { 1, 2 });
             input[1] = new Stack(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[2,1],[4,3]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveStack()
+        public async Task WritePrimitiveStack()
         {
             Stack input = new Stack( new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[2,1]", json);
         }
 
         [Fact]
-        public static void WriteQueueOfQueue()
+        public async Task WriteQueueOfQueue()
         {
             Queue input = new Queue();
             input.Enqueue(new Queue(new List<int>() { 1, 2 }));
             input.Enqueue(new Queue(new List<int>() { 3, 4 }));
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteGenericQueueOfQueue()
+        public async Task WriteGenericQueueOfQueue()
         {
             Queue<Queue> input = new Queue<Queue>();
             input.Enqueue(new Queue(new List<int>() { 1, 2 }));
             input.Enqueue(new Queue(new List<int>() { 3, 4 }));
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             GenericQueueWrapper<QueueWrapper> input2 = new GenericQueueWrapper<QueueWrapper>();
             input2.Enqueue(new QueueWrapper(new List<object>() { 1, 2 }));
             input2.Enqueue(new QueueWrapper(new List<object>() { 3, 4 }));
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfQueue()
+        public async Task WriteArrayOfQueue()
         {
             Queue[] input = new Queue[2];
             input[0] = new Queue(new List<int>() { 1, 2 });
             input[1] = new Queue(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveQueue()
+        public async Task WritePrimitiveQueue()
         {
             Queue input = new Queue(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteArrayListOfArrayList()
+        public async Task WriteArrayListOfArrayList()
         {
             ArrayList input = new ArrayList
             {
@@ -295,7 +296,7 @@ namespace System.Text.Json.Serialization.Tests
                 new ArrayList(new List<int>() { 3, 4 })
             };
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
 
             ArrayListWrapper input2 = new ArrayListWrapper(new List<object>
@@ -304,37 +305,37 @@ namespace System.Text.Json.Serialization.Tests
                 new ArrayListWrapper(new List<object>() { 3, 4 })
             });
 
-            json = JsonSerializer.Serialize(input2);
+            json = await JsonSerializerWrapperForString.SerializeWrapper(input2);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WriteArrayOfArrayList()
+        public async Task WriteArrayOfArrayList()
         {
             ArrayList[] input = new ArrayList[2];
             input[0] = new ArrayList(new List<int>() { 1, 2 });
             input[1] = new ArrayList(new List<int>() { 3, 4 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[[1,2],[3,4]]", json);
         }
 
         [Fact]
-        public static void WritePrimitiveArrayList()
+        public async Task WritePrimitiveArrayList()
         {
             ArrayList input = new ArrayList(new List<int> { 1, 2 });
 
-            string json = JsonSerializer.Serialize(input);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(input);
             Assert.Equal("[1,2]", json);
         }
 
         [Fact]
-        public static void WriteSimpleTestStructWithNullableStructCollectionWrappers()
+        public async Task WriteSimpleTestStructWithNullableStructCollectionWrappers()
         {
             {
                 SimpleTestStructWithNullableStructCollectionWrappers obj = new SimpleTestStructWithNullableStructCollectionWrappers();
                 obj.Initialize();
-                Assert.Equal(SimpleTestStructWithNullableStructCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(SimpleTestStructWithNullableStructCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
@@ -344,17 +345,17 @@ namespace System.Text.Json.Serialization.Tests
                     @"""List"" : null," +
                     @"""Dictionary"" : null" +
                     @"}";
-                Assert.Equal(json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteSimpleTestClassWithStructCollectionWrappers()
+        public async Task WriteSimpleTestClassWithStructCollectionWrappers()
         {
             {
                 SimpleTestClassWithStructCollectionWrappers obj = new SimpleTestClassWithStructCollectionWrappers();
                 obj.Initialize();
-                Assert.Equal(SimpleTestClassWithStructCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(SimpleTestClassWithStructCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
 
             {
@@ -368,12 +369,12 @@ namespace System.Text.Json.Serialization.Tests
                     @"""List"" : []," +
                     @"""Dictionary"" : {}" +
                     @"}";
-                Assert.Equal(json.StripWhitespace(), JsonSerializer.Serialize(obj));
+                Assert.Equal(json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj));
             }
         }
 
         [Fact]
-        public static void WriteNonGenericCollectionWrappers()
+        public async Task WriteNonGenericCollectionWrappers()
         {
             SimpleTestClassWithNonGenericCollectionWrappers obj1 = new SimpleTestClassWithNonGenericCollectionWrappers();
             SimpleTestClassWithIEnumerableWrapper obj2 = new SimpleTestClassWithIEnumerableWrapper();
@@ -387,20 +388,20 @@ namespace System.Text.Json.Serialization.Tests
             obj4.Initialize();
             obj5.Initialize();
 
-            Assert.Equal(SimpleTestClassWithNonGenericCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize(obj1));
-            Assert.Equal(SimpleTestClassWithNonGenericCollectionWrappers.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj1));
+            Assert.Equal(SimpleTestClassWithNonGenericCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj1));
+            Assert.Equal(SimpleTestClassWithNonGenericCollectionWrappers.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj1));
 
-            Assert.Equal(SimpleTestClassWithIEnumerableWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj2));
-            Assert.Equal(SimpleTestClassWithIEnumerableWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj2));
+            Assert.Equal(SimpleTestClassWithIEnumerableWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj2));
+            Assert.Equal(SimpleTestClassWithIEnumerableWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj2));
 
-            Assert.Equal(SimpleTestClassWithICollectionWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj3));
-            Assert.Equal(SimpleTestClassWithICollectionWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj3));
+            Assert.Equal(SimpleTestClassWithICollectionWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj3));
+            Assert.Equal(SimpleTestClassWithICollectionWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj3));
 
-            Assert.Equal(SimpleTestClassWithStackWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj4));
-            Assert.Equal(SimpleTestClassWithStackWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj4));
+            Assert.Equal(SimpleTestClassWithStackWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj4));
+            Assert.Equal(SimpleTestClassWithStackWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj4));
 
-            Assert.Equal(SimpleTestClassWithQueueWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize(obj5));
-            Assert.Equal(SimpleTestClassWithQueueWrapper.s_json.StripWhitespace(), JsonSerializer.Serialize<object>(obj5));
+            Assert.Equal(SimpleTestClassWithQueueWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper(obj5));
+            Assert.Equal(SimpleTestClassWithQueueWrapper.s_json.StripWhitespace(), await JsonSerializerWrapperForString.SerializeWrapper<object>(obj5));
         }
     }
 }
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.ObjectModel.Read.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.ObjectModel.Read.cs
new file mode 100644 (file)
index 0000000..2fc8575
--- /dev/null
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests
+    {
+        [Fact]
+        public async Task Read_ObjectModelCollection()
+        {
+            Collection<bool> c = await JsonSerializerWrapperForString.DeserializeWrapper<Collection<bool>>("[true,false]");
+            Assert.Equal(2, c.Count);
+            Assert.True(c[0]);
+            Assert.False(c[1]);
+
+            // Regression test for https://github.com/dotnet/runtime/issues/30686.
+            ObservableCollection<bool> oc = await JsonSerializerWrapperForString.DeserializeWrapper<ObservableCollection<bool>>("[true,false]");
+            Assert.Equal(2, oc.Count);
+            Assert.True(oc[0]);
+            Assert.False(oc[1]);
+
+            SimpleKeyedCollection kc = await JsonSerializerWrapperForString.DeserializeWrapper<SimpleKeyedCollection>("[true]");
+            Assert.Equal(1, kc.Count);
+            Assert.True(kc[0]);
+        }
+
+        [Fact]
+        public async Task Read_ObjectModelCollection_Throws()
+        {
+            // No default constructor.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ReadOnlyCollection<bool>>("[true,false]"));
+            // No default constructor.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ReadOnlyObservableCollection<bool>>("[true,false]"));
+            // No default constructor.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<ReadOnlyDictionary<string, bool>>(@"{""true"":false}"));
+
+            // Abstract types can't be instantiated. This means there's no default constructor, so the type is not supported for deserialization.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<KeyedCollection<string, bool>>("[true]"));
+        }
+
+        public class SimpleKeyedCollection : KeyedCollection<string, bool>
+        {
+            protected override string GetKeyForItem(bool item)
+            {
+                return item.ToString();
+            }
+        }
+    }
+}
@@ -3,33 +3,34 @@
 
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
-    public static partial class CollectionTests
+    public abstract partial class CollectionTests
     {
         [Fact]
-        public static void Write_ObjectModelCollection()
+        public async Task Write_ObjectModelCollection()
         {
             Collection<bool> c = new Collection<bool>() { true, false };
-            Assert.Equal("[true,false]", JsonSerializer.Serialize(c));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper(c));
 
             ObservableCollection<bool> oc = new ObservableCollection<bool>() { true, false };
-            Assert.Equal("[true,false]", JsonSerializer.Serialize(oc));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper(oc));
 
             SimpleKeyedCollection kc = new SimpleKeyedCollection() { true, false };
-            Assert.Equal("[true,false]", JsonSerializer.Serialize(kc));
-            Assert.Equal("[true,false]", JsonSerializer.Serialize<KeyedCollection<string, bool>>(kc));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper(kc));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper<KeyedCollection<string, bool>>(kc));
 
             ReadOnlyCollection<bool> roc = new ReadOnlyCollection<bool>(new List<bool> { true, false });
-            Assert.Equal("[true,false]", JsonSerializer.Serialize(roc));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper(roc));
 
             ReadOnlyObservableCollection<bool> rooc = new ReadOnlyObservableCollection<bool>(oc);
-            Assert.Equal("[true,false]", JsonSerializer.Serialize(rooc));
+            Assert.Equal("[true,false]", await JsonSerializerWrapperForString.SerializeWrapper(rooc));
 
             ReadOnlyDictionary<string, bool> rod = new ReadOnlyDictionary<string, bool>(new Dictionary<string, bool> { ["true"] = false });
-            Assert.Equal(@"{""true"":false}", JsonSerializer.Serialize(rod));
+            Assert.Equal(@"{""true"":false}", await JsonSerializerWrapperForString.SerializeWrapper(rod));
         }
     }
 }
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Read.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Read.cs
new file mode 100644 (file)
index 0000000..22bb9b2
--- /dev/null
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Specialized;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests
+    {
+        [Fact]
+        public async Task Read_SpecializedCollection()
+        {
+            BitVector32 bv32 = await JsonSerializerWrapperForString.DeserializeWrapper<BitVector32>(@"{""Data"":4}");
+            // Data property is skipped because it doesn't have a setter.
+            Assert.Equal(0, bv32.Data);
+
+            HybridDictionary hd = await JsonSerializerWrapperForString.DeserializeWrapper<HybridDictionary>(@"{""key"":""value""}");
+            Assert.Equal(1, hd.Count);
+            Assert.Equal("value", ((JsonElement)hd["key"]).GetString());
+
+            IOrderedDictionary iod = await JsonSerializerWrapperForString.DeserializeWrapper<OrderedDictionary>(@"{""key"":""value""}");
+            Assert.Equal(1, iod.Count);
+            Assert.Equal("value", ((JsonElement)iod["key"]).GetString());
+
+            ListDictionary ld = await JsonSerializerWrapperForString.DeserializeWrapper<ListDictionary>(@"{""key"":""value""}");
+            Assert.Equal(1, ld.Count);
+            Assert.Equal("value", ((JsonElement)ld["key"]).GetString());
+        }
+
+        [Fact]
+        public async Task Read_SpecializedCollection_Throws()
+        {
+            // Add method for this collection only accepts strings, even though it only implements IList which usually
+            // indicates that the element type is typeof(object).
+            await Assert.ThrowsAsync<InvalidCastException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringCollection>(@"[""1"", ""2""]"));
+
+            // Not supported. Not IList, and we don't detect the add method for this collection.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<StringDictionary>(@"[{""Key"": ""key"",""Value"":""value""}]"));
+
+            // Int key is not allowed.
+            await Assert.ThrowsAsync<JsonException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<HybridDictionary>(@"{1:""value""}"));
+
+            // Runtime type in this case is IOrderedDictionary (we don't replace with concrete type), which we can't instantiate.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<IOrderedDictionary>(@"{""first"":""John"",""second"":""Jane"",""third"":""Jet""}"));
+
+            // Not supported. Not IList, and we don't detect the add method for this collection.
+            await Assert.ThrowsAsync<NotSupportedException>(async () => await JsonSerializerWrapperForString.DeserializeWrapper<NameValueCollection>(@"[""NameValueCollection""]"));
+        }
+    }
+}
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Write.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Specialized.Write.cs
new file mode 100644 (file)
index 0000000..084777e
--- /dev/null
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Specialized;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests
+    {
+        [Fact]
+        public async Task Write_SpecializedCollection()
+        {
+            Assert.Equal(@"{""Data"":4}", await JsonSerializerWrapperForString.SerializeWrapper(new BitVector32(4)));
+            Assert.Equal(@"{""Data"":4}", await JsonSerializerWrapperForString.SerializeWrapper<object>(new BitVector32(4)));
+
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper(new HybridDictionary { ["key"] = "value" }));
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper<object>(new HybridDictionary { ["key"] = "value" }));
+
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper(new OrderedDictionary { ["key"] = "value" }));
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper<IOrderedDictionary>(new OrderedDictionary { ["key"] = "value" }));
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper<object>(new OrderedDictionary { ["key"] = "value" }));
+
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper(new ListDictionary { ["key"] = "value" }));
+            Assert.Equal(@"{""key"":""value""}", await JsonSerializerWrapperForString.SerializeWrapper<object>(new ListDictionary { ["key"] = "value" }));
+
+            Assert.Equal(@"[""1"",""2""]", await JsonSerializerWrapperForString.SerializeWrapper(new StringCollection { "1", "2" }));
+            Assert.Equal(@"[""1"",""2""]", await JsonSerializerWrapperForString.SerializeWrapper<object>(new StringCollection { "1", "2" }));
+
+            Assert.Equal(@"[{""Key"":""key"",""Value"":""value""}]", await JsonSerializerWrapperForString.SerializeWrapper(new StringDictionary { ["key"] = "value" }));
+            Assert.Equal(@"[{""Key"":""key"",""Value"":""value""}]", await JsonSerializerWrapperForString.SerializeWrapper<object>(new StringDictionary { ["key"] = "value" }));
+
+            // Element type returned by .GetEnumerator for this type is string, specifically the key.
+            Assert.Equal(@"[""key""]", await JsonSerializerWrapperForString.SerializeWrapper(new NameValueCollection { ["key"] = "value" }));
+        }
+    }
+}
diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.cs
new file mode 100644 (file)
index 0000000..82ac3b7
--- /dev/null
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public abstract partial class CollectionTests : SerializerTests
+    {
+        public CollectionTests(JsonSerializerWrapperForString stringSerializerWrapper, JsonSerializerWrapperForStream streamSerializerWrapper)
+            : base(stringSerializerWrapper, streamSerializerWrapper) { }
+    }
+}
diff --git a/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapperForStream.cs b/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapperForStream.cs
new file mode 100644 (file)
index 0000000..d3e9994
--- /dev/null
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.IO;
+using System.Text.Json.Serialization.Metadata;
+using System.Threading.Tasks;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    /// <summary>
+    /// Base class for wrapping Stream-based JsonSerializer methods which allows tests to run under different configurations.
+    /// </summary>
+    public abstract partial class JsonSerializerWrapperForStream
+    {
+        protected internal abstract Task SerializeWrapper<T>(Stream stream, T value, JsonSerializerOptions options = null);
+        protected internal abstract Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerOptions options = null);
+        protected internal abstract Task SerializeWrapper<T>(Stream stream, T value, JsonTypeInfo<T> jsonTypeInfo);
+        protected internal abstract Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonSerializerOptions options = null);
+        protected internal abstract Task<object> DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions options = null);
+        protected internal abstract Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonTypeInfo<T> jsonTypeInfo);
+    }
+}
index 8d53fc3..528ac29 100644 (file)
@@ -3,6 +3,8 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
 using Xunit;
 
 namespace System.Text.Json
@@ -67,5 +69,20 @@ namespace System.Text.Json
                     break;
             }
         }
+
+        public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source)
+        {
+            var list = new List<T>();
+            await foreach (T item in source)
+            {
+                list.Add(item);
+            }
+            return list;
+        }
+
+        private static readonly Regex s_stripWhitespace = new Regex(@"\s+", RegexOptions.Compiled);
+
+        public static string StripWhitespace(this string value)
+            => s_stripWhitespace.Replace(value, string.Empty);
     }
 }
index c7198b1..e1536ad 100644 (file)
@@ -7,6 +7,9 @@ namespace System.Text.Json.Serialization.Tests
     {
         protected JsonSerializerWrapperForString JsonSerializerWrapperForString { get; }
 
-        protected SerializerTests(JsonSerializerWrapperForString serializerWrapper) => JsonSerializerWrapperForString = serializerWrapper;
+        protected JsonSerializerWrapperForStream JsonSerializerWrapperForStream { get; }
+
+        protected SerializerTests(JsonSerializerWrapperForString stringSerializerWrapper, JsonSerializerWrapperForStream? streamSerializerWrapper = null)
+            => (JsonSerializerWrapperForString, JsonSerializerWrapperForStream) = (stringSerializerWrapper, streamSerializerWrapper);
     }
 }
index a725199..9f423cf 100644 (file)
@@ -1967,4 +1967,20 @@ namespace System.Text.Json.Serialization.Tests
     {
         public int Id { get; set; }
     }
+
+    public class UppercaseNamingPolicy : JsonNamingPolicy
+    {
+        public override string ConvertName(string name)
+        {
+            return name.ToUpperInvariant();
+        }
+    }
+
+    public class NullNamingPolicy : JsonNamingPolicy
+    {
+        public override string ConvertName(string name)
+        {
+            return null;
+        }
+    }
 }
index 77882f6..79d4378 100644 (file)
@@ -1,7 +1,9 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Reflection;
 using System.Text.Json.Serialization;
+using Microsoft.DotNet.RemoteExecutor;
 using Xunit;
 
 namespace System.Text.Json.SourceGeneration.Tests
@@ -17,6 +19,46 @@ namespace System.Text.Json.SourceGeneration.Tests
             Assert.NotNull(NestedPublicContext.NestedProtectedInternalClass.Default);
         }
 
+        [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+        public static void Converters_AndTypeInfoCreator_NotRooted_WhenMetadataNotPresent()
+        {
+            RemoteExecutor.Invoke(
+                new Action(() =>
+                {
+                    object[] objArr = new object[] { new MyStruct() };
+
+                    // Metadata not generated for MyStruct without JsonSerializableAttribute.
+                    NotSupportedException ex = Assert.Throws<NotSupportedException>(
+                        () => JsonSerializer.Serialize(objArr, MetadataContext.Default.ObjectArray));
+                    string exAsStr = ex.ToString();
+                    Assert.Contains(typeof(MyStruct).ToString(), exAsStr);
+                    Assert.Contains("JsonSerializerOptions", exAsStr);
+
+                    // This test uses reflection to:
+                    // - Access JsonSerializerOptions.s_defaultSimpleConverters
+                    // - Access JsonSerializerOptions.s_defaultFactoryConverters
+                    // - Access JsonSerializerOptions._typeInfoCreationFunc
+                    //
+                    // If any of them changes, this test will need to be kept in sync.
+
+                    // Confirm built-in converters not set.
+                    AssertFieldNull("s_defaultSimpleConverters", optionsInstance: null);
+                    AssertFieldNull("s_defaultFactoryConverters", optionsInstance: null);
+
+                    // Confirm type info dynamic creator not set.
+                    AssertFieldNull("_typeInfoCreationFunc", MetadataContext.Default.Options);
+
+                    static void AssertFieldNull(string fieldName, JsonSerializerOptions? optionsInstance)
+                    {
+                        BindingFlags bindingFlags = BindingFlags.NonPublic | (optionsInstance == null ? BindingFlags.Static : BindingFlags.Instance);
+                        FieldInfo fieldInfo = typeof(JsonSerializerOptions).GetField(fieldName, bindingFlags);
+                        Assert.NotNull(fieldInfo);
+                        Assert.Null(fieldInfo.GetValue(optionsInstance));
+                    }
+                }),
+                new RemoteInvokeOptions() { ExpectedExitCode = 0 }).Dispose();
+        }
+
         [JsonSerializable(typeof(JsonMessage))]
         internal partial class NestedContext : JsonSerializerContext { }
 
index 0017021..db55741 100644 (file)
@@ -4,7 +4,6 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Reflection;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization.Metadata;
 using Xunit;
@@ -473,41 +472,6 @@ namespace System.Text.Json.SourceGeneration.Tests
             public DayOfWeek? NullableDay { get; set; }
         }
 
-        [Fact]
-        public void Converters_AndTypeInfoCreator_NotRooted_WhenMetadataNotPresent()
-        {
-            object[] objArr = new object[] { new MyStruct() };
-
-            // Metadata not generated for MyStruct without JsonSerializableAttribute.
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(
-                () => JsonSerializer.Serialize(objArr, DefaultContext.ObjectArray));
-            string exAsStr = ex.ToString();
-            Assert.Contains(typeof(MyStruct).ToString(), exAsStr);
-            Assert.Contains("JsonSerializerOptions", exAsStr);
-
-            // This test uses reflection to:
-            // - Access JsonSerializerOptions.s_defaultSimpleConverters
-            // - Access JsonSerializerOptions.s_defaultFactoryConverters
-            // - Access JsonSerializerOptions._typeInfoCreationFunc
-            //
-            // If any of them changes, this test will need to be kept in sync.
-
-            // Confirm built-in converters not set.
-            AssertFieldNull("s_defaultSimpleConverters", optionsInstance: null);
-            AssertFieldNull("s_defaultFactoryConverters", optionsInstance: null);
-
-            // Confirm type info dynamic creator not set.
-            AssertFieldNull("_typeInfoCreationFunc", ((JsonSerializerContext)DefaultContext).Options);
-
-            static void AssertFieldNull(string fieldName, JsonSerializerOptions? optionsInstance)
-            {
-                BindingFlags bindingFlags = BindingFlags.NonPublic | (optionsInstance == null ? BindingFlags.Static : BindingFlags.Instance);
-                FieldInfo fieldInfo = typeof(JsonSerializerOptions).GetField(fieldName, bindingFlags);
-                Assert.NotNull(fieldInfo);
-                Assert.Null(fieldInfo.GetValue(optionsInstance));
-            }
-        }
-
         private const string ExceptionMessageFromCustomContext = "Exception thrown from custom context.";
 
         [Fact]
@@ -529,8 +493,6 @@ namespace System.Text.Json.SourceGeneration.Tests
             Assert.Contains(ExceptionMessageFromCustomContext, ex.ToString());
         }
 
-        internal struct MyStruct { }
-
         internal class CustomContext : JsonSerializerContext
         {
             public CustomContext(JsonSerializerOptions options) : base(options, null) { }
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs
new file mode 100644 (file)
index 0000000..8d581ae
--- /dev/null
@@ -0,0 +1,740 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Text.Json.Serialization;
+using System.Text.Json.Serialization.Tests;
+
+namespace System.Text.Json.SourceGeneration.Tests
+{
+    public partial class CollectionTests_Metadata : CollectionTests
+    {
+        public CollectionTests_Metadata()
+            : this(new StringSerializerWrapper(CollectionTestsContext_Metadata.Default, (options) => new CollectionTestsContext_Metadata(options)))
+        {
+        }
+
+        protected CollectionTests_Metadata(JsonSerializerWrapperForString serializerWrapper)
+            : base(serializerWrapper, new StreamSerializerWrapper())
+        {
+        }
+
+        [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+        [JsonSerializable(typeof(ConcurrentDictionary<string, string>))]
+        [JsonSerializable(typeof(ConcurrentQueue<string>))]
+        [JsonSerializable(typeof(ConcurrentStack<string>))]
+        [JsonSerializable(typeof(BlockingCollection<string>))]
+        [JsonSerializable(typeof(ConcurrentBag<string>))]
+        [JsonSerializable(typeof(GenericConcurrentQueuePrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentQueueInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentStackPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentStackInternalConstructor<string>))]
+        [JsonSerializable(typeof(IDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, string>))]
+        [JsonSerializable(typeof(SortedDictionary<string, string>))]
+        [JsonSerializable(typeof(object))]
+        [JsonSerializable(typeof(IDictionary<string, string>))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<string, string>))]
+        [JsonSerializable(typeof(ImmutableDictionary<string, string>))]
+        [JsonSerializable(typeof(IImmutableDictionary<string, string>))]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, string>))]
+        [JsonSerializable(typeof(Hashtable))]
+        [JsonSerializable(typeof(SortedList))]
+        [JsonSerializable(typeof(WrapperForIDictionary))]
+        [JsonSerializable(typeof(StringToStringDictionaryWrapper))]
+        [JsonSerializable(typeof(StringToStringSortedDictionaryWrapper))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(StringToStringIImmutableDictionaryWrapper))]
+        [JsonSerializable(typeof(HashtableWrapper))]
+        [JsonSerializable(typeof(SortedListWrapper))]
+        [JsonSerializable(typeof(GenericStructIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(GenericStructIDictionaryWrapper<string, string>?))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, object>))]
+        [JsonSerializable(typeof(IDictionary<string, object>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, object>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(PocoDictionary))]
+        [JsonSerializable(typeof(IDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(ImmutableDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(IImmutableDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(Dictionary<string, int[]>))]
+        [JsonSerializable(typeof(List<Dictionary<string, int>>))]
+        [JsonSerializable(typeof(List<ImmutableSortedDictionary<string, int>>))]
+        [JsonSerializable(typeof(Dictionary<string, int>[]), TypeInfoPropertyName = "ArrayOfDictionaryStringInt")]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, int>[]))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, int>>))]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, Dictionary<string, int>>>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, int>[]>))]
+        [JsonSerializable(typeof(SimpleTestClass))]
+        [JsonSerializable(typeof(Dictionary<string, int>))]
+        [JsonSerializable(typeof(Dictionary<string, JsonElement>))]
+        [JsonSerializable(typeof(PocoDuplicate))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary1))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary2))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary3))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary4))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary5))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary6))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary7))]
+        [JsonSerializable(typeof(ClassWithIgnoredIDictionary))]
+        [JsonSerializable(typeof(ClassWithIgnoreAttributeDictionary))]
+        [JsonSerializable(typeof(ClassWithIgnoredImmutableDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, AllSingleUpperProperties_Child>))]
+        [JsonSerializable(typeof(AllSingleUpperPropertiesParent))]
+        [JsonSerializable(typeof(ClassWithDictionaryOfString_ChildWithDictionaryOfString))]
+        [JsonSerializable(typeof(ClassWithDictionaryOfString_ChildWithDictionaryOfString))]
+        [JsonSerializable(typeof(ClassWithDictionaryAndProperty_DictionaryFirst))]
+        [JsonSerializable(typeof(ClassWithDictionaryAndProperty_DictionaryLast))]
+        [JsonSerializable(typeof(SimpleClassWithDictionaries))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringTValue<int>))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringTValue<Poco>))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringPoco))]
+        [JsonSerializable(typeof(DictionaryThatHasIncompatibleEnumerator))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithoutParameterlessCtor>))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary?))]
+        [JsonSerializable(typeof(ClassWithStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(Poco))]
+        [JsonSerializable(typeof(JsonElement))]
+        [JsonSerializable(typeof(string))]
+        [JsonSerializable(typeof(IDictionary<int, int>))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithInternalParameterlessConstructor>))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithPrivateParameterlessConstructor>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, CustomClass>>))]
+        [JsonSerializable(typeof(TestClassWithDictionary))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<Uri, int>))]
+        [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper<Uri, int>))]
+        [JsonSerializable(typeof(List<int>))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<int, int>))]
+        [JsonSerializable(typeof(Dictionary<string, CustomClass>))]
+        [JsonSerializable(typeof(IDerivedIDictionaryOfTKeyTValue<string, string>))]
+        [JsonSerializable(typeof(List<List<int>>))]
+        [JsonSerializable(typeof(GenericListWrapper<StringListWrapper>))]
+        [JsonSerializable(typeof(List<List<int>>))]
+        [JsonSerializable(typeof(GenericListWrapper<StringListWrapper>))]
+        [JsonSerializable(typeof(List<int[]>))]
+        [JsonSerializable(typeof(GenericListWrapper<string[]>))]
+        [JsonSerializable(typeof(List<int>[]), TypeInfoPropertyName = "ArrayOfIntList")]
+        [JsonSerializable(typeof(StringListWrapper[]))]
+        [JsonSerializable(typeof(List<int>))]
+        [JsonSerializable(typeof(StringListWrapper))]
+        [JsonSerializable(typeof(IEnumerable<IEnumerable<int>>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<StringIEnumerableWrapper>))]
+        [JsonSerializable(typeof(IEnumerable<int[]>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<int[]>))]
+        [JsonSerializable(typeof(IEnumerable<int>[]), TypeInfoPropertyName = "ArrayOfIntIEnumerable")]
+        [JsonSerializable(typeof(StringIEnumerableWrapper[]))]
+        [JsonSerializable(typeof(IEnumerable<int>))]
+        [JsonSerializable(typeof(StringIEnumerableWrapper))]
+        [JsonSerializable(typeof(IList<IList<int>>))]
+        [JsonSerializable(typeof(GenericIListWrapper<StringIListWrapper>))]
+        [JsonSerializable(typeof(IList<int[]>))]
+        [JsonSerializable(typeof(GenericIListWrapper<string[]>))]
+        [JsonSerializable(typeof(IList<int>[]), TypeInfoPropertyName = "ArrayOfIntIList")]
+        [JsonSerializable(typeof(StringIListWrapper[]))]
+        [JsonSerializable(typeof(IList<int>))]
+        [JsonSerializable(typeof(StringIListWrapper))]
+        [JsonSerializable(typeof(GenericStructIListWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructIListWrapper<int>?))]
+        [JsonSerializable(typeof(GenericStructICollectionWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructICollectionWrapper<int>?))]
+        [JsonSerializable(typeof(ICollection<ICollection<int>>))]
+        [JsonSerializable(typeof(ICollection<int[]>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<string[]>))]
+        [JsonSerializable(typeof(ICollection<int>[]), TypeInfoPropertyName = "ArrayOfIntICollection")]
+        [JsonSerializable(typeof(ICollection<int>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<string>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<IReadOnlyCollection<int>>))]
+        [JsonSerializable(typeof(GenericIReadOnlyCollectionWrapper<WrapperForIReadOnlyCollectionOfT<string>>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int[]>))]
+        [JsonSerializable(typeof(GenericIReadOnlyCollectionWrapper<int[]>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int>[]), TypeInfoPropertyName = "ArrayOfIntIReadOnlyCollection")]
+        [JsonSerializable(typeof(WrapperForIReadOnlyCollectionOfT<string>[]))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int>))]
+        [JsonSerializable(typeof(WrapperForIReadOnlyCollectionOfT<string>))]
+        [JsonSerializable(typeof(IReadOnlyList<IReadOnlyList<int>>))]
+        [JsonSerializable(typeof(GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper>))]
+        [JsonSerializable(typeof(IReadOnlyList<int[]>))]
+        [JsonSerializable(typeof(GenericIReadOnlyListWrapper<string[]>))]
+        [JsonSerializable(typeof(IReadOnlyList<int>[]), TypeInfoPropertyName = "ArrayOfIntIReadOnlyList")]
+        [JsonSerializable(typeof(StringIReadOnlyListWrapper[]))]
+        [JsonSerializable(typeof(IReadOnlyList<int>))]
+        [JsonSerializable(typeof(StringIReadOnlyListWrapper))]
+        [JsonSerializable(typeof(ISet<ISet<int>>))]
+        [JsonSerializable(typeof(GenericISetWrapper<StringISetWrapper>))]
+        [JsonSerializable(typeof(GenericStructISetWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructISetWrapper<int>?))]
+        [JsonSerializable(typeof(ISet<HashSet<int>>))]
+        [JsonSerializable(typeof(HashSet<ISet<int>>))]
+        [JsonSerializable(typeof(ISet<int[]>))]
+        [JsonSerializable(typeof(ISet<int>[]), TypeInfoPropertyName = "ArrayOfIntISet")]
+        [JsonSerializable(typeof(ISet<int>))]
+        [JsonSerializable(typeof(Stack<Stack<int>>))]
+        [JsonSerializable(typeof(GenericStackWrapper<StringStackWrapper>))]
+        [JsonSerializable(typeof(Stack<int[]>))]
+        [JsonSerializable(typeof(GenericStackWrapper<string[]>))]
+        [JsonSerializable(typeof(Stack<int>[]), TypeInfoPropertyName = "ArrayOfIntStack")]
+        [JsonSerializable(typeof(StringStackWrapper[]))]
+        [JsonSerializable(typeof(Stack<int>))]
+        [JsonSerializable(typeof(StringStackWrapper))]
+        [JsonSerializable(typeof(Queue<Queue<int>>))]
+        [JsonSerializable(typeof(GenericQueueWrapper<StringQueueWrapper>))]
+        [JsonSerializable(typeof(Queue<int[]>))]
+        [JsonSerializable(typeof(Queue<int>[]), TypeInfoPropertyName = "ArrayOfIntQueue")]
+        [JsonSerializable(typeof(Queue<int>))]
+        [JsonSerializable(typeof(HashSet<HashSet<int>>))]
+        [JsonSerializable(typeof(GenericHashSetWrapper<StringHashSetWrapper>))]
+        [JsonSerializable(typeof(HashSet<int[]>))]
+        [JsonSerializable(typeof(HashSet<int>[]), TypeInfoPropertyName = "ArrayOfIntHashSet")]
+        [JsonSerializable(typeof(HashSet<int>))]
+        [JsonSerializable(typeof(LinkedList<LinkedList<int>>))]
+        [JsonSerializable(typeof(GenericLinkedListWrapper<StringLinkedListWrapper>))]
+        [JsonSerializable(typeof(LinkedList<int[]>))]
+        [JsonSerializable(typeof(LinkedList<int>[]), TypeInfoPropertyName = "ArrayOfIntLinkedList")]
+        [JsonSerializable(typeof(LinkedList<int>))]
+        [JsonSerializable(typeof(SortedSet<int>[]))]
+        [JsonSerializable(typeof(StringSortedSetWrapper[]))]
+        [JsonSerializable(typeof(SortedSet<int>))]
+        [JsonSerializable(typeof(ClassWithGenericStructIListWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructICollectionWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructISetWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithGenericStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestStructWithNullableGenericStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithGenericCollectionWrappers))]
+        [JsonSerializable(typeof(string[]))]
+        [JsonSerializable(typeof(List<string>))]
+        [JsonSerializable(typeof(GenericListWrapper<string>))]
+        [JsonSerializable(typeof(MyMyList<string>))]
+        [JsonSerializable(typeof(MyListString))]
+        [JsonSerializable(typeof(NetworkWrapper))]
+        [JsonSerializable(typeof(Client))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<Uri, int>))]
+        [JsonSerializable(typeof(IEnumerable<IEnumerable>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<WrapperForIEnumerable>))]
+        [JsonSerializable(typeof(IEnumerable))]
+        [JsonSerializable(typeof(IEnumerable[]))]
+        [JsonSerializable(typeof(IList<IList>))]
+        [JsonSerializable(typeof(GenericIListWrapper<WrapperForIList>))]
+        [JsonSerializable(typeof(IList))]
+        [JsonSerializable(typeof(IList[]))]
+        [JsonSerializable(typeof(StructWrapperForIList))]
+        [JsonSerializable(typeof(StructWrapperForIList?))]
+        [JsonSerializable(typeof(ClassWithStructIListWrapper))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary?))]
+        [JsonSerializable(typeof(ClassWithStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(WrapperForIList))]
+        [JsonSerializable(typeof(ICollection<ICollection>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<WrapperForICollection>))]
+        [JsonSerializable(typeof(ICollection))]
+        [JsonSerializable(typeof(ICollection[]))]
+        [JsonSerializable(typeof(Stack<Stack>))]
+        [JsonSerializable(typeof(Stack))]
+        [JsonSerializable(typeof(Stack[]))]
+        [JsonSerializable(typeof(Queue<Queue>))]
+        [JsonSerializable(typeof(Queue))]
+        [JsonSerializable(typeof(Queue[]))]
+        [JsonSerializable(typeof(QueueWrapper))]
+        [JsonSerializable(typeof(ArrayList))]
+        [JsonSerializable(typeof(ArrayListWrapper))]
+        [JsonSerializable(typeof(ArrayList[]))]
+        [JsonSerializable(typeof(SimpleTestClassWithNonGenericCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestStructWithNullableStructCollectionWrappers))]
+        [JsonSerializable(typeof(Collection<bool>))]
+        [JsonSerializable(typeof(ObservableCollection<bool>))]
+        [JsonSerializable(typeof(SimpleKeyedCollection))]
+        [JsonSerializable(typeof(ReadOnlyCollection<bool>))]
+        [JsonSerializable(typeof(ReadOnlyObservableCollection<bool>))]
+        [JsonSerializable(typeof(ReadOnlyDictionary<string, bool>))]
+        [JsonSerializable(typeof(KeyedCollection<string, bool>))]
+        [JsonSerializable(typeof(BitVector32))]
+        [JsonSerializable(typeof(HybridDictionary))]
+        [JsonSerializable(typeof(OrderedDictionary))]
+        [JsonSerializable(typeof(ListDictionary))]
+        [JsonSerializable(typeof(StringCollection))]
+        [JsonSerializable(typeof(StringDictionary))]
+        [JsonSerializable(typeof(IOrderedDictionary))]
+        [JsonSerializable(typeof(NameValueCollection))]
+        [JsonSerializable(typeof(ImmutableArray<ImmutableArray<int>>))]
+        [JsonSerializable(typeof(ImmutableArray<int[]>))]
+        [JsonSerializable(typeof(ImmutableArray<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntArray")]
+        [JsonSerializable(typeof(ImmutableArray<int>))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableArray))]
+        [JsonSerializable(typeof(IImmutableList<IImmutableList<int>>))]
+        [JsonSerializable(typeof(IImmutableList<int[]>))]
+        [JsonSerializable(typeof(IImmutableList<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntArrayList")]
+        [JsonSerializable(typeof(IImmutableList<int>))]
+        [JsonSerializable(typeof(IImmutableStack<IImmutableStack<int>>))]
+        [JsonSerializable(typeof(IImmutableStack<int[]>))]
+        [JsonSerializable(typeof(IImmutableStack<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntStack")]
+        [JsonSerializable(typeof(IImmutableStack<int>))]
+        [JsonSerializable(typeof(IImmutableQueue<IImmutableQueue<int>>))]
+        [JsonSerializable(typeof(IImmutableQueue<int[]>))]
+        [JsonSerializable(typeof(IImmutableQueue<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntQueue")]
+        [JsonSerializable(typeof(IImmutableQueue<int>))]
+        [JsonSerializable(typeof(IImmutableSet<IImmutableSet<int>>))]
+        [JsonSerializable(typeof(IImmutableSet<int[]>))]
+        [JsonSerializable(typeof(IImmutableSet<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntSet")]
+        [JsonSerializable(typeof(IImmutableSet<int>))]
+        [JsonSerializable(typeof(ImmutableHashSet<ImmutableHashSet<int>>))]
+        [JsonSerializable(typeof(ImmutableHashSet<int[]>))]
+        [JsonSerializable(typeof(ImmutableHashSet<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntHashSet")]
+        [JsonSerializable(typeof(ImmutableHashSet<int>))]
+        [JsonSerializable(typeof(ImmutableList<ImmutableList<int>>))]
+        [JsonSerializable(typeof(ImmutableList<int[]>))]
+        [JsonSerializable(typeof(ImmutableList<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntList")]
+        [JsonSerializable(typeof(ImmutableList<int>))]
+        [JsonSerializable(typeof(ImmutableStack<ImmutableStack<int>>))]
+        [JsonSerializable(typeof(ImmutableStack<int[]>))]
+        [JsonSerializable(typeof(ImmutableStack<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntStack")]
+        [JsonSerializable(typeof(ImmutableStack<int>))]
+        [JsonSerializable(typeof(ImmutableQueue<ImmutableQueue<int>>))]
+        [JsonSerializable(typeof(ImmutableQueue<int[]>))]
+        [JsonSerializable(typeof(ImmutableQueue<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntQueue")]
+        [JsonSerializable(typeof(ImmutableQueue<int>))]
+        [JsonSerializable(typeof(ImmutableSortedSet<int>[]))]
+        [JsonSerializable(typeof(ImmutableSortedSet<int>))]
+        [JsonSerializable(typeof(SimpleTestClassWithIImmutableDictionaryWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableStackWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableQueueWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableSetWrapper))]
+        [JsonSerializable(typeof(ClassWithPopulatedDictionaryAndNoSetter))]
+        [JsonSerializable(typeof(StringIImmutableQueueWrapper))]
+        [JsonSerializable(typeof(StringIImmutableStackWrapper))]
+        [JsonSerializable(typeof(ClassWithPopulatedDictionaryAndSetter))]
+        [JsonSerializable(typeof(StringIImmutableListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithObjectImmutableArray))]
+        [JsonSerializable(typeof(ImmutableArray<string>))]
+        [JsonSerializable(typeof(StringIImmutableSetWrapper))]
+        [JsonSerializable(typeof(IEnumerable<ValueB>))]
+        [JsonSerializable(typeof(ICollection<ICollection<int>>))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIEnumerableWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIReadOnlyCollectionWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIReadOnlyListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper))]
+        [JsonSerializable(typeof(Dictionary<string, int?>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<GenericICollectionWrapper<string>>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericICollectionWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericICollectionWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericIListWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericIListWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericISetWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericISetWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapperPrivateConstructor<string, string>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapperInternalConstructor<string, string>))]
+        [JsonSerializable(typeof(StringToStringIReadOnlyDictionaryWrapperPrivateConstructor))]
+        [JsonSerializable(typeof(StringToStringIReadOnlyDictionaryWrapperInternalConstructor))]
+        [JsonSerializable(typeof(GenericListWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericListWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericQueueWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericQueueWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericStackWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericStackWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(StringToGenericDictionaryWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(StringToGenericDictionaryWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(SimpleTestClassWithNonGenericCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithIEnumerableWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithICollectionWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStackWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithQueueWrapper))]
+        [JsonSerializable(typeof(List<object>))]
+        [JsonSerializable(typeof(WrapperForIEnumerable))]
+        [JsonSerializable(typeof(GenericStackWrapper<StackWrapper>))]
+        [JsonSerializable(typeof(DictionaryEntry))]
+        [JsonSerializable(typeof(Dictionary<string, string>[]))]
+        [JsonSerializable(typeof(GenericQueueWrapper<QueueWrapper>))]
+        [JsonSerializable(typeof(WrapperForIEnumerablePrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIEnumerableInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForICollectionPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForICollectionInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForIListPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIListInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForIDictionaryPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIDictionaryInternalConstructor))]
+        [JsonSerializable(typeof(IDerivedICollectionOfT<string>))]
+        [JsonSerializable(typeof(IDerivedIList))]
+        [JsonSerializable(typeof(IDerivedISetOfT<string>))]
+        [JsonSerializable(typeof(ReadOnlyWrapperForIList))]
+        [JsonSerializable(typeof(ReadOnlyStringIListWrapper))]
+        [JsonSerializable(typeof(ReadOnlyStringICollectionWrapper))]
+        [JsonSerializable(typeof(ReadOnlyStringISetWrapper))]
+        [JsonSerializable(typeof(ReadOnlyWrapperForIDictionary))]
+        [JsonSerializable(typeof(ReadOnlyStringToStringIDictionaryWrapper))]
+        [JsonSerializable(typeof(Dictionary<string, int?>[]))]
+        internal sealed partial class CollectionTestsContext_Metadata : JsonSerializerContext
+        {
+        }
+    }
+
+    public partial class CollectionTests_Default : CollectionTests_Metadata
+    {
+        public CollectionTests_Default()
+            : base(new StringSerializerWrapper(CollectionTestsContext_Default.Default, (options) => new CollectionTestsContext_Default(options)))
+        {
+        }
+
+        [JsonSerializable(typeof(ConcurrentDictionary<string, string>))]
+        [JsonSerializable(typeof(ConcurrentQueue<string>))]
+        [JsonSerializable(typeof(ConcurrentStack<string>))]
+        [JsonSerializable(typeof(BlockingCollection<string>))]
+        [JsonSerializable(typeof(ConcurrentBag<string>))]
+        [JsonSerializable(typeof(GenericConcurrentQueuePrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentQueueInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentStackPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericConcurrentStackInternalConstructor<string>))]
+        [JsonSerializable(typeof(IDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, string>))]
+        [JsonSerializable(typeof(SortedDictionary<string, string>))]
+        [JsonSerializable(typeof(object))]
+        [JsonSerializable(typeof(IDictionary<string, string>))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<string, string>))]
+        [JsonSerializable(typeof(ImmutableDictionary<string, string>))]
+        [JsonSerializable(typeof(IImmutableDictionary<string, string>))]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, string>))]
+        [JsonSerializable(typeof(Hashtable))]
+        [JsonSerializable(typeof(SortedList))]
+        [JsonSerializable(typeof(WrapperForIDictionary))]
+        [JsonSerializable(typeof(StringToStringDictionaryWrapper))]
+        [JsonSerializable(typeof(StringToStringSortedDictionaryWrapper))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(StringToStringIImmutableDictionaryWrapper))]
+        [JsonSerializable(typeof(HashtableWrapper))]
+        [JsonSerializable(typeof(SortedListWrapper))]
+        [JsonSerializable(typeof(GenericStructIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(GenericStructIDictionaryWrapper<string, string>?))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, object>))]
+        [JsonSerializable(typeof(IDictionary<string, object>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, object>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapper<string, string>))]
+        [JsonSerializable(typeof(PocoDictionary))]
+        [JsonSerializable(typeof(IDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(ImmutableDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(IImmutableDictionary<string, List<int>>))]
+        [JsonSerializable(typeof(Dictionary<string, int[]>))]
+        [JsonSerializable(typeof(List<Dictionary<string, int>>))]
+        [JsonSerializable(typeof(List<ImmutableSortedDictionary<string, int>>))]
+        [JsonSerializable(typeof(Dictionary<string, int>[]), TypeInfoPropertyName = "ArrayOfDictionaryStringInt")]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, int>[]))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, int>>))]
+        [JsonSerializable(typeof(ImmutableSortedDictionary<string, ImmutableSortedDictionary<string, int>>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, Dictionary<string, int>>>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, int>[]>))]
+        [JsonSerializable(typeof(SimpleTestClass))]
+        [JsonSerializable(typeof(Dictionary<string, int>))]
+        [JsonSerializable(typeof(Dictionary<string, JsonElement>))]
+        [JsonSerializable(typeof(PocoDuplicate))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary1))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary2))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary3))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary4))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary5))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary6))]
+        [JsonSerializable(typeof(ClassWithIgnoredDictionary7))]
+        [JsonSerializable(typeof(ClassWithIgnoredIDictionary))]
+        [JsonSerializable(typeof(ClassWithIgnoreAttributeDictionary))]
+        [JsonSerializable(typeof(ClassWithIgnoredImmutableDictionary))]
+        [JsonSerializable(typeof(Dictionary<string, AllSingleUpperProperties_Child>))]
+        [JsonSerializable(typeof(AllSingleUpperPropertiesParent))]
+        [JsonSerializable(typeof(ClassWithDictionaryOfString_ChildWithDictionaryOfString))]
+        [JsonSerializable(typeof(ClassWithDictionaryOfString_ChildWithDictionaryOfString))]
+        [JsonSerializable(typeof(ClassWithDictionaryAndProperty_DictionaryFirst))]
+        [JsonSerializable(typeof(ClassWithDictionaryAndProperty_DictionaryLast))]
+        [JsonSerializable(typeof(SimpleClassWithDictionaries))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringTValue<int>))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringTValue<Poco>))]
+        [JsonSerializable(typeof(DictionaryThatOnlyImplementsIDictionaryOfStringPoco))]
+        [JsonSerializable(typeof(DictionaryThatHasIncompatibleEnumerator))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithoutParameterlessCtor>))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary?))]
+        [JsonSerializable(typeof(ClassWithStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(Poco))]
+        [JsonSerializable(typeof(JsonElement))]
+        [JsonSerializable(typeof(string))]
+        [JsonSerializable(typeof(IDictionary<int, int>))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithInternalParameterlessConstructor>))]
+        [JsonSerializable(typeof(Dictionary<string, ClassWithPrivateParameterlessConstructor>))]
+        [JsonSerializable(typeof(Dictionary<string, Dictionary<string, CustomClass>>))]
+        [JsonSerializable(typeof(TestClassWithDictionary))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<Uri, int>))]
+        [JsonSerializable(typeof(GenericIReadOnlyDictionaryWrapper<Uri, int>))]
+        [JsonSerializable(typeof(List<int>))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<int, int>))]
+        [JsonSerializable(typeof(Dictionary<string, CustomClass>))]
+        [JsonSerializable(typeof(IDerivedIDictionaryOfTKeyTValue<string, string>))]
+        [JsonSerializable(typeof(List<List<int>>))]
+        [JsonSerializable(typeof(GenericListWrapper<StringListWrapper>))]
+        [JsonSerializable(typeof(List<List<int>>))]
+        [JsonSerializable(typeof(GenericListWrapper<StringListWrapper>))]
+        [JsonSerializable(typeof(List<int[]>))]
+        [JsonSerializable(typeof(GenericListWrapper<string[]>))]
+        [JsonSerializable(typeof(List<int>[]), TypeInfoPropertyName = "ArrayOfIntList")]
+        [JsonSerializable(typeof(StringListWrapper[]))]
+        [JsonSerializable(typeof(List<int>))]
+        [JsonSerializable(typeof(StringListWrapper))]
+        [JsonSerializable(typeof(IEnumerable<IEnumerable<int>>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<StringIEnumerableWrapper>))]
+        [JsonSerializable(typeof(IEnumerable<int[]>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<int[]>))]
+        [JsonSerializable(typeof(IEnumerable<int>[]), TypeInfoPropertyName = "ArrayOfIntIEnumerable")]
+        [JsonSerializable(typeof(StringIEnumerableWrapper[]))]
+        [JsonSerializable(typeof(IEnumerable<int>))]
+        [JsonSerializable(typeof(StringIEnumerableWrapper))]
+        [JsonSerializable(typeof(IList<IList<int>>))]
+        [JsonSerializable(typeof(GenericIListWrapper<StringIListWrapper>))]
+        [JsonSerializable(typeof(IList<int[]>))]
+        [JsonSerializable(typeof(GenericIListWrapper<string[]>))]
+        [JsonSerializable(typeof(IList<int>[]), TypeInfoPropertyName = "ArrayOfIntIList")]
+        [JsonSerializable(typeof(StringIListWrapper[]))]
+        [JsonSerializable(typeof(IList<int>))]
+        [JsonSerializable(typeof(StringIListWrapper))]
+        [JsonSerializable(typeof(GenericStructIListWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructIListWrapper<int>?))]
+        [JsonSerializable(typeof(GenericStructICollectionWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructICollectionWrapper<int>?))]
+        [JsonSerializable(typeof(ICollection<ICollection<int>>))]
+        [JsonSerializable(typeof(ICollection<int[]>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<string[]>))]
+        [JsonSerializable(typeof(ICollection<int>[]), TypeInfoPropertyName = "ArrayOfIntICollection")]
+        [JsonSerializable(typeof(ICollection<int>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<string>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<IReadOnlyCollection<int>>))]
+        [JsonSerializable(typeof(GenericIReadOnlyCollectionWrapper<WrapperForIReadOnlyCollectionOfT<string>>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int[]>))]
+        [JsonSerializable(typeof(GenericIReadOnlyCollectionWrapper<int[]>))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int>[]), TypeInfoPropertyName = "ArrayOfIntIReadOnlyCollection")]
+        [JsonSerializable(typeof(WrapperForIReadOnlyCollectionOfT<string>[]))]
+        [JsonSerializable(typeof(IReadOnlyCollection<int>))]
+        [JsonSerializable(typeof(WrapperForIReadOnlyCollectionOfT<string>))]
+        [JsonSerializable(typeof(IReadOnlyList<IReadOnlyList<int>>))]
+        [JsonSerializable(typeof(GenericIReadOnlyListWrapper<StringIReadOnlyListWrapper>))]
+        [JsonSerializable(typeof(IReadOnlyList<int[]>))]
+        [JsonSerializable(typeof(GenericIReadOnlyListWrapper<string[]>))]
+        [JsonSerializable(typeof(IReadOnlyList<int>[]), TypeInfoPropertyName = "ArrayOfIntIReadOnlyList")]
+        [JsonSerializable(typeof(StringIReadOnlyListWrapper[]))]
+        [JsonSerializable(typeof(IReadOnlyList<int>))]
+        [JsonSerializable(typeof(StringIReadOnlyListWrapper))]
+        [JsonSerializable(typeof(ISet<ISet<int>>))]
+        [JsonSerializable(typeof(GenericISetWrapper<StringISetWrapper>))]
+        [JsonSerializable(typeof(GenericStructISetWrapper<int>))]
+        [JsonSerializable(typeof(GenericStructISetWrapper<int>?))]
+        [JsonSerializable(typeof(ISet<HashSet<int>>))]
+        [JsonSerializable(typeof(HashSet<ISet<int>>))]
+        [JsonSerializable(typeof(ISet<int[]>))]
+        [JsonSerializable(typeof(ISet<int>[]), TypeInfoPropertyName = "ArrayOfIntISet")]
+        [JsonSerializable(typeof(ISet<int>))]
+        [JsonSerializable(typeof(Stack<Stack<int>>))]
+        [JsonSerializable(typeof(GenericStackWrapper<StringStackWrapper>))]
+        [JsonSerializable(typeof(Stack<int[]>))]
+        [JsonSerializable(typeof(GenericStackWrapper<string[]>))]
+        [JsonSerializable(typeof(Stack<int>[]), TypeInfoPropertyName = "ArrayOfIntStack")]
+        [JsonSerializable(typeof(StringStackWrapper[]))]
+        [JsonSerializable(typeof(Stack<int>))]
+        [JsonSerializable(typeof(StringStackWrapper))]
+        [JsonSerializable(typeof(Queue<Queue<int>>))]
+        [JsonSerializable(typeof(GenericQueueWrapper<StringQueueWrapper>))]
+        [JsonSerializable(typeof(Queue<int[]>))]
+        [JsonSerializable(typeof(Queue<int>[]), TypeInfoPropertyName = "ArrayOfIntQueue")]
+        [JsonSerializable(typeof(Queue<int>))]
+        [JsonSerializable(typeof(HashSet<HashSet<int>>))]
+        [JsonSerializable(typeof(GenericHashSetWrapper<StringHashSetWrapper>))]
+        [JsonSerializable(typeof(HashSet<int[]>))]
+        [JsonSerializable(typeof(HashSet<int>[]), TypeInfoPropertyName = "ArrayOfIntHashSet")]
+        [JsonSerializable(typeof(HashSet<int>))]
+        [JsonSerializable(typeof(LinkedList<LinkedList<int>>))]
+        [JsonSerializable(typeof(GenericLinkedListWrapper<StringLinkedListWrapper>))]
+        [JsonSerializable(typeof(LinkedList<int[]>))]
+        [JsonSerializable(typeof(LinkedList<int>[]), TypeInfoPropertyName = "ArrayOfIntLinkedList")]
+        [JsonSerializable(typeof(LinkedList<int>))]
+        [JsonSerializable(typeof(SortedSet<int>[]))]
+        [JsonSerializable(typeof(StringSortedSetWrapper[]))]
+        [JsonSerializable(typeof(SortedSet<int>))]
+        [JsonSerializable(typeof(ClassWithGenericStructIListWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructICollectionWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(ClassWithGenericStructISetWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithGenericStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestStructWithNullableGenericStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithGenericCollectionWrappers))]
+        [JsonSerializable(typeof(string[]))]
+        [JsonSerializable(typeof(List<string>))]
+        [JsonSerializable(typeof(GenericListWrapper<string>))]
+        [JsonSerializable(typeof(MyMyList<string>))]
+        [JsonSerializable(typeof(MyListString))]
+        [JsonSerializable(typeof(NetworkWrapper))]
+        [JsonSerializable(typeof(Client))]
+        [JsonSerializable(typeof(IReadOnlyDictionary<Uri, int>))]
+        [JsonSerializable(typeof(IEnumerable<IEnumerable>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapper<WrapperForIEnumerable>))]
+        [JsonSerializable(typeof(IEnumerable))]
+        [JsonSerializable(typeof(IEnumerable[]))]
+        [JsonSerializable(typeof(IList<IList>))]
+        [JsonSerializable(typeof(GenericIListWrapper<WrapperForIList>))]
+        [JsonSerializable(typeof(IList))]
+        [JsonSerializable(typeof(IList[]))]
+        [JsonSerializable(typeof(StructWrapperForIList))]
+        [JsonSerializable(typeof(StructWrapperForIList?))]
+        [JsonSerializable(typeof(ClassWithStructIListWrapper))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary))]
+        [JsonSerializable(typeof(StructWrapperForIDictionary?))]
+        [JsonSerializable(typeof(ClassWithStructIDictionaryWrapper))]
+        [JsonSerializable(typeof(WrapperForIList))]
+        [JsonSerializable(typeof(ICollection<ICollection>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<WrapperForICollection>))]
+        [JsonSerializable(typeof(ICollection))]
+        [JsonSerializable(typeof(ICollection[]))]
+        [JsonSerializable(typeof(Stack<Stack>))]
+        [JsonSerializable(typeof(Stack))]
+        [JsonSerializable(typeof(Stack[]))]
+        [JsonSerializable(typeof(Queue<Queue>))]
+        [JsonSerializable(typeof(Queue))]
+        [JsonSerializable(typeof(Queue[]))]
+        [JsonSerializable(typeof(QueueWrapper))]
+        [JsonSerializable(typeof(ArrayList))]
+        [JsonSerializable(typeof(ArrayListWrapper))]
+        [JsonSerializable(typeof(ArrayList[]))]
+        [JsonSerializable(typeof(SimpleTestClassWithNonGenericCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithStructCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestStructWithNullableStructCollectionWrappers))]
+        [JsonSerializable(typeof(Collection<bool>))]
+        [JsonSerializable(typeof(ObservableCollection<bool>))]
+        [JsonSerializable(typeof(SimpleKeyedCollection))]
+        [JsonSerializable(typeof(ReadOnlyCollection<bool>))]
+        [JsonSerializable(typeof(ReadOnlyObservableCollection<bool>))]
+        [JsonSerializable(typeof(ReadOnlyDictionary<string, bool>))]
+        [JsonSerializable(typeof(KeyedCollection<string, bool>))]
+        [JsonSerializable(typeof(BitVector32))]
+        [JsonSerializable(typeof(HybridDictionary))]
+        [JsonSerializable(typeof(OrderedDictionary))]
+        [JsonSerializable(typeof(ListDictionary))]
+        [JsonSerializable(typeof(StringCollection))]
+        [JsonSerializable(typeof(StringDictionary))]
+        [JsonSerializable(typeof(IOrderedDictionary))]
+        [JsonSerializable(typeof(NameValueCollection))]
+        [JsonSerializable(typeof(ImmutableArray<ImmutableArray<int>>))]
+        [JsonSerializable(typeof(ImmutableArray<int[]>))]
+        [JsonSerializable(typeof(ImmutableArray<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntArray")]
+        [JsonSerializable(typeof(ImmutableArray<int>))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableArray))]
+        [JsonSerializable(typeof(IImmutableList<IImmutableList<int>>))]
+        [JsonSerializable(typeof(IImmutableList<int[]>))]
+        [JsonSerializable(typeof(IImmutableList<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntArrayList")]
+        [JsonSerializable(typeof(IImmutableList<int>))]
+        [JsonSerializable(typeof(IImmutableStack<IImmutableStack<int>>))]
+        [JsonSerializable(typeof(IImmutableStack<int[]>))]
+        [JsonSerializable(typeof(IImmutableStack<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntStack")]
+        [JsonSerializable(typeof(IImmutableStack<int>))]
+        [JsonSerializable(typeof(IImmutableQueue<IImmutableQueue<int>>))]
+        [JsonSerializable(typeof(IImmutableQueue<int[]>))]
+        [JsonSerializable(typeof(IImmutableQueue<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntQueue")]
+        [JsonSerializable(typeof(IImmutableQueue<int>))]
+        [JsonSerializable(typeof(IImmutableSet<IImmutableSet<int>>))]
+        [JsonSerializable(typeof(IImmutableSet<int[]>))]
+        [JsonSerializable(typeof(IImmutableSet<int>[]), TypeInfoPropertyName = "ArrayOfIImmutableIntSet")]
+        [JsonSerializable(typeof(IImmutableSet<int>))]
+        [JsonSerializable(typeof(ImmutableHashSet<ImmutableHashSet<int>>))]
+        [JsonSerializable(typeof(ImmutableHashSet<int[]>))]
+        [JsonSerializable(typeof(ImmutableHashSet<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntHashSet")]
+        [JsonSerializable(typeof(ImmutableHashSet<int>))]
+        [JsonSerializable(typeof(ImmutableList<ImmutableList<int>>))]
+        [JsonSerializable(typeof(ImmutableList<int[]>))]
+        [JsonSerializable(typeof(ImmutableList<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntList")]
+        [JsonSerializable(typeof(ImmutableList<int>))]
+        [JsonSerializable(typeof(ImmutableStack<ImmutableStack<int>>))]
+        [JsonSerializable(typeof(ImmutableStack<int[]>))]
+        [JsonSerializable(typeof(ImmutableStack<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntStack")]
+        [JsonSerializable(typeof(ImmutableStack<int>))]
+        [JsonSerializable(typeof(ImmutableQueue<ImmutableQueue<int>>))]
+        [JsonSerializable(typeof(ImmutableQueue<int[]>))]
+        [JsonSerializable(typeof(ImmutableQueue<int>[]), TypeInfoPropertyName = "ArrayOfImmutableIntQueue")]
+        [JsonSerializable(typeof(ImmutableQueue<int>))]
+        [JsonSerializable(typeof(ImmutableSortedSet<int>[]))]
+        [JsonSerializable(typeof(ImmutableSortedSet<int>))]
+        [JsonSerializable(typeof(SimpleTestClassWithIImmutableDictionaryWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableStackWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableQueueWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithImmutableSetWrapper))]
+        [JsonSerializable(typeof(ClassWithPopulatedDictionaryAndNoSetter))]
+        [JsonSerializable(typeof(StringIImmutableQueueWrapper))]
+        [JsonSerializable(typeof(StringIImmutableStackWrapper))]
+        [JsonSerializable(typeof(ClassWithPopulatedDictionaryAndSetter))]
+        [JsonSerializable(typeof(StringIImmutableListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithObjectImmutableArray))]
+        [JsonSerializable(typeof(ImmutableArray<string>))]
+        [JsonSerializable(typeof(StringIImmutableSetWrapper))]
+        [JsonSerializable(typeof(IEnumerable<ValueB>))]
+        [JsonSerializable(typeof(ICollection<ICollection<int>>))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIEnumerableWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIReadOnlyCollectionWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringIReadOnlyListWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStringToStringIReadOnlyDictionaryWrapper))]
+        [JsonSerializable(typeof(Dictionary<string, int?>))]
+        [JsonSerializable(typeof(GenericICollectionWrapper<GenericICollectionWrapper<string>>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericIEnumerableWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericICollectionWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericICollectionWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericIListWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericIListWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericISetWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericISetWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapperPrivateConstructor<string, string>))]
+        [JsonSerializable(typeof(GenericIDictionaryWrapperInternalConstructor<string, string>))]
+        [JsonSerializable(typeof(StringToStringIReadOnlyDictionaryWrapperPrivateConstructor))]
+        [JsonSerializable(typeof(StringToStringIReadOnlyDictionaryWrapperInternalConstructor))]
+        [JsonSerializable(typeof(GenericListWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericListWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericQueueWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericQueueWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(GenericStackWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(GenericStackWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(StringToGenericDictionaryWrapperPrivateConstructor<string>))]
+        [JsonSerializable(typeof(StringToGenericDictionaryWrapperInternalConstructor<string>))]
+        [JsonSerializable(typeof(SimpleTestClassWithNonGenericCollectionWrappers))]
+        [JsonSerializable(typeof(SimpleTestClassWithIEnumerableWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithICollectionWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithStackWrapper))]
+        [JsonSerializable(typeof(SimpleTestClassWithQueueWrapper))]
+        [JsonSerializable(typeof(List<object>))]
+        [JsonSerializable(typeof(WrapperForIEnumerable))]
+        [JsonSerializable(typeof(GenericStackWrapper<StackWrapper>))]
+        [JsonSerializable(typeof(DictionaryEntry))]
+        [JsonSerializable(typeof(Dictionary<string, string>[]))]
+        [JsonSerializable(typeof(GenericQueueWrapper<QueueWrapper>))]
+        [JsonSerializable(typeof(WrapperForIEnumerablePrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIEnumerableInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForICollectionPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForICollectionInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForIListPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIListInternalConstructor))]
+        [JsonSerializable(typeof(WrapperForIDictionaryPrivateConstructor))]
+        [JsonSerializable(typeof(WrapperForIDictionaryInternalConstructor))]
+        [JsonSerializable(typeof(IDerivedICollectionOfT<string>))]
+        [JsonSerializable(typeof(IDerivedIList))]
+        [JsonSerializable(typeof(IDerivedISetOfT<string>))]
+        [JsonSerializable(typeof(ReadOnlyWrapperForIList))]
+        [JsonSerializable(typeof(ReadOnlyStringIListWrapper))]
+        [JsonSerializable(typeof(ReadOnlyStringICollectionWrapper))]
+        [JsonSerializable(typeof(ReadOnlyStringISetWrapper))]
+        [JsonSerializable(typeof(ReadOnlyWrapperForIDictionary))]
+        [JsonSerializable(typeof(ReadOnlyStringToStringIDictionaryWrapper))]
+        [JsonSerializable(typeof(Dictionary<string, int?>[]))]
+        internal sealed partial class CollectionTestsContext_Default : JsonSerializerContext
+        {
+        }
+    }
+}
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.IO;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization.Metadata;
 using System.Text.Json.Serialization.Tests;
@@ -8,12 +9,12 @@ using System.Threading.Tasks;
 
 namespace System.Text.Json.SourceGeneration.Tests
 {
-    internal sealed class JsonSerializerWrapperForString_SourceGen : JsonSerializerWrapperForString
+    internal sealed class StringSerializerWrapper : JsonSerializerWrapperForString
     {
         private readonly JsonSerializerContext _defaultContext;
         private readonly Func<JsonSerializerOptions, JsonSerializerContext> _customContextCreator;
 
-        public JsonSerializerWrapperForString_SourceGen(JsonSerializerContext defaultContext, Func<JsonSerializerOptions, JsonSerializerContext> customContextCreator)
+        public StringSerializerWrapper(JsonSerializerContext defaultContext, Func<JsonSerializerOptions, JsonSerializerContext> customContextCreator)
         {
             _defaultContext = defaultContext ?? throw new ArgumentNullException(nameof(defaultContext));
             _customContextCreator = customContextCreator ?? throw new ArgumentNullException(nameof(defaultContext));
@@ -37,6 +38,13 @@ namespace System.Text.Json.SourceGeneration.Tests
 
         protected internal override Task<string> SerializeWrapper<T>(T value, JsonSerializerOptions? options = null)
         {
+            Type runtimeType = GetRuntimeType(value);
+
+            if (runtimeType != typeof(T))
+            {
+                return SerializeWrapper(value, runtimeType, options);
+            }
+
             if (options != null)
             {
                 return Task.FromResult(Serialize(value, options));
@@ -53,6 +61,16 @@ namespace System.Text.Json.SourceGeneration.Tests
             return JsonSerializer.Serialize(value, typeInfo);
         }
 
+        private static Type GetRuntimeType<TValue>(in TValue value)
+        {
+            if (typeof(TValue) == typeof(object) && value != null)
+            {
+                return value.GetType();
+            }
+
+            return typeof(TValue);
+        }
+
         protected internal override Task<string> SerializeWrapper(object value, Type inputType, JsonSerializerContext context)
             => throw new NotImplementedException();
 
@@ -99,4 +117,14 @@ namespace System.Text.Json.SourceGeneration.Tests
         protected internal override Task<object> DeserializeWrapper(string json, Type type, JsonSerializerContext context)
             => throw new NotImplementedException();
     }
+
+    internal sealed class StreamSerializerWrapper : JsonSerializerWrapperForStream
+    {
+        protected internal override Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonSerializerOptions options = null) => throw new NotImplementedException();
+        protected internal override Task<object> DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions options = null) => throw new NotImplementedException();
+        protected internal override Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonTypeInfo<T> jsonTypeInfo) => throw new NotImplementedException();
+        protected internal override Task SerializeWrapper<T>(Stream stream, T value, JsonSerializerOptions options = null) => throw new NotImplementedException();
+        protected internal override Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerOptions options = null) => throw new NotImplementedException();
+        protected internal override Task SerializeWrapper<T>(Stream stream, T value, JsonTypeInfo<T> jsonTypeInfo) => throw new NotImplementedException();
+    }
 }
index 6ebb90f..cc9b3d6 100644 (file)
@@ -12,11 +12,11 @@ namespace System.Text.Json.SourceGeneration.Tests
     public partial class PropertyVisibilityTests_Metadata : PropertyVisibilityTests
     {
         public PropertyVisibilityTests_Metadata()
-            : this(new JsonSerializerWrapperForString_SourceGen(PropertyVisibilityTestsContext_Metadata.Default, (options) => new PropertyVisibilityTestsContext_Metadata(options)))
+            : this(new StringSerializerWrapper(PropertyVisibilityTestsContext_Metadata.Default, (options) => new PropertyVisibilityTestsContext_Metadata(options)))
         {
         }
 
-        protected PropertyVisibilityTests_Metadata(JsonSerializerWrapperForString serializerWrapper)
+        protected PropertyVisibilityTests_Metadata(Serialization.Tests.JsonSerializerWrapperForString serializerWrapper)
             : base(serializerWrapper)
         {
         }
@@ -259,10 +259,9 @@ namespace System.Text.Json.SourceGeneration.Tests
     }
 
     public partial class PropertyVisibilityTests_Default : PropertyVisibilityTests_Metadata
-    //public partial class PropertyVisibilityTests_Default : PropertyVisibilityTests
     {
         public PropertyVisibilityTests_Default()
-            : base(new JsonSerializerWrapperForString_SourceGen(PropertyVisibilityTestsContext_Default.Default, (options) => new PropertyVisibilityTestsContext_Default(options)))
+            : base(new StringSerializerWrapper(PropertyVisibilityTestsContext_Default.Default, (options) => new PropertyVisibilityTestsContext_Default(options)))
         {
         }
 
index daa3a4c..a086659 100644 (file)
@@ -52,8 +52,8 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public static void DictionaryFastPathPrimitiveValueSupported()
         {
-            Assert.NotNull(DictionaryTypeContext.Default.DictionarySystemStringSystemString.Serialize);
-            Assert.NotNull(DictionaryTypeContext.Default.DictionarySystemStringSystemTextJsonSourceGenerationTestsJsonMessage.Serialize);
+            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringString.Serialize);
+            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringJsonMessage.Serialize);
             Assert.NotNull(DictionaryTypeContext.Default.JsonMessage.Serialize);
             Assert.Null(DictionaryTypeContext.Default.String.Serialize);
             Assert.Null(DictionaryTypeContext.Default.Int32.Serialize);
index 2520aa5..9b8dc0b 100644 (file)
@@ -2,6 +2,7 @@
   <PropertyGroup>
     <TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkCurrent)</TargetFrameworks>
     <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
+    <IncludeRemoteExecutor>true</IncludeRemoteExecutor>
     <!-- SYSLIB0020: JsonSerializerOptions.IgnoreNullValues is obsolete -->
     <NoWarn>$(NoWarn);SYSLIB0020</NoWarn>
   </PropertyGroup>
   </ItemGroup>
 
   <ItemGroup>
+    <Compile Include="..\Common\CollectionTests\CollectionTests.AsyncEnumerable.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.AsyncEnumerable.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Concurrent.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Concurrent.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.KeyPolicy.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.KeyPolicy.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.NonStringKey.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.NonStringKey.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Generic.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Generic.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Generic.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Generic.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Immutable.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Immutable.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.KeyValuePair.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.KeyValuePair.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.NonGeneric.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.NonGeneric.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.NonGeneric.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.NonGeneric.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.ObjectModel.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.ObjectModel.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.ObjectModel.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.ObjectModel.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Specialized.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Specialized.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Specialized.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Specialized.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Immutable.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Immutable.Write.cs" />
+    <Compile Include="..\Common\JsonSerializerWrapperForStream.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForStream.cs" />
     <Compile Include="..\Common\JsonSerializerWrapperForString.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForString.cs" />
     <Compile Include="..\Common\JsonTestHelper.cs" Link="CommonTest\System\Text\Json\JsonTestHelper.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.cs" />
@@ -39,7 +58,8 @@
     <Compile Include="..\Common\TestClasses\TestClasses.ValueTypedMember.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\TestClasses\TestClasses.ValueTypedMember.cs" />
     <Compile Include="ContextClasses.cs" />
     <Compile Include="JsonSerializerContextTests.cs" />
-    <Compile Include="Serialization\JsonSerializerWrapperForString_SourceGen.cs" />
+    <Compile Include="Serialization\CollectionTests.cs" />
+    <Compile Include="Serialization\JsonSerializerWrapper.cs" />
     <Compile Include="JsonTestHelper.cs" />
     <Compile Include="MetadataAndSerializationContextTests.cs" />
     <Compile Include="MetadataContextTests.cs" />
index ff110fe..50be97c 100644 (file)
@@ -134,4 +134,6 @@ namespace System.Text.Json.SourceGeneration.Tests
         public string Message { get; set; }
         public int Length => Message?.Length ?? 0; // Read-only property
     }
+
+    internal struct MyStruct { }
 }
index 269469a..d30e62a 100644 (file)
@@ -801,11 +801,6 @@ namespace System.Text.Json
             }
         }
 
-        private static readonly Regex s_stripWhitespace = new Regex(@"\s+", RegexOptions.Compiled);
-
-        public static string StripWhitespace(this string value)
-            => s_stripWhitespace.Replace(value, string.Empty);
-
 #if NET6_0_OR_GREATER
         // This is needed due to the fact that git might normalize line endings when checking-out files
         public static string NormalizeLineEndings(this string value) => value.ReplaceLineEndings();
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests.cs
new file mode 100644 (file)
index 0000000..d0a10ba
--- /dev/null
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public sealed partial class CollectionTestsDynamic : CollectionTests
+    {
+        public CollectionTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer, JsonSerializerWrapperForStream.AsyncStreamSerializer) { }
+    }
+}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.Write.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.Write.cs
deleted file mode 100644 (file)
index 0cb162b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Concurrent;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void Write_ConcurrentCollection()
-        {
-            Assert.Equal(@"[""1""]", JsonSerializer.Serialize(new BlockingCollection<string> { "1" }));
-
-            Assert.Equal(@"[""1""]", JsonSerializer.Serialize(new ConcurrentBag<string> { "1" }));
-
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize(new ConcurrentDictionary<string, string> { ["key"] = "value" }));
-
-            ConcurrentQueue<string> qc = new ConcurrentQueue<string>();
-            qc.Enqueue("1");
-            Assert.Equal(@"[""1""]", JsonSerializer.Serialize(qc));
-
-            ConcurrentStack<string> qs = new ConcurrentStack<string>();
-            qs.Push("1");
-            Assert.Equal(@"[""1""]", JsonSerializer.Serialize(qs));
-        }
-    }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Concurrent.cs
deleted file mode 100644 (file)
index 2a737f3..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Concurrent;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void Read_ConcurrentCollection()
-        {
-            ConcurrentDictionary<string, string> cd = JsonSerializer.Deserialize<ConcurrentDictionary<string, string>>(@"{""key"":""value""}");
-            Assert.Equal(1, cd.Count);
-            Assert.Equal("value", cd["key"]);
-
-            ConcurrentQueue<string> qc = JsonSerializer.Deserialize<ConcurrentQueue<string>>(@"[""1""]");
-            Assert.Equal(1, qc.Count);
-            bool found = qc.TryPeek(out string val);
-            Assert.True(found);
-            Assert.Equal("1", val);
-
-            ConcurrentStack<string> qs = JsonSerializer.Deserialize<ConcurrentStack<string>>(@"[""1""]");
-            Assert.Equal(1, qs.Count);
-            found = qs.TryPeek(out val);
-            Assert.True(found);
-            Assert.Equal("1", val);
-        }
-
-        [Theory]
-        [InlineData(typeof(BlockingCollection<string>), @"[""1""]")] // Not supported. Not IList, and we don't detect the add method for this collection.
-        [InlineData(typeof(ConcurrentBag<string>), @"[""1""]")] // Not supported. Not IList, and we don't detect the add method for this collection.
-        public static void Read_ConcurrentCollection_Throws(Type type, string json)
-        {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
-            Assert.Contains(type.ToString(), ex.Message);
-        }
-
-        [Theory]
-        [InlineData(typeof(GenericConcurrentQueuePrivateConstructor<string>), @"[""1""]")]
-        [InlineData(typeof(GenericConcurrentQueueInternalConstructor<string>), @"[""1""]")]
-        [InlineData(typeof(GenericConcurrentStackPrivateConstructor<string>), @"[""1""]")]
-        [InlineData(typeof(GenericConcurrentStackInternalConstructor<string>), @"[""1""]")]
-        public static void Read_ConcurrentCollection_NoPublicConstructor_Throws(Type type, string json)
-        {
-            NotSupportedException ex = Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize(json, type));
-            Assert.Contains(type.ToString(), ex.Message);
-        }
-    }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Immutable.Read.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Immutable.Read.cs
deleted file mode 100644 (file)
index 09b6562..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void ReadImmutableArrayOfImmutableArray()
-        {
-            ImmutableArray<ImmutableArray<int>> result = JsonSerializer.Deserialize<ImmutableArray<ImmutableArray<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableArray<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadImmutableArrayOfArray()
-        {
-            ImmutableArray<int[]> result = JsonSerializer.Deserialize<ImmutableArray<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfImmutableArray()
-        {
-            ImmutableArray<int>[] result = JsonSerializer.Deserialize<ImmutableArray<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableArray<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadSimpleImmutableArray()
-        {
-            ImmutableArray<int> result = JsonSerializer.Deserialize<ImmutableArray<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<ImmutableArray<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadSimpleClassWithImmutableArray()
-        {
-            SimpleTestClassWithImmutableArray obj = JsonSerializer.Deserialize<SimpleTestClassWithImmutableArray>(SimpleTestClassWithImmutableArray.s_json);
-            obj.Verify();
-        }
-
-        [Fact]
-        public static void ReadIImmutableListTOfIImmutableListT()
-        {
-            IImmutableList<IImmutableList<int>> result = JsonSerializer.Deserialize<IImmutableList<IImmutableList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (IImmutableList<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadIImmutableListTOfArray()
-        {
-            IImmutableList<int[]> result = JsonSerializer.Deserialize<IImmutableList<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfIIImmutableListT()
-        {
-            IImmutableList<int>[] result = JsonSerializer.Deserialize<IImmutableList<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (IImmutableList<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveIImmutableListT()
-        {
-            IImmutableList<int> result = JsonSerializer.Deserialize<IImmutableList<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<IImmutableList<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableListWrapper>(@"[""1"",""2""]"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableListWrapper>(@"[]"));
-        }
-
-        [Fact]
-        public static void ReadIImmutableStackTOfIImmutableStackT()
-        {
-            IImmutableStack<IImmutableStack<int>> result = JsonSerializer.Deserialize<IImmutableStack<IImmutableStack<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 4;
-
-            foreach (IImmutableStack<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected--, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadIImmutableStackTOfArray()
-        {
-            IImmutableStack<int[]> result = JsonSerializer.Deserialize<IImmutableStack<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 3;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-
-                expected = 1;
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfIIImmutableStackT()
-        {
-            IImmutableStack<int>[] result = JsonSerializer.Deserialize<IImmutableStack<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 2;
-
-            foreach (IImmutableStack<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected--, i);
-                }
-
-                expected = 4;
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveIImmutableStackT()
-        {
-            IImmutableStack<int> result = JsonSerializer.Deserialize<IImmutableStack<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 2;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected--, i);
-            }
-
-            result = JsonSerializer.Deserialize<IImmutableStack<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableStackWrapper>(@"[""1"",""2""]"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableStackWrapper>(@"[]"));
-        }
-
-        [Fact]
-        public static void ReadIImmutableQueueTOfIImmutableQueueT()
-        {
-            IImmutableQueue<IImmutableQueue<int>> result = JsonSerializer.Deserialize<IImmutableQueue<IImmutableQueue<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (IImmutableQueue<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadIImmutableQueueTOfArray()
-        {
-            IImmutableQueue<int[]> result = JsonSerializer.Deserialize<IImmutableQueue<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableQueueT()
-        {
-            IImmutableQueue<int>[] result = JsonSerializer.Deserialize<IImmutableQueue<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (IImmutableQueue<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveIImmutableQueueT()
-        {
-            IImmutableQueue<int> result = JsonSerializer.Deserialize<IImmutableQueue<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<IImmutableQueue<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableQueueWrapper>(@"[""1"",""2""]"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableQueueWrapper>(@"[]"));
-        }
-
-        [Fact]
-        public static void ReadIImmutableSetTOfIImmutableSetT()
-        {
-            IImmutableSet<IImmutableSet<int>> result = JsonSerializer.Deserialize<IImmutableSet<IImmutableSet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (IImmutableSet<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadIImmutableSetTOfArray()
-        {
-            IImmutableSet<int[]> result = JsonSerializer.Deserialize<IImmutableSet<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableSetT()
-        {
-            IImmutableSet<int>[] result = JsonSerializer.Deserialize<IImmutableSet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (IImmutableSet<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadPrimitiveIImmutableSetT()
-        {
-            IImmutableSet<int> result = JsonSerializer.Deserialize<IImmutableSet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            List<int> expected = new List<int> { 1, 2 };
-
-            foreach (int i in result)
-            {
-                expected.Remove(i);
-            }
-
-            Assert.Equal(0, expected.Count);
-
-            result = JsonSerializer.Deserialize<IImmutableSet<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableSetWrapper>(@"[""1"",""2""]"));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringIImmutableSetWrapper>(@"[]"));
-        }
-
-        [Fact]
-        public static void ReadImmutableHashSetTOfImmutableHashSetT()
-        {
-            ImmutableHashSet<ImmutableHashSet<int>> result = JsonSerializer.Deserialize<ImmutableHashSet<ImmutableHashSet<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (ImmutableHashSet<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadImmutableHashSetTOfArray()
-        {
-            ImmutableHashSet<int[]> result = JsonSerializer.Deserialize<ImmutableHashSet<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableHashSetT()
-        {
-            ImmutableHashSet<int>[] result = JsonSerializer.Deserialize<ImmutableHashSet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            List<int> expected = new List<int> { 1, 2, 3, 4 };
-
-            foreach (ImmutableHashSet<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    expected.Remove(i);
-                }
-            }
-
-            Assert.Equal(0, expected.Count);
-        }
-
-        [Fact]
-        public static void ReadPrimitiveImmutableHashSetT()
-        {
-            ImmutableHashSet<int> result = JsonSerializer.Deserialize<ImmutableHashSet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            List<int> expected = new List<int> { 1, 2 };
-
-            foreach (int i in result)
-            {
-                expected.Remove(i);
-            }
-
-            Assert.Equal(0, expected.Count);
-
-            result = JsonSerializer.Deserialize<ImmutableHashSet<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadImmutableListTOfImmutableListT()
-        {
-            ImmutableList<ImmutableList<int>> result = JsonSerializer.Deserialize<ImmutableList<ImmutableList<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableList<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadImmutableListTOfArray()
-        {
-            ImmutableList<int[]> result = JsonSerializer.Deserialize<ImmutableList<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableListT()
-        {
-            ImmutableList<int>[] result = JsonSerializer.Deserialize<ImmutableList<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableList<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveImmutableListT()
-        {
-            ImmutableList<int> result = JsonSerializer.Deserialize<ImmutableList<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<ImmutableList<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadImmutableStackTOfImmutableStackT()
-        {
-            ImmutableStack<ImmutableStack<int>> result = JsonSerializer.Deserialize<ImmutableStack<ImmutableStack<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 4;
-
-            foreach (ImmutableStack<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected--, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadImmutableStackTOfArray()
-        {
-            ImmutableStack<int[]> result = JsonSerializer.Deserialize<ImmutableStack<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 3;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-
-                expected = 1;
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableStackT()
-        {
-            ImmutableStack<int>[] result = JsonSerializer.Deserialize<ImmutableStack<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 2;
-
-            foreach (ImmutableStack<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected--, i);
-                }
-
-                expected = 4;
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveImmutableStackT()
-        {
-            ImmutableStack<int> result = JsonSerializer.Deserialize<ImmutableStack<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 2;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected--, i);
-            }
-
-            result = JsonSerializer.Deserialize<ImmutableStack<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadImmutableQueueTOfImmutableQueueT()
-        {
-            ImmutableQueue<ImmutableQueue<int>> result = JsonSerializer.Deserialize<ImmutableQueue<ImmutableQueue<int>>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableQueue<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadImmutableQueueTOfArray()
-        {
-            ImmutableQueue<int[]> result = JsonSerializer.Deserialize<ImmutableQueue<int[]>>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (int[] arr in result)
-            {
-                foreach (int i in arr)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadArrayOfImmutableQueueT()
-        {
-            ImmutableQueue<int>[] result = JsonSerializer.Deserialize<ImmutableQueue<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableQueue<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveImmutableQueueT()
-        {
-            ImmutableQueue<int> result = JsonSerializer.Deserialize<ImmutableQueue<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<ImmutableQueue<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadArrayOfIImmutableSortedSetT()
-        {
-            ImmutableSortedSet<int>[] result = JsonSerializer.Deserialize<ImmutableSortedSet<int>[]>(Encoding.UTF8.GetBytes(@"[[1,2],[3,4]]"));
-            int expected = 1;
-
-            foreach (ImmutableSortedSet<int> l in result)
-            {
-                foreach (int i in l)
-                {
-                    Assert.Equal(expected++, i);
-                }
-            }
-        }
-
-        [Fact]
-        public static void ReadPrimitiveImmutableSortedSetT()
-        {
-            ImmutableSortedSet<int> result = JsonSerializer.Deserialize<ImmutableSortedSet<int>>(Encoding.UTF8.GetBytes(@"[1,2]"));
-            int expected = 1;
-
-            foreach (int i in result)
-            {
-                Assert.Equal(expected++, i);
-            }
-
-            result = JsonSerializer.Deserialize<ImmutableSortedSet<int>>(Encoding.UTF8.GetBytes(@"[]"));
-            Assert.Equal(0, result.Count());
-        }
-
-        [Fact]
-        public static void ReadSimpleTestClass_ImmutableCollectionWrappers_Throws()
-        {
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<SimpleTestClassWithIImmutableDictionaryWrapper>(SimpleTestClassWithIImmutableDictionaryWrapper.s_json));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<SimpleTestClassWithImmutableListWrapper>(SimpleTestClassWithImmutableListWrapper.s_json));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<SimpleTestClassWithImmutableStackWrapper>(SimpleTestClassWithImmutableStackWrapper.s_json));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<SimpleTestClassWithImmutableQueueWrapper>(SimpleTestClassWithImmutableQueueWrapper.s_json));
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<SimpleTestClassWithImmutableSetWrapper>(SimpleTestClassWithImmutableSetWrapper.s_json));
-        }
-    }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.ObjectModel.Read.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.ObjectModel.Read.cs
deleted file mode 100644 (file)
index a89c84a..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.ObjectModel;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void Read_ObjectModelCollection()
-        {
-            Collection<bool> c = JsonSerializer.Deserialize<Collection<bool>>("[true,false]");
-            Assert.Equal(2, c.Count);
-            Assert.True(c[0]);
-            Assert.False(c[1]);
-
-            // Regression test for https://github.com/dotnet/runtime/issues/30686.
-            ObservableCollection<bool> oc = JsonSerializer.Deserialize<ObservableCollection<bool>>("[true,false]");
-            Assert.Equal(2, oc.Count);
-            Assert.True(oc[0]);
-            Assert.False(oc[1]);
-
-            SimpleKeyedCollection kc = JsonSerializer.Deserialize<SimpleKeyedCollection>("[true]");
-            Assert.Equal(1, kc.Count);
-            Assert.True(kc[0]);
-        }
-
-        [Fact]
-        public static void Read_ObjectModelCollection_Throws()
-        {
-            // No default constructor.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<ReadOnlyCollection<bool>>("[true,false]"));
-            // No default constructor.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<ReadOnlyObservableCollection<bool>>("[true,false]"));
-            // No default constructor.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<ReadOnlyDictionary<string, bool>>(@"{""true"":false}"));
-
-            // Abstract types can't be instantiated. This means there's no default constructor, so the type is not supported for deserialization.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<KeyedCollection<string, bool>>("[true]"));
-        }
-
-        public class SimpleKeyedCollection : KeyedCollection<string, bool>
-        {
-            protected override string GetKeyForItem(bool item)
-            {
-                return item.ToString();
-            }
-        }
-    }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Read.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Read.cs
deleted file mode 100644 (file)
index d4566de..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Specialized;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void Read_SpecializedCollection()
-        {
-            BitVector32 bv32 = JsonSerializer.Deserialize<BitVector32>(@"{""Data"":4}");
-            // Data property is skipped because it doesn't have a setter.
-            Assert.Equal(0, bv32.Data);
-
-            HybridDictionary hd = JsonSerializer.Deserialize<HybridDictionary>(@"{""key"":""value""}");
-            Assert.Equal(1, hd.Count);
-            Assert.Equal("value", ((JsonElement)hd["key"]).GetString());
-
-            IOrderedDictionary iod = JsonSerializer.Deserialize<OrderedDictionary>(@"{""key"":""value""}");
-            Assert.Equal(1, iod.Count);
-            Assert.Equal("value", ((JsonElement)iod["key"]).GetString());
-
-            ListDictionary ld = JsonSerializer.Deserialize<ListDictionary>(@"{""key"":""value""}");
-            Assert.Equal(1, ld.Count);
-            Assert.Equal("value", ((JsonElement)ld["key"]).GetString());
-        }
-
-        [Fact]
-        public static void Read_SpecializedCollection_Throws()
-        {
-            // Add method for this collection only accepts strings, even though it only implements IList which usually
-            // indicates that the element type is typeof(object).
-            Assert.Throws<InvalidCastException>(() => JsonSerializer.Deserialize<StringCollection>(@"[""1"", ""2""]"));
-
-            // Not supported. Not IList, and we don't detect the add method for this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<StringDictionary>(@"[{""Key"": ""key"",""Value"":""value""}]"));
-
-            // Int key is not allowed.
-            Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<HybridDictionary>(@"{1:""value""}"));
-
-            // Runtime type in this case is IOrderedDictionary (we don't replace with concrete type), which we can't instantiate.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<IOrderedDictionary>(@"{""first"":""John"",""second"":""Jane"",""third"":""Jet""}"));
-
-            // Not supported. Not IList, and we don't detect the add method for this collection.
-            Assert.Throws<NotSupportedException>(() => JsonSerializer.Deserialize<NameValueCollection>(@"[""NameValueCollection""]"));
-        }
-    }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Write.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CollectionTests/CollectionTests.Specialized.Write.cs
deleted file mode 100644 (file)
index 0bc2181..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Specialized;
-using Xunit;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    public static partial class CollectionTests
-    {
-        [Fact]
-        public static void Write_SpecializedCollection()
-        {
-            Assert.Equal(@"{""Data"":4}", JsonSerializer.Serialize(new BitVector32(4)));
-            Assert.Equal(@"{""Data"":4}", JsonSerializer.Serialize<object>(new BitVector32(4)));
-
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize(new HybridDictionary { ["key"] = "value" }));
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize<object>(new HybridDictionary { ["key"] = "value" }));
-
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize(new OrderedDictionary { ["key"] = "value" }));
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize<IOrderedDictionary>(new OrderedDictionary { ["key"] = "value" }));
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize<object>(new OrderedDictionary { ["key"] = "value" }));
-
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize(new ListDictionary { ["key"] = "value" }));
-            Assert.Equal(@"{""key"":""value""}", JsonSerializer.Serialize<object>(new ListDictionary { ["key"] = "value" }));
-
-            Assert.Equal(@"[""1"",""2""]", JsonSerializer.Serialize(new StringCollection { "1", "2" }));
-            Assert.Equal(@"[""1"",""2""]", JsonSerializer.Serialize<object>(new StringCollection { "1", "2" }));
-
-            Assert.Equal(@"[{""Key"":""key"",""Value"":""value""}]", JsonSerializer.Serialize(new StringDictionary { ["key"] = "value" }));
-            Assert.Equal(@"[{""Key"":""key"",""Value"":""value""}]", JsonSerializer.Serialize<object>(new StringDictionary { ["key"] = "value" }));
-
-            // Element type returned by .GetEnumerator for this type is string, specifically the key.
-            Assert.Equal(@"[""key""]", JsonSerializer.Serialize(new NameValueCollection { ["key"] = "value" }));
-        }
-    }
-}
@@ -10,19 +10,12 @@ namespace System.Text.Json.Serialization.Tests
     /// <summary>
     /// Base class for wrapping Stream-based JsonSerializer methods which allows tests to run under different configurations.
     /// </summary>
-    public abstract class JsonSerializationWrapperForStream
+    public abstract partial class JsonSerializerWrapperForStream
     {
-        public static JsonSerializationWrapperForStream AsyncStreamSerializer => new AsyncStreamSerializerWrapper();
-        public static JsonSerializationWrapperForStream SyncStreamSerializer => new SyncStreamSerializerWrapper();
+        public static JsonSerializerWrapperForStream AsyncStreamSerializer => new AsyncStreamSerializerWrapper();
+        public static JsonSerializerWrapperForStream SyncStreamSerializer => new SyncStreamSerializerWrapper();
 
-        protected internal abstract Task SerializeWrapper<T>(Stream stream, T value, JsonSerializerOptions options = null);
-        protected internal abstract Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerOptions options = null);
-        protected internal abstract Task SerializeWrapper<T>(Stream stream, T value, JsonTypeInfo<T> jsonTypeInfo);
-        protected internal abstract Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonSerializerOptions options = null);
-        protected internal abstract Task<object> DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions options = null);
-        protected internal abstract Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonTypeInfo<T> jsonTypeInfo);
-
-        private class AsyncStreamSerializerWrapper : JsonSerializationWrapperForStream
+        private class AsyncStreamSerializerWrapper : JsonSerializerWrapperForStream
         {
             protected internal override async Task SerializeWrapper<T>(Stream utf8Json, T value, JsonSerializerOptions options = null)
             {
@@ -55,7 +48,7 @@ namespace System.Text.Json.Serialization.Tests
             }
         }
 
-        private class SyncStreamSerializerWrapper : JsonSerializationWrapperForStream
+        private class SyncStreamSerializerWrapper : JsonSerializerWrapperForStream
         {
             protected internal override Task SerializeWrapper<T>(Stream stream, T value, JsonSerializerOptions options = null)
             {
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapperForString_Dynamic.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapperForString_Dynamic.cs
deleted file mode 100644 (file)
index aaee9f0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Text.Json.Serialization.Metadata;
-using System.Threading.Tasks;
-
-namespace System.Text.Json.Serialization.Tests
-{
-    internal sealed class JsonSerializerWrapperForString_Dynamic
-        : JsonSerializerWrapperForString
-    {
-        protected internal override Task<T> DeserializeWrapper<T>(string json, JsonSerializerOptions options = null)
-            => Task.FromResult(JsonSerializer.Deserialize<T>(json, options));
-
-        protected internal override Task<object> DeserializeWrapper(string json, Type type, JsonSerializerOptions options = null)
-            => Task.FromResult(JsonSerializer.Deserialize(json, type,  options));
-
-        protected internal override Task<T> DeserializeWrapper<T>(string json, JsonTypeInfo<T> jsonTypeInfo) => throw new NotImplementedException();
-
-        protected internal override Task<object> DeserializeWrapper(string json, Type type, JsonSerializerContext context) => throw new NotImplementedException();
-
-        protected internal override Task<string> SerializeWrapper(object value, Type inputType, JsonSerializerOptions options = null)
-            => Task.FromResult(JsonSerializer.Serialize(value, inputType, options));
-
-        protected internal override Task<string> SerializeWrapper<T>(T value, JsonSerializerOptions options = null)
-            => Task.FromResult(JsonSerializer.Serialize<T>(value, options));
-
-        protected internal override Task<string> SerializeWrapper(object value, Type inputType, JsonSerializerContext context) => throw new NotImplementedException();
-
-        protected internal override Task<string> SerializeWrapper<T>(T value, JsonTypeInfo<T> jsonTypeInfo) => throw new NotImplementedException();
-    }
-}
index 8a6535c..33f4f5f 100644 (file)
@@ -576,22 +576,6 @@ namespace System.Text.Json.Serialization.Tests
         public int MyObject { get; set; }
     }
 
-    public class UppercaseNamingPolicy : JsonNamingPolicy
-    {
-        public override string ConvertName(string name)
-        {
-            return name.ToUpperInvariant();
-        }
-    }
-
-    public class NullNamingPolicy : JsonNamingPolicy
-    {
-        public override string ConvertName(string name)
-        {
-            return null;
-        }
-    }
-
     public class EmptyClassWithExtensionProperty
     {
         [JsonExtensionData]
index 85a36e9..71b8830 100644 (file)
@@ -1,12 +1,10 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using Xunit;
-
 namespace System.Text.Json.Serialization.Tests
 {
     public sealed partial class PropertyVisibilityTestsDynamic : PropertyVisibilityTests
     {
-        public PropertyVisibilityTestsDynamic() : base(new JsonSerializerWrapperForString_Dynamic()) { }
+        public PropertyVisibilityTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer) { }
     }
 }
index 91d8f7a..b5fa253 100644 (file)
@@ -5,7 +5,6 @@ using System.Collections;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Collections.Immutable;
-using System.Collections.ObjectModel;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
index 5f458db..7d448fa 100644 (file)
@@ -7,7 +7,7 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Xunit;
-using Utf8MemoryStream = System.Text.Json.Tests.Serialization.CollectionTests.Utf8MemoryStream;
+using Utf8MemoryStream = System.Text.Json.Serialization.Tests.CollectionTests.Utf8MemoryStream;
 
 namespace System.Text.Json.Serialization.Tests
 {
index fc85e18..858ecec 100644 (file)
@@ -5,12 +5,12 @@ namespace System.Text.Json.Serialization.Tests
 {
     public sealed class StreamTests_Async : StreamTests
     {
-        public StreamTests_Async() : base(JsonSerializationWrapperForStream.AsyncStreamSerializer) { }
+        public StreamTests_Async() : base(JsonSerializerWrapperForStream.AsyncStreamSerializer) { }
     }
 
     public sealed class StreamTests_Sync : StreamTests
     {
-        public StreamTests_Sync() : base(JsonSerializationWrapperForStream.SyncStreamSerializer) { }
+        public StreamTests_Sync() : base(JsonSerializerWrapperForStream.SyncStreamSerializer) { }
     }
 
     public abstract partial class StreamTests
@@ -18,9 +18,9 @@ namespace System.Text.Json.Serialization.Tests
         /// <summary>
         /// Wrapper for JsonSerializer's Serialize() and Deserialize() methods.
         /// </summary>
-        private JsonSerializationWrapperForStream Serializer { get; }
+        private JsonSerializerWrapperForStream Serializer { get; }
 
-        public StreamTests(JsonSerializationWrapperForStream serializer)
+        public StreamTests(JsonSerializerWrapperForStream serializer)
         {
             Serializer = serializer;
         }
index 9e11763..d3feb54 100644 (file)
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="$(CommonTestPath)System\IO\WrappedMemoryStream.cs" Link="CommonTest\System\IO\WrappedMemoryStream.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.AsyncEnumerable.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.AsyncEnumerable.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Concurrent.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Concurrent.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.KeyPolicy.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.KeyPolicy.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Dictionary.NonStringKey.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Dictionary.NonStringKey.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Generic.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Generic.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Generic.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Generic.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Immutable.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Immutable.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.KeyValuePair.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.KeyValuePair.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.NonGeneric.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.NonGeneric.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.NonGeneric.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.NonGeneric.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.ObjectModel.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.ObjectModel.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.ObjectModel.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.ObjectModel.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Specialized.Read.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Specialized.Read.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Specialized.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Specialized.Write.cs" />
+    <Compile Include="..\Common\CollectionTests\CollectionTests.Immutable.Write.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\CollectionTests\CollectionTests.Immutable.Write.cs" />
+    <Compile Include="..\Common\JsonSerializerWrapperForStream.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForStream.cs" />
     <Compile Include="..\Common\JsonSerializerWrapperForString.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForString.cs" />
     <Compile Include="..\Common\JsonTestHelper.cs" Link="CommonTest\System\Text\Json\JsonTestHelper.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.cs" />
     <Compile Include="Serialization\Array.WriteTests.cs" />
     <Compile Include="Serialization\CacheTests.cs" />
     <Compile Include="Serialization\CamelCaseUnitTests.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.AsyncEnumerable.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Concurrent.Write.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Concurrent.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Dictionary.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Dictionary.KeyPolicy.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Dictionary.NonStringKey.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Generic.Read.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Generic.Write.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Immutable.Read.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.KeyValuePair.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.NonGeneric.Read.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.NonGeneric.Write.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.ObjectModel.Read.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.ObjectModel.Write.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Specialized.Read.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Specialized.Write.cs" />
-    <Compile Include="Serialization\CollectionTests\CollectionTests.Immutable.Write.cs" />
+    <Compile Include="Serialization\CollectionTests.cs" />
     <Compile Include="Serialization\ConstructorTests\ConstructorTests.AttributePresence.cs" />
     <Compile Include="Serialization\ConstructorTests\ConstructorTests.Cache.cs" />
     <Compile Include="Serialization\ConstructorTests\ConstructorTests.Exceptions.cs" />
     <Compile Include="Serialization\InvalidTypeTests.cs" />
     <Compile Include="Serialization\JsonDocumentTests.cs" />
     <Compile Include="Serialization\JsonElementTests.cs" />
-    <Compile Include="Serialization\JsonSerializerWrapperForString_Dynamic.cs" />
+    <Compile Include="Serialization\JsonSerializerWrapperForStream.cs" />
     <Compile Include="Serialization\JsonSerializerWrapperForString.cs" />
-    <Compile Include="Serialization\JsonSerializationWrapperForStream.cs" />
     <Compile Include="Serialization\MetadataTests\JsonContext\DateTimeOffset.cs" />
     <Compile Include="Serialization\MetadataTests\JsonContext\Dictionary.cs" />
     <Compile Include="Serialization\MetadataTests\JsonContext\HighLowTemps.cs" />