From 583a3a4d0c2b3ea2f1f2127ece0178ce9809d54f Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Tue, 2 Aug 2022 17:12:19 +0100 Subject: [PATCH 1/2] Makes a couple of changes on unsupported types: * Add runtime detection for constructor parameters with missing names. Fix #58690. * Extend NotSupportedTypeConverter to MemberInfo types from System.Type types. Contributes to #58947. --- .../gen/JsonSourceGenerator.Parser.cs | 14 +- .../gen/Reflection/TypeWrapper.cs | 16 +- .../src/Resources/Strings.resx | 3 + .../Value/UnsupportedTypeConverterFactory.cs | 4 +- .../Metadata/ReflectionJsonTypeInfoOfT.cs | 16 +- .../Text/Json/ThrowHelper.Serialization.cs | 7 + .../tests/Common/UnsupportedTypesTests.cs | 194 ++++++++++-------- .../Serialization/UnsupportedTypesTests.cs | 15 +- 8 files changed, 151 insertions(+), 118 deletions(-) diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index b1fe30e7f4acee..3718cc53c4186c 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -101,7 +101,7 @@ private sealed class Parser // Unsupported types private readonly Type _delegateType; - private readonly Type _typeType; + private readonly Type _memberInfoType; private readonly Type _serializationInfoType; private readonly Type _intPtrType; private readonly Type _uIntPtrType; @@ -232,15 +232,15 @@ public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGene _jsonObjectType = _metadataLoadContext.Resolve(JsonObjectFullName); _jsonValueType = _metadataLoadContext.Resolve(JsonValueFullName); _jsonDocumentType = _metadataLoadContext.Resolve(JsonDocumentFullName); + _dateOnlyType = _metadataLoadContext.Resolve(DateOnlyFullName); + _timeOnlyType = _metadataLoadContext.Resolve(TimeOnlyFullName); // Unsupported types. _delegateType = _metadataLoadContext.Resolve(SpecialType.System_Delegate); - _typeType = _metadataLoadContext.Resolve(typeof(Type)); + _memberInfoType = _metadataLoadContext.Resolve(typeof(MemberInfo)); _serializationInfoType = _metadataLoadContext.Resolve(typeof(Runtime.Serialization.SerializationInfo)); _intPtrType = _metadataLoadContext.Resolve(typeof(IntPtr)); _uIntPtrType = _metadataLoadContext.Resolve(typeof(UIntPtr)); - _dateOnlyType = _metadataLoadContext.Resolve(DateOnlyFullName); - _timeOnlyType = _metadataLoadContext.Resolve(TimeOnlyFullName); _jsonConverterOfTType = _metadataLoadContext.Resolve(JsonConverterOfTFullName); @@ -960,7 +960,10 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener } } } - else if (_knownUnsupportedTypes.Contains(type) || _delegateType.IsAssignableFrom(type)) + else if ( + _knownUnsupportedTypes.Contains(type) || + _memberInfoType.IsAssignableFrom(type) || + _delegateType.IsAssignableFrom(type)) { classType = ClassType.KnownUnsupportedType; } @@ -1590,7 +1593,6 @@ private void PopulateKnownTypes() AddTypeIfNotNull(_knownTypes, _jsonValueType); AddTypeIfNotNull(_knownTypes, _jsonDocumentType); - _knownUnsupportedTypes.Add(_typeType); _knownUnsupportedTypes.Add(_serializationInfoType); _knownUnsupportedTypes.Add(_intPtrType); _knownUnsupportedTypes.Add(_uIntPtrType); diff --git a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs index 92dd222a5fecab..c34339e6ca153c 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs @@ -595,17 +595,11 @@ protected override bool IsPrimitiveImpl() public override bool IsAssignableFrom(Type c) { - if (c is TypeWrapper tr) - { - return tr._typeSymbol.AllInterfaces.Contains(_typeSymbol, SymbolEqualityComparer.Default) || - (tr._namedTypeSymbol != null && tr._namedTypeSymbol.BaseTypes().Contains(_typeSymbol, SymbolEqualityComparer.Default)); - } - else if (_metadataLoadContext.Resolve(c) is TypeWrapper trr) - { - return trr._typeSymbol.AllInterfaces.Contains(_typeSymbol, SymbolEqualityComparer.Default) || - (trr._namedTypeSymbol != null && trr._namedTypeSymbol.BaseTypes().Contains(_typeSymbol, SymbolEqualityComparer.Default)); - } - return false; + TypeWrapper? tr = c as TypeWrapper ?? _metadataLoadContext.Resolve(c) as TypeWrapper; + + return tr is not null && + (tr._typeSymbol.AllInterfaces.Contains(_typeSymbol, SymbolEqualityComparer.Default) || + (tr._namedTypeSymbol != null && tr._namedTypeSymbol.BaseTypes().Contains(_typeSymbol, SymbolEqualityComparer.Default))); } #pragma warning disable RS1024 // Compare symbols correctly diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 01d0af8f556137..46477c7f34e4f9 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -518,6 +518,9 @@ The collection type '{0}' is abstract, an interface, or is read only, and could not be instantiated and populated. + + The deserialization constructor for type '{0}' contains parameters with null names. This might happen because the parameter names have been trimmed by the linker. Consider using the source generated serializer instead. + 'IgnoreNullValues' and 'DefaultIgnoreCondition' cannot both be set to non-default values. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs index 6265bec854fd75..cc39341a9c0a73 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs @@ -15,8 +15,8 @@ public override bool CanConvert(Type type) // If a type is added, also add to the SourceGeneration project. return - // There's no safe way to construct a Type from untrusted user input. - typeof(Type).IsAssignableFrom(type) || + // There's no safe way to construct a Type/MemberInfo from untrusted user input. + typeof(MemberInfo).IsAssignableFrom(type) || // (De)serialization of SerializationInfo is already disallowed due to Type being disallowed // (the two ctors on SerializationInfo take a Type, and a Type member is present when serializing). // Explicitly disallowing this type provides a clear exception when ctors with diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs index f176e154011b85..eff6067051f942 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs @@ -230,12 +230,8 @@ private static bool PropertyIsOverriddenAndIgnored( internal override JsonParameterInfoValues[] GetParameterInfoValues() { - ParameterInfo[] parameters = Converter.ConstructorInfo!.GetParameters(); - return GetParameterInfoArray(parameters); - } - - private static JsonParameterInfoValues[] GetParameterInfoArray(ParameterInfo[] parameters) - { + Debug.Assert(Converter.ConstructorInfo != null); + ParameterInfo[] parameters = Converter.ConstructorInfo.GetParameters(); int parameterCount = parameters.Length; JsonParameterInfoValues[] jsonParameters = new JsonParameterInfoValues[parameterCount]; @@ -243,9 +239,15 @@ private static JsonParameterInfoValues[] GetParameterInfoArray(ParameterInfo[] p { ParameterInfo reflectionInfo = parameters[i]; + if (reflectionInfo.Name is null) + { + Debug.Assert(Converter.ConstructorInfo.DeclaringType != null); + ThrowHelper.ThrowNotSupportedException_BaseConverterDoesNotSupportMetadata(Converter.ConstructorInfo.DeclaringType); + } + JsonParameterInfoValues jsonInfo = new() { - Name = reflectionInfo.Name!, + Name = reflectionInfo.Name, ParameterType = reflectionInfo.ParameterType, Position = reflectionInfo.Position, HasDefaultValue = reflectionInfo.HasDefaultValue, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 22d33955c81299..cd8c980162129c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -709,6 +709,13 @@ public static void ThrowNotSupportedException_NoMetadataForType(Type type, IJson throw new NotSupportedException(SR.Format(SR.NoMetadataForType, type, resolver?.GetType().FullName ?? "")); } + + [DoesNotReturn] + public static void ThrowNotSupportedException_ConstructorContainsNullParameterNames(Type declaringType) + { + throw new NotSupportedException(SR.Format(SR.ConstructorContainsNullParameterNames, declaringType)); + } + [DoesNotReturn] public static void ThrowInvalidOperationException_NoMetadataForType(Type type, IJsonTypeInfoResolver? resolver) { diff --git a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs index 738f3397bcdf99..9b3671437a0c46 100644 --- a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; @@ -20,110 +21,117 @@ public UnsupportedTypesTests( SupportsJsonPathOnSerialize = supportsJsonPathOnSerialize; } - [Fact] - public async Task DeserializeUnsupportedType() + [Theory] + [MemberData(nameof(GetUnsupportedValues))] + public async Task DeserializeUnsupportedType(ValueWrapper wrapper) { - // Any test payload is fine. - string json = @"""Some string"""; + _ = wrapper; // only used to instantiate T - await RunTest(json); - await RunTest(json); - await RunTest(json); - await RunTest(json); // One nullable variation. - await RunTest(json); + string json = @"""Some string"""; // Any test payload is fine. - async Task RunTest(string json) - { - Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); - string fullName = type.FullName; + Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); + string fullName = type.FullName; - NotSupportedException ex = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json)); - string exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$", exAsStr); + NotSupportedException ex = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper(json)); + string exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$", exAsStr); - json = $@"{{""Prop"":{json}}}"; + json = $@"{{""Prop"":{json}}}"; - ex = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>(json)); - exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$.Prop", exAsStr); + ex = await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>(json)); + exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$.Prop", exAsStr); - // Verify Nullable<> semantics. NSE is not thrown because the serializer handles null. - if (isNullableOfT) - { - Assert.Null(JsonSerializer.Deserialize("null")); + // Verify Nullable<> semantics. NSE is not thrown because the serializer handles null. + if (isNullableOfT) + { + Assert.Null(JsonSerializer.Deserialize("null")); - json = $@"{{""Prop"":null}}"; - ClassWithType obj = await Serializer.DeserializeWrapper>(json); - Assert.Null(obj.Prop); - } + json = $@"{{""Prop"":null}}"; + ClassWithType obj = await Serializer.DeserializeWrapper>(json); + Assert.Null(obj.Prop); } } - [Fact] - public async Task SerializeUnsupportedType() + [Theory] + [MemberData(nameof(GetUnsupportedValues))] + public async Task SerializeUnsupportedType(ValueWrapper wrapper) { - // TODO refactor to Xunit theory - await RunTest(typeof(int)); - await RunTest(new SerializationInfo(typeof(Type), new FormatterConverter())); - await RunTest((IntPtr)123); - await RunTest(new IntPtr(123)); // One nullable variation. - await RunTest((UIntPtr)123); - - async Task RunTest(T value) + T value = wrapper.value; + + Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); + string fullName = type.FullName; + + NotSupportedException ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(value)); + string exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$", exAsStr); + + ClassWithType obj = new ClassWithType { Prop = value }; + ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(obj)); + exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + + if (SupportsJsonPathOnSerialize) + { + Assert.Contains("$.Prop", exAsStr); + } + else { - Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); - string fullName = type.FullName; - - NotSupportedException ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(value)); - string exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$", exAsStr); - - ClassWithType obj = new ClassWithType { Prop = value }; - ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(obj)); - exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - - if (SupportsJsonPathOnSerialize) - { - Assert.Contains("$.Prop", exAsStr); - } - else - { - Assert.Contains("$.", exAsStr); - Assert.DoesNotContain("$.Prop", exAsStr); - } - - // Verify null semantics. NSE is not thrown because the serializer handles null. - if (!type.IsValueType || isNullableOfT) - { - string serialized = await Serializer.SerializeWrapper((T)(object)null); - Assert.Equal("null", serialized); - - obj.Prop = (T)(object)null; - serialized = await Serializer.SerializeWrapper(obj); - Assert.Equal(@"{""Prop"":null}", serialized); - - serialized = await Serializer.SerializeWrapper(obj, new JsonSerializerOptions { IgnoreNullValues = true }); - Assert.Equal(@"{}", serialized); - } + Assert.Contains("$.", exAsStr); + Assert.DoesNotContain("$.Prop", exAsStr); + } + + // Verify null semantics. NSE is not thrown because the serializer handles null. + if (!type.IsValueType || isNullableOfT) + { + string serialized = await Serializer.SerializeWrapper((T)(object)null); + Assert.Equal("null", serialized); + + obj.Prop = (T)(object)null; + serialized = await Serializer.SerializeWrapper(obj); + Assert.Equal(@"{""Prop"":null}", serialized); + + serialized = await Serializer.SerializeWrapper(obj, new JsonSerializerOptions { IgnoreNullValues = true }); + Assert.Equal(@"{}", serialized); + } #if !BUILDING_SOURCE_GENERATOR_TESTS - Type runtimeType = GetNullableOfTUnderlyingType(value.GetType(), out bool _); + Type runtimeType = GetNullableOfTUnderlyingType(value.GetType(), out bool _); - ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(value)); - exAsStr = ex.ToString(); - Assert.Contains(runtimeType.FullName, exAsStr); - Assert.Contains("$", exAsStr); + ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(value)); + exAsStr = ex.ToString(); + Assert.Contains(runtimeType.FullName, exAsStr); + Assert.Contains("$", exAsStr); - ClassWithType polyObj = new ClassWithType { Prop = value }; - ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(polyObj)); - exAsStr = ex.ToString(); - Assert.Contains(runtimeType.FullName, exAsStr); + ClassWithType polyObj = new ClassWithType { Prop = value }; + ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(polyObj)); + exAsStr = ex.ToString(); + Assert.Contains(runtimeType.FullName, exAsStr); #endif - } + } + + public static IEnumerable GetUnsupportedValues() + { + yield return WrapArgs(typeof(int)); + yield return WrapArgs(typeof(ClassWithExtensionProperty).GetConstructor(Array.Empty())); + yield return WrapArgs(typeof(ClassWithExtensionProperty).GetProperty(nameof(ClassWithExtensionProperty.MyInt))); + yield return WrapArgs(new SerializationInfo(typeof(Type), new FormatterConverter())); + yield return WrapArgs((IntPtr)123); + yield return WrapArgs(new IntPtr(123)); // One nullable variation. + yield return WrapArgs((UIntPtr)123); + + static object[] WrapArgs(T value) => new object[] { new ValueWrapper(value) }; + } + + // Helper record used to path both value & type information to generic theories. + // This is needed e.g. when passing System.Type instances whose runtime type + // actually is System.Reflection.RuntimeType. + public record ValueWrapper(T value) + { + public override string ToString() => value.ToString(); } public class ClassWithIntPtr @@ -151,6 +159,20 @@ public override void Write(Utf8JsonWriter writer, IntPtr value, JsonSerializerOp } } +#if !BUILDING_SOURCE_GENERATOR_TESTS + [Fact] + public async Task TypeWithNullConstructorParameterName_ThrowsNotSupportedException() + { + // Regression test for https://github.com/dotnet/runtime/issues/58690 + Type type = Assembly.GetExecutingAssembly().GetType("System.Runtime.CompilerServices.NullableContextAttribute")!; + object value = Activator.CreateInstance(type, (byte)0)!; + Assert.NotNull(value); + + await Assert.ThrowsAnyAsync(() => Serializer.SerializeWrapper(value)); + await Assert.ThrowsAnyAsync(() => Serializer.DeserializeWrapper("{}", type)); + } +#endif + [Fact] public async Task RuntimeConverterIsSupported_IntPtr() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs index 6483a5e7b3d75b..c54ad186086bbf 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using System.Runtime.Serialization; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Tests; @@ -25,6 +26,10 @@ public UnsupportedTypesTests_Metadata() : base( // Unsupported types: [JsonSerializable(typeof(Type))] [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ConstructorInfo))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(PropertyInfo))] + [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(SerializationInfo))] [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(IntPtr))] @@ -60,6 +65,10 @@ public UnsupportedTypesTests_Default() : base( // Unsupported types: [JsonSerializable(typeof(Type))] [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ConstructorInfo))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(PropertyInfo))] + [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(SerializationInfo))] [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(IntPtr))] @@ -74,12 +83,6 @@ public UnsupportedTypesTests_Default() : base( [JsonSerializable(typeof(ClassThatImplementsIAsyncEnumerable))] [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(ClassWithAsyncEnumerableConverter))] -#if NETCOREAPP - [JsonSerializable(typeof(DateOnly))] - [JsonSerializable(typeof(ClassWithType))] - [JsonSerializable(typeof(TimeOnly))] - [JsonSerializable(typeof(ClassWithType))] -#endif internal sealed partial class UnsupportedTypesTestsContext_Default : JsonSerializerContext { } From adb7d7042d782b37559543a1483b5e4040299016 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 3 Aug 2022 11:43:41 +0100 Subject: [PATCH 2/2] Fix failing test in mono --- .../Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs | 3 ++- .../System.Text.Json/tests/Common/UnsupportedTypesTests.cs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs index eff6067051f942..fbcf67e202786e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/ReflectionJsonTypeInfoOfT.cs @@ -239,7 +239,8 @@ internal override JsonParameterInfoValues[] GetParameterInfoValues() { ParameterInfo reflectionInfo = parameters[i]; - if (reflectionInfo.Name is null) + // Trimmed parameter names are reported as null in CoreCLR or "" in Mono. + if (string.IsNullOrEmpty(reflectionInfo.Name)) { Debug.Assert(Converter.ConstructorInfo.DeclaringType != null); ThrowHelper.ThrowNotSupportedException_BaseConverterDoesNotSupportMetadata(Converter.ConstructorInfo.DeclaringType); diff --git a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs index 9b3671437a0c46..0c4566c529d16e 100644 --- a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs @@ -165,8 +165,9 @@ public async Task TypeWithNullConstructorParameterName_ThrowsNotSupportedExcepti { // Regression test for https://github.com/dotnet/runtime/issues/58690 Type type = Assembly.GetExecutingAssembly().GetType("System.Runtime.CompilerServices.NullableContextAttribute")!; - object value = Activator.CreateInstance(type, (byte)0)!; - Assert.NotNull(value); + ConstructorInfo ctorInfo = type.GetConstructor(new Type[] { typeof(byte) }); + Assert.True(string.IsNullOrEmpty(ctorInfo.GetParameters()[0].Name)); + object value = ctorInfo.Invoke(new object[] { (byte)0 }); await Assert.ThrowsAnyAsync(() => Serializer.SerializeWrapper(value)); await Assert.ThrowsAnyAsync(() => Serializer.DeserializeWrapper("{}", type));