diff --git a/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx b/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx
index f772c16d39646..4cee84fe5e639 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.DataContractSerialization/src/Resources/Strings.resx
@@ -312,6 +312,12 @@
Member '{0}' in type '{1}' cannot have DataMemberAttribute attribute Name set to null or empty string.
+
+ '{0}' is an invalid data node when deserializing extension data.
+
+
+ Type '{0}' in namespace '{1}' is not a valid base type for enum '{2}' in namespace '{3}'.
+
'{0}' in type '{1}' cannot have EnumMemberAttribute attribute Value set to null or empty string.
@@ -624,6 +630,9 @@
Unrecognized Byte Order Mark.
+
+ The maximum nametable character count quota ({0}) has been exceeded while reading XML data. The nametable is a data structure used to store strings encountered during XML processing - long XML documents with non-repeating element names, attribute names and attribute values may trigger this quota. This quota may be increased by changing the MaxNameTableCharCount property on the XmlDictionaryReaderQuotas object used when creating the XML reader.
+
Base64 encoded data expected. Found {0}.
@@ -786,6 +795,9 @@
The maximum array length quota ({0}) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.
+
+ The maximum array length quota ({0}) or the maximum items in object graph quota has been exceeded while reading XML data. These quotas may be increased by changing the MaxArrayLength property on XmlDictionaryReaderQuotas or the MaxItemsInObjectGraph setting.
+
The 'maximum bytes per Read operation' quota ({0}) has been exceeded while reading XML data. Long element start tags (consisting of the element name, attribute names and attribute values) may trigger this quota. This quota may be increased by changing the MaxBytesPerRead property on the XmlDictionaryReaderQuotas object used when creating the XML reader.
@@ -1059,6 +1071,9 @@
DataContract for type '{0}' cannot be added to DataContractSet since type '{1}' with the same data contract name '{2}' in namespace '{3}' is already present and the contracts are not equivalent.
+
+ DataContract name '{0}' from namespace '{1}' does not match the generic name '{2}' from namespace '{3}'.
+
Type '{0}' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types.
@@ -1155,10 +1170,235 @@
'{0}' must be greater than 0.
+
+ {0} The class cannot be deserialized.
+
Collection type '{0}' cannot be deserialized since it
Unknown Type for null value
-
\ No newline at end of file
+
+ List of referenced types contains more than one type with same data contract name. Need to exclude all but one of the following types. Only matching types can be valid references: {0}
+
+
+ List of referenced types contains more than one type with data contract name '{0}' in namespace '{1}'. Need to exclude all but one of the following types. Only matching types can be valid references: {2}
+
+
+ List of referenced collection types contains more than one type with same data contract name. Include only one of the following types. Only matching types can be valid references: {0}
+
+
+ List of referenced collection types contains more than one type with data contract name '{0}' in namespace '{1}'. Include only one of the following types. Only matching types can be valid references: {2}
+
+
+ ReferencedCollectionTypes specified via ImportOptions must contain valid types. Cannot contain null.
+
+
+ (matching)
+
+
+ (not matching)
+
+
+ ReferencedTypes specified via ImportOptions must contain valid types. Cannot contain null.
+
+
+ Using surrogates with get-only collection properties is not supported. Consider removing the surrogate associated with '{0}' or adding a setter to '{1}.{2}'.
+
+
+ The element cannot have 'abstract' set to 'true'.
+
+
+ The type cannot have 'abstract' set to 'true'.
+
+
+ Invalid '{0}' annotation in type '{1}' from namespace '{2}'. Attribute '{3}' not present.
+
+
+ Anonymous type in element '{0}' from namespace '{1}' is not supported.
+
+
+ 'anyAttribute' is not supported.
+
+
+ Form for element '{0}' must be qualified.
+
+
+ Array type '{0}' in namespace '{1}' cannot be imported. {2}
+
+
+ One of its base types, '{0}' from namespace '{1}' is not ISerializable.
+
+
+ A unique name cannot be computed for '{0}' because there are already Int32.MaxValue types of with the same name.
+
+
+ The type contains two attributes with the same name '{0}'. Multiple attributes with the same name in one type are not supported.
+
+
+ The type contains two elements with the same name '{0}'. Multiple elements with the same name in one type are not supported because members marked with DataMemberAttribute attribute must have unique names.
+
+
+ Cannot import invalid schemas. Compilation on the XmlSchemaSet failed.
+
+
+ Cannot import type for null XmlQualifiedName specified via parameter.
+
+
+ Cannot import null XmlSchema contained in XmlSchemaSet specified via parameter.
+
+
+ An internal error has occurred. Could not load serialization schema. Consider providing schema with namespace '{0}'.
+
+
+ Default value on element '{0}' is not supported.
+
+
+ It is not ISerializable but its base type '{0}' in namespace '{1}' is ISerializable.
+
+
+ 'maxOccurs' on element '{0}' must be 1.
+
+
+ 'minOccurs' on element '{0}' must be 0 or 1.
+
+
+ Ref to element '{0}' in '{1}' namespace is not supported.
+
+
+ Enumeration facets without 'value' are not supported.
+
+
+ Anonymous type with <list> cannot be used to create Flags enumeration because it is not a valid enum type.
+
+
+ Simple type list must contain an anonymous type specifying enumeration facets.
+
+
+ Facets other than enumeration facets are not supported.
+
+
+ Anonymous type with <restriction> cannot be used to create Flags enumeration because it is not a valid enum type.
+
+
+ Enum type '{0}' in namespace '{1}' cannot be imported. {2}
+
+
+ Anonymous type with <union>. cannot be used to create Flags enumeration because it is not a valid enum type.
+
+
+ Fixed value on element '{0}' is not supported.
+
+
+ Form on element '{0}' must be qualified.
+
+
+ Annotation for generic type '{0}' did not have attribute '{1}'.
+
+
+ Nested level on annotation elements '{0}' from namespace '{1}' for generic type '{2}' must be in increasing order.
+
+
+ Annotation element '{0}' from namespace '{1}' for generic type '{2}' has an invalid value '{3}' for attribute '{4}'. Expecting value to be of type '{5}'.
+
+
+ Annotation for generic type '{2}' has an invalid element '{0}' from namespace '{1}'.
+
+
+ Annotation '{0}' from namespace '{1}' has an invalid element '{2}' from namespace '{3}'. Expecting text.
+
+
+ Type '{0}' in namespace '{1}' cannot be used as the base type of a data contract type, because it itself does not have a data contract. Consider marking type '{0}' with the DataContractAttribute attribute.
+
+
+ Annotation for element {0} in type {1} from namespace {2} specifies EmitDefaultValue as 'true'. This requires the element to be either nillable or the element's type must be a value type.
+
+
+ Cannot import type '{0}' in namespace '{1}' as its base type because derived type is ISerializable but the base type is not ISerializable.
+
+
+ It is an invalid dictionary type. Element '{0}' must reference a complex type containing a sequence with two required elements. Either fix the schema or remove the IsDictionary annotation.
+
+
+ It is an invalid dictionary type since element '{0}' references a type from a different namespace '{1}'. Either fix the schema or remove the IsDictionary annotation.
+
+
+ '{0}' is an invalid value for IsDictionary annotation. {1}
+
+
+ '{0}' is an invalid value for IsValueType annotation. {1}
+
+
+ Its root sequence contains more than one particle.
+
+
+ Derived ISerializable types cannot contain any particles.
+
+
+ It does not contain root sequence with a wildcard element <any>.
+
+
+ It does not reference attribute '{0}' from namespace '{1}'.
+
+
+ ISerializable type '{0}' in namespace '{1}' cannot be imported. '{2}'
+
+
+ 'maxOccurs' on the wildcard element must be '{0}'.
+
+
+ 'minOccurs' on the wildcard element must be '{0}'.
+
+
+ Namespace on the wildcard element must be '{0}'.
+
+
+ ProcessContents on the wildcard element must be '{0}'.
+
+
+ Complex type with mixed content is not supported.
+
+
+ The root sequence must contain only local elements. Group ref, choice, any and nested sequences are not supported.
+
+
+ Redefine is not supported.
+
+
+ The root particle must be a sequence.
+
+
+ 'maxOccurs' on the root sequence must be 1.
+
+
+ 'minOccurs' on the root sequence must be 1.
+
+
+ Complex types with simple content extension are not supported.
+
+
+ Simple type restriction must specify a base type.
+
+
+ Simple types with <union> content are not supported.
+
+
+ Invalid type specified. Type with name '{0}' not found in schema with namespace '{1}'.
+
+
+ Substitution group on element '{0}' is not supported.
+
+
+ The global element found in the schema with same name references a different type '{0}' in namespace '{1}'. Data contract types must have the same name as their root element name. Consider removing the global element or changing its type.
+
+
+ Type '{0}' in namespace '{1}' cannot be imported. {2}
+
+
+ {0} Either change the schema so that the types can map to data contract types or use ImportXmlType or use a different serializer.
+
+
+ Attributes must be optional and from namespace '{0}'.
+
+
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj b/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj
index f8df7d3599de5..f81bacc216dca 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj
+++ b/src/libraries/System.Private.DataContractSerialization/src/System.Private.DataContractSerialization.csproj
@@ -1,4 +1,4 @@
-
+
$(NetCoreAppCurrent)
$(NoWarn);1634;1691;649
@@ -15,11 +15,11 @@
-
-
+
+
+
+
@@ -29,44 +29,56 @@
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -81,6 +93,7 @@
+
@@ -89,6 +102,7 @@
+
@@ -96,59 +110,42 @@
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -168,6 +165,7 @@
+
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/AccessorBuilder.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/AccessorBuilder.cs
index e6af588406a6d..23f1ea8aeeb70 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/AccessorBuilder.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/AccessorBuilder.cs
@@ -8,6 +8,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
+using System.Runtime.Serialization.DataContracts;
using System.Text;
using System.Threading.Tasks;
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
index 1200e4ee07097..a395b82d6f99f 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs
@@ -2,44 +2,35 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.IO;
using System.Linq;
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Security;
using System.Threading;
using System.Xml;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
-namespace System.Runtime.Serialization
+using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+namespace System.Runtime.Serialization.DataContracts
{
internal sealed class ClassDataContract : DataContract
{
+ internal const string ContractTypeString = nameof(ClassDataContract);
+ public override string? ContractType => ContractTypeString;
+
public XmlDictionaryString[]? ContractNamespaces;
public XmlDictionaryString[]? MemberNames;
- public XmlDictionaryString[]? MemberNamespaces;
+ internal XmlDictionaryString[]? MemberNamespaces;
private XmlDictionaryString?[]? _childElementNamespaces;
private ClassDataContractCriticalHelper _helper;
- private bool _isScriptObject;
-
- internal const DynamicallyAccessedMemberTypes DataContractPreserveMemberTypes =
- DynamicallyAccessedMemberTypes.PublicMethods |
- DynamicallyAccessedMemberTypes.NonPublicMethods |
- DynamicallyAccessedMemberTypes.PublicConstructors |
- DynamicallyAccessedMemberTypes.NonPublicConstructors |
- DynamicallyAccessedMemberTypes.PublicFields |
- DynamicallyAccessedMemberTypes.PublicProperties;
-
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal ClassDataContract(Type type) : base(new ClassDataContractCriticalHelper(type))
{
@@ -56,23 +47,32 @@ private ClassDataContract(Type type, XmlDictionaryString ns, string[] memberName
private void InitClassDataContract()
{
_helper = (base.Helper as ClassDataContractCriticalHelper)!;
- this.ContractNamespaces = _helper.ContractNamespaces;
- this.MemberNames = _helper.MemberNames;
- this.MemberNamespaces = _helper.MemberNamespaces;
- _isScriptObject = _helper.IsScriptObject;
+ ContractNamespaces = _helper.ContractNamespaces;
+ MemberNames = _helper.MemberNames;
+ MemberNamespaces = _helper.MemberNamespaces;
+ }
+
+ public override DataContract? BaseContract
+ {
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get => BaseClassContract;
}
- internal ClassDataContract? BaseContract
+ internal ClassDataContract? BaseClassContract
{
- get { return _helper.BaseContract; }
+ get => _helper.BaseClassContract;
+ set => _helper.BaseClassContract = value;
}
internal List? Members
{
- get { return _helper.Members; }
+ get => _helper.Members;
+ set => _helper.Members = value;
}
- public XmlDictionaryString?[]? ChildElementNamespaces
+ public override ReadOnlyCollection DataMembers => (Members == null) ? DataContract.s_emptyDataMemberList : Members.AsReadOnly();
+
+ internal XmlDictionaryString?[]? ChildElementNamespaces
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
get
@@ -95,95 +95,39 @@ public XmlDictionaryString?[]? ChildElementNamespaces
}
return _childElementNamespaces;
}
- set
- {
- _childElementNamespaces = value;
- }
}
- internal MethodInfo? OnSerializing
- {
- get
- { return _helper.OnSerializing; }
- }
+ internal MethodInfo? OnSerializing => _helper.OnSerializing;
- internal MethodInfo? OnSerialized
- {
- get
- { return _helper.OnSerialized; }
- }
+ internal MethodInfo? OnSerialized => _helper.OnSerialized;
- internal MethodInfo? OnDeserializing
- {
- get
- { return _helper.OnDeserializing; }
- }
+ internal MethodInfo? OnDeserializing => _helper.OnDeserializing;
- internal MethodInfo? OnDeserialized
- {
- get
- { return _helper.OnDeserialized; }
- }
+ internal MethodInfo? OnDeserialized => _helper.OnDeserialized;
- internal MethodInfo? ExtensionDataSetMethod
- {
- get { return _helper.ExtensionDataSetMethod; }
- }
+ internal MethodInfo? ExtensionDataSetMethod => _helper.ExtensionDataSetMethod;
public override DataContractDictionary? KnownDataContracts
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- { return _helper.KnownDataContracts; }
+ get => _helper.KnownDataContracts;
+ internal set => _helper.KnownDataContracts = value;
}
public override bool IsISerializable
{
- get { return _helper.IsISerializable; }
- set { _helper.IsISerializable = value; }
- }
-
- internal bool IsNonAttributedType
- {
- get
- { return _helper.IsNonAttributedType; }
- }
-
- public bool HasExtensionData
- {
- get
- { return _helper.HasExtensionData; }
- set { _helper.HasExtensionData = value; }
+ get => _helper.IsISerializable;
+ internal set => _helper.IsISerializable = value;
}
- [MemberNotNullWhen(true, nameof(KeyValuePairGenericArguments))]
- [MemberNotNullWhen(true, nameof(KeyValuePairAdapterConstructorInfo))]
- [MemberNotNullWhen(true, nameof(GetKeyValuePairMethodInfo))]
- internal bool IsKeyValuePairAdapter
- {
- get
-#pragma warning disable CS8775 // Member must have a non-null value when exiting in some condition.
- { return _helper.IsKeyValuePairAdapter; }
-#pragma warning restore CS8775 // Member must have a non-null value when exiting in some condition.
- }
+ internal bool IsNonAttributedType => _helper.IsNonAttributedType;
- internal Type[]? KeyValuePairGenericArguments
- {
- get
- { return _helper.KeyValuePairGenericArguments; }
- }
+ internal bool HasExtensionData => _helper.HasExtensionData;
- internal ConstructorInfo? KeyValuePairAdapterConstructorInfo
- {
- get
- { return _helper.KeyValuePairAdapterConstructorInfo; }
- }
+ internal string? SerializationExceptionMessage => _helper.SerializationExceptionMessage;
+ internal string? DeserializationExceptionMessage => _helper.DeserializationExceptionMessage;
- internal MethodInfo? GetKeyValuePairMethodInfo
- {
- get
- { return _helper.GetKeyValuePairMethodInfo; }
- }
+ internal bool IsReadOnlyContract => DeserializationExceptionMessage != null;
internal ConstructorInfo? GetISerializableConstructor()
{
@@ -209,7 +153,7 @@ internal MethodInfo? GetKeyValuePairMethodInfo
internal bool CreateNewInstanceViaDefaultConstructor([NotNullWhen(true)] out object? obj)
{
ConstructorInfo? ci = GetNonAttributedTypeConstructor();
- if (ci == null)
+ if (ci == null || UnderlyingType == Globals.TypeOfSchemaDefinedType)
{
obj = null;
return false;
@@ -231,6 +175,7 @@ internal bool CreateNewInstanceViaDefaultConstructor([NotNullWhen(true)] out obj
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private XmlFormatClassWriterDelegate CreateXmlFormatWriterDelegate()
{
+ Debug.Assert(UnderlyingType != Globals.TypeOfSchemaDefinedType);
return new XmlFormatWriterGenerator().GenerateClassWriter(this);
}
@@ -253,14 +198,12 @@ internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate
}
return _helper.XmlFormatWriterDelegate;
}
- set
- {
- }
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private XmlFormatClassReaderDelegate CreateXmlFormatReaderDelegate()
{
+ Debug.Assert(UnderlyingType != Globals.TypeOfSchemaDefinedType);
return new XmlFormatReaderGenerator().GenerateClassReader(this);
}
@@ -275,6 +218,10 @@ internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
{
if (_helper.XmlFormatReaderDelegate == null)
{
+ if (IsReadOnlyContract)
+ {
+ ThrowInvalidDataContractException(DeserializationExceptionMessage, type: null);
+ }
XmlFormatClassReaderDelegate tempDelegate = CreateXmlFormatReaderDelegate();
Interlocked.MemoryBarrier();
_helper.XmlFormatReaderDelegate = tempDelegate;
@@ -283,31 +230,17 @@ internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
}
return _helper.XmlFormatReaderDelegate;
}
- set
- {
- }
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal static ClassDataContract CreateClassDataContractForKeyValue(Type type, XmlDictionaryString ns, string[] memberNames)
{
- ClassDataContract? cdc = (ClassDataContract?)DataContract.GetDataContractFromGeneratedAssembly(type);
- if (cdc == null)
- {
- return new ClassDataContract(type, ns, memberNames);
- }
- else
- {
- ClassDataContract cloned = cdc.Clone();
- cloned.UpdateNamespaceAndMembers(type, ns, memberNames);
- return cloned;
- }
+ return new ClassDataContract(type, ns, memberNames);
}
internal static void CheckAndAddMember(List members, DataMember memberContract, Dictionary memberNamesTable)
{
- DataMember? existingMemberContract;
- if (memberNamesTable.TryGetValue(memberContract.Name, out existingMemberContract))
+ if (memberNamesTable.TryGetValue(memberContract.Name, out DataMember? existingMemberContract))
{
Type declaringType = memberContract.MemberInfo.DeclaringType!;
DataContract.ThrowInvalidDataContractException(
@@ -329,7 +262,7 @@ internal static void CheckAndAddMember(List members, DataMember memb
if (!childType.IsEnum && !Globals.TypeOfIXmlSerializable.IsAssignableFrom(childType)
&& DataContract.GetBuiltInDataContract(childType) == null && childType != Globals.TypeOfDBNull)
{
- string ns = DataContract.GetStableName(childType).Namespace;
+ string ns = DataContract.GetXmlName(childType).Namespace;
if (ns.Length > 0 && ns != dataContract.Namespace.Value)
return dictionary.Add(ns);
}
@@ -370,11 +303,9 @@ internal static bool IsNonAttributedTypeValidForSerialization(
if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false))
return false;
- Type[] interfaceTypes = type.GetInterfaces();
-
if (!IsArraySegment(type))
{
- foreach (Type interfaceType in interfaceTypes)
+ foreach (Type interfaceType in type.GetInterfaces())
{
if (CollectionDataContract.IsCollectionInterface(interfaceType))
return false;
@@ -389,60 +320,15 @@ internal static bool IsNonAttributedTypeValidForSerialization(
if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
return false;
- if (type.IsValueType)
- {
- return type.IsVisible;
- }
- else
- {
- return (type.IsVisible &&
- type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Type.EmptyTypes) != null);
- }
- }
- private static readonly Dictionary s_knownSerializableTypeInfos = new Dictionary {
- { "System.Collections.Generic.KeyValuePair`2", Array.Empty() },
- { "System.Collections.Generic.Queue`1", new[] { "_syncRoot" } },
- { "System.Collections.Generic.Stack`1", new[] {"_syncRoot" } },
- { "System.Collections.ObjectModel.ReadOnlyCollection`1", new[] {"_syncRoot" } },
- { "System.Collections.ObjectModel.ReadOnlyDictionary`2", new[] {"_syncRoot", "_keys", "_values" } },
- { "System.Tuple`1", Array.Empty() },
- { "System.Tuple`2", Array.Empty() },
- { "System.Tuple`3", Array.Empty() },
- { "System.Tuple`4", Array.Empty() },
- { "System.Tuple`5", Array.Empty() },
- { "System.Tuple`6", Array.Empty() },
- { "System.Tuple`7", Array.Empty() },
- { "System.Tuple`8", Array.Empty() },
- { "System.Collections.Queue", new[] {"_syncRoot" } },
- { "System.Collections.Stack", new[] {"_syncRoot" } },
- { "System.Globalization.CultureInfo", Array.Empty() },
- { "System.Version", Array.Empty() },
- };
-
- private static string GetGeneralTypeName(Type type)
- {
- return type.IsGenericType && !type.IsGenericParameter
- ? type.GetGenericTypeDefinition().FullName!
- : type.FullName!;
- }
-
- internal static bool IsKnownSerializableType(Type type)
- {
- // Applies to known types that DCS understands how to serialize/deserialize
- //
- string typeFullName = GetGeneralTypeName(type);
-
- return s_knownSerializableTypeInfos.ContainsKey(typeFullName);
- }
+ if (type == Globals.TypeOfExtensionDataObject)
+ return false;
- internal static bool IsNonSerializedMember(Type type, string memberName)
- {
- string typeFullName = GetGeneralTypeName(type);
+ if (type.IsValueType)
+ return type.IsVisible;
- string[]? members;
- return s_knownSerializableTypeInfos.TryGetValue(typeFullName, out members)
- && members.Contains(memberName);
+ return (type.IsVisible &&
+ type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Type.EmptyTypes) != null);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -452,17 +338,17 @@ internal static bool IsNonSerializedMember(Type type, string memberName)
return null;
XmlDictionaryString?[]? baseChildElementNamespaces = null;
- if (this.BaseContract != null)
- baseChildElementNamespaces = this.BaseContract.ChildElementNamespaces;
+ if (BaseClassContract != null)
+ baseChildElementNamespaces = BaseClassContract.ChildElementNamespaces;
int baseChildElementNamespaceCount = (baseChildElementNamespaces != null) ? baseChildElementNamespaces.Length : 0;
XmlDictionaryString?[] childElementNamespaces = new XmlDictionaryString?[Members.Count + baseChildElementNamespaceCount];
if (baseChildElementNamespaceCount > 0)
Array.Copy(baseChildElementNamespaces!, childElementNamespaces, baseChildElementNamespaces!.Length);
XmlDictionary dictionary = new XmlDictionary();
- for (int i = 0; i < this.Members.Count; i++)
+ for (int i = 0; i < Members.Count; i++)
{
- childElementNamespaces[i + baseChildElementNamespaceCount] = GetChildNamespaceToDeclare(this, this.Members[i].MemberType, dictionary);
+ childElementNamespaces[i + baseChildElementNamespaceCount] = GetChildNamespaceToDeclare(this, Members[i].MemberType, dictionary);
}
return childElementNamespaces;
@@ -474,24 +360,15 @@ private void EnsureMethodsImported()
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
+ internal override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
{
Debug.Assert(context != null);
-
- if (_isScriptObject)
- {
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
- }
XmlFormatWriterDelegate(xmlWriter, obj, context, this);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
+ internal override object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
{
- if (_isScriptObject)
- {
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
- }
xmlReader.Read();
object? o = XmlFormatReaderDelegate(xmlReader, context, MemberNames, MemberNamespaces);
xmlReader.ReadEndElement();
@@ -518,15 +395,24 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
}
return true;
}
- if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForRead(securityException))
+ if (BaseClassContract != null && BaseClassContract.RequiresMemberAccessForRead(securityException))
return true;
- if (ConstructorRequiresMemberAccess(GetNonAttributedTypeConstructor()))
+ if (ConstructorRequiresMemberAccess(GetISerializableConstructor()))
{
- if (Globals.TypeOfScriptObject_IsAssignableFrom(UnderlyingType))
+ if (securityException != null)
{
- return true;
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
+ new SecurityException(SR.Format(
+ SR.PartialTrustIXmlSerialzableNoPublicConstructor,
+ DataContract.GetClrTypeFullName(UnderlyingType)),
+ securityException));
}
+ return true;
+ }
+
+ if (ConstructorRequiresMemberAccess(GetNonAttributedTypeConstructor()))
+ {
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
@@ -538,7 +424,7 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
return true;
}
- if (MethodRequiresMemberAccess(this.OnDeserializing))
+ if (MethodRequiresMemberAccess(OnDeserializing))
{
if (securityException != null)
{
@@ -546,13 +432,13 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustDataContractOnDeserializingNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.OnDeserializing!.Name),
+ OnDeserializing!.Name),
securityException));
}
return true;
}
- if (MethodRequiresMemberAccess(this.OnDeserialized))
+ if (MethodRequiresMemberAccess(OnDeserialized))
{
if (securityException != null)
{
@@ -560,27 +446,27 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustDataContractOnDeserializedNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.OnDeserialized!.Name),
+ OnDeserialized!.Name),
securityException));
}
return true;
}
- if (this.Members != null)
+ if (Members != null)
{
- for (int i = 0; i < this.Members.Count; i++)
+ for (int i = 0; i < Members.Count; i++)
{
- if (this.Members[i].RequiresMemberAccessForSet())
+ if (Members[i].RequiresMemberAccessForSet())
{
if (securityException != null)
{
- if (this.Members[i].MemberInfo is FieldInfo)
+ if (Members[i].MemberInfo is FieldInfo)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(SR.Format(
SR.PartialTrustDataContractFieldSetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.Members[i].MemberInfo.Name),
+ Members[i].MemberInfo.Name),
securityException));
}
else
@@ -589,7 +475,7 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustDataContractPropertySetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.Members[i].MemberInfo.Name),
+ Members[i].MemberInfo.Name),
securityException));
}
}
@@ -623,24 +509,24 @@ internal bool RequiresMemberAccessForWrite(SecurityException? securityException)
return true;
}
- if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForWrite(securityException))
+ if (BaseClassContract != null && BaseClassContract.RequiresMemberAccessForWrite(securityException))
return true;
- if (MethodRequiresMemberAccess(this.OnSerializing))
+ if (MethodRequiresMemberAccess(OnSerializing))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(SR.Format(
SR.PartialTrustDataContractOnSerializingNotPublic,
- DataContract.GetClrTypeFullName(this.UnderlyingType),
- this.OnSerializing!.Name),
+ DataContract.GetClrTypeFullName(UnderlyingType),
+ OnSerializing!.Name),
securityException));
}
return true;
}
- if (MethodRequiresMemberAccess(this.OnSerialized))
+ if (MethodRequiresMemberAccess(OnSerialized))
{
if (securityException != null)
{
@@ -648,27 +534,27 @@ internal bool RequiresMemberAccessForWrite(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustDataContractOnSerializedNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.OnSerialized!.Name),
+ OnSerialized!.Name),
securityException));
}
return true;
}
- if (this.Members != null)
+ if (Members != null)
{
- for (int i = 0; i < this.Members.Count; i++)
+ for (int i = 0; i < Members.Count; i++)
{
- if (this.Members[i].RequiresMemberAccessForGet())
+ if (Members[i].RequiresMemberAccessForGet())
{
if (securityException != null)
{
- if (this.Members[i].MemberInfo is FieldInfo)
+ if (Members[i].MemberInfo is FieldInfo)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(SR.Format(
SR.PartialTrustDataContractFieldGetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.Members[i].MemberInfo.Name),
+ Members[i].MemberInfo.Name),
securityException));
}
else
@@ -677,7 +563,7 @@ internal bool RequiresMemberAccessForWrite(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustDataContractPropertyGetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.Members[i].MemberInfo.Name),
+ Members[i].MemberInfo.Name),
securityException));
}
}
@@ -692,8 +578,6 @@ internal bool RequiresMemberAccessForWrite(SecurityException? securityException)
private sealed class ClassDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private static Type[]? s_serInfoCtorArgs;
- private static readonly MethodInfo s_getKeyValuePairMethod = typeof(KeyValuePairAdapter<,>).GetMethod("GetKeyValuePair", Globals.ScanAllMembers)!;
- private static readonly ConstructorInfo s_ctorGenericMethod = typeof(KeyValuePairAdapter<,>).GetConstructor(Globals.ScanAllMembers, new Type[] { typeof(KeyValuePair<,>).MakeGenericType(typeof(KeyValuePairAdapter<,>).GetGenericArguments()) })!;
private ClassDataContract? _baseContract;
private List? _members;
@@ -701,82 +585,65 @@ private sealed class ClassDataContractCriticalHelper : DataContract.DataContract
private MethodInfo? _onDeserializing, _onDeserialized;
private MethodInfo? _extensionDataSetMethod;
private DataContractDictionary? _knownDataContracts;
- private bool _isISerializable;
+ private string? _serializationExceptionMessage;
private bool _isKnownTypeAttributeChecked;
private bool _isMethodChecked;
+
///
- /// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and hasDataContract
+ /// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and isNonAttributedType
///
private bool _isNonAttributedType;
///
- /// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and isNonAttributedType
+ /// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and hasDataContract
///
private bool _hasDataContract;
private bool _hasExtensionData;
- private readonly bool _isScriptObject;
-
- private XmlDictionaryString?[]? _childElementNamespaces;
- private XmlFormatClassReaderDelegate? _xmlFormatReaderDelegate;
- private XmlFormatClassWriterDelegate? _xmlFormatWriterDelegate;
- public XmlDictionaryString[]? ContractNamespaces;
- public XmlDictionaryString[]? MemberNames;
- public XmlDictionaryString[]? MemberNamespaces;
+ internal XmlDictionaryString[]? ContractNamespaces;
+ internal XmlDictionaryString[]? MemberNames;
+ internal XmlDictionaryString[]? MemberNamespaces;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal ClassDataContractCriticalHelper([DynamicallyAccessedMembers(DataContractPreserveMemberTypes)]
Type type) : base(type)
{
- XmlQualifiedName stableName = GetStableNameAndSetHasDataContract(type);
+ XmlQualifiedName xmlName = GetXmlNameAndSetHasDataContract(type);
if (type == Globals.TypeOfDBNull)
{
- this.StableName = stableName;
+ XmlName = xmlName;
_members = new List();
XmlDictionary dictionary = new XmlDictionary(2);
- this.Name = dictionary.Add(StableName.Name);
- this.Namespace = dictionary.Add(StableName.Namespace);
- this.ContractNamespaces = this.MemberNames = this.MemberNamespaces = Array.Empty();
+ Name = dictionary.Add(XmlName.Name);
+ Namespace = dictionary.Add(XmlName.Namespace);
+ ContractNamespaces = MemberNames = MemberNamespaces = Array.Empty();
EnsureMethodsImported();
return;
}
Type? baseType = type.BaseType;
- _isISerializable = (Globals.TypeOfISerializable.IsAssignableFrom(type));
+ IsISerializable = (Globals.TypeOfISerializable.IsAssignableFrom(type));
SetIsNonAttributedType(type);
- if (_isISerializable)
+ if (IsISerializable)
{
if (HasDataContract)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.ISerializableCannotHaveDataContract, DataContract.GetClrTypeFullName(type))));
if (baseType != null && !(baseType.IsSerializable && Globals.TypeOfISerializable.IsAssignableFrom(baseType)))
baseType = null;
}
- SetKeyValuePairAdapterFlags(type);
- this.IsValueType = type.IsValueType;
+ IsValueType = type.IsValueType;
if (baseType != null && baseType != Globals.TypeOfObject && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri)
{
- // https://github.com/dotnet/corefx/pull/19629:
- // A DataContract created at runtime does not work with the base DataContract pre-generated by SG.
- // It's because the runtime DataContract requires full information of a base DataContract while a
- // pre-generated DataContract is incomplete.
- //
- // At this point in code, we're in the midlle of creating a new DataContract at runtime, so we need to make
- // sure that we create our own base type DataContract when the base type could potentially have SG generated
- // DataContract.
- //
- // We wanted to enable the fix for the issue described above only when SG generated DataContracts are available.
- // Currently we don't have a good way of detecting usage of SG (either globally or per data contract).
-
DataContract baseContract = DataContract.GetDataContract(baseType);
- if (baseContract is CollectionDataContract)
+ if (baseContract is CollectionDataContract collectionDC)
{
- this.BaseContract = ((CollectionDataContract)baseContract).SharedTypeContract as ClassDataContract;
+ BaseClassContract = collectionDC.SharedTypeContract as ClassDataContract;
}
else
{
- this.BaseContract = baseContract as ClassDataContract;
+ BaseClassContract = baseContract as ClassDataContract;
}
- if (this.BaseContract != null && this.BaseContract.IsNonAttributedType && !_isNonAttributedType)
+ if (BaseClassContract != null && BaseClassContract.IsNonAttributedType && !_isNonAttributedType)
{
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError
(new InvalidDataContractException(SR.Format(SR.AttributedTypesCannotInheritFromNonAttributedSerializableTypes,
@@ -785,7 +652,7 @@ internal ClassDataContractCriticalHelper([DynamicallyAccessedMembers(DataContrac
}
else
{
- this.BaseContract = null;
+ BaseClassContract = null;
}
_hasExtensionData = (Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(type));
@@ -794,21 +661,21 @@ internal ClassDataContractCriticalHelper([DynamicallyAccessedMembers(DataContrac
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.OnlyDataContractTypesCanHaveExtensionData, DataContract.GetClrTypeFullName(type))));
}
- if (_isISerializable)
+ if (IsISerializable)
{
- SetDataContractName(stableName);
+ SetDataContractName(xmlName);
}
else
{
- this.StableName = stableName;
+ XmlName = xmlName;
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
- Name = dictionary.Add(StableName.Name);
- Namespace = dictionary.Add(StableName.Namespace);
+ Name = dictionary.Add(XmlName.Name);
+ Namespace = dictionary.Add(XmlName.Namespace);
int baseMemberCount = 0;
int baseContractCount = 0;
- if (BaseContract == null)
+ if (BaseClassContract == null)
{
MemberNames = new XmlDictionaryString[Members.Count];
MemberNamespaces = new XmlDictionaryString[Members.Count];
@@ -816,14 +683,18 @@ internal ClassDataContractCriticalHelper([DynamicallyAccessedMembers(DataContrac
}
else
{
- baseMemberCount = BaseContract.MemberNames!.Length;
+ if (BaseClassContract.IsReadOnlyContract)
+ {
+ _serializationExceptionMessage = BaseClassContract.SerializationExceptionMessage;
+ }
+ baseMemberCount = BaseClassContract.MemberNames!.Length;
MemberNames = new XmlDictionaryString[Members.Count + baseMemberCount];
- Array.Copy(BaseContract.MemberNames, MemberNames, baseMemberCount);
+ Array.Copy(BaseClassContract.MemberNames, MemberNames, baseMemberCount);
MemberNamespaces = new XmlDictionaryString[Members.Count + baseMemberCount];
- Array.Copy(BaseContract.MemberNamespaces!, MemberNamespaces, baseMemberCount);
- baseContractCount = BaseContract.ContractNamespaces!.Length;
+ Array.Copy(BaseClassContract.MemberNamespaces!, MemberNamespaces, baseMemberCount);
+ baseContractCount = BaseClassContract.ContractNamespaces!.Length;
ContractNamespaces = new XmlDictionaryString[1 + baseContractCount];
- Array.Copy(BaseContract.ContractNamespaces, ContractNamespaces, baseContractCount);
+ Array.Copy(BaseClassContract.ContractNamespaces, ContractNamespaces, baseContractCount);
}
ContractNamespaces[baseContractCount] = Namespace;
for (int i = 0; i < Members.Count; i++)
@@ -834,8 +705,6 @@ internal ClassDataContractCriticalHelper([DynamicallyAccessedMembers(DataContrac
}
EnsureMethodsImported();
- _isScriptObject = this.IsNonAttributedType &&
- Globals.TypeOfScriptObject_IsAssignableFrom(this.UnderlyingType);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -843,10 +712,10 @@ internal ClassDataContractCriticalHelper(
[DynamicallyAccessedMembers(DataContractPreserveMemberTypes)]
Type type, XmlDictionaryString ns, string[] memberNames) : base(type)
{
- this.StableName = new XmlQualifiedName(GetStableNameAndSetHasDataContract(type).Name, ns.Value);
+ XmlName = new XmlQualifiedName(GetXmlNameAndSetHasDataContract(type).Name, ns.Value);
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(1 + Members.Count);
- Name = dictionary.Add(StableName.Name);
+ Name = dictionary.Add(XmlName.Name);
Namespace = ns;
ContractNamespaces = new XmlDictionaryString[] { Namespace };
MemberNames = new XmlDictionaryString[Members.Count];
@@ -862,15 +731,14 @@ internal ClassDataContractCriticalHelper(
private void EnsureIsReferenceImported(Type type)
{
- DataContractAttribute? dataContractAttribute;
bool isReference = false;
- bool hasDataContractAttribute = TryGetDCAttribute(type, out dataContractAttribute);
+ bool hasDataContractAttribute = TryGetDCAttribute(type, out DataContractAttribute? dataContractAttribute);
- if (BaseContract != null)
+ if (BaseClassContract != null)
{
if (hasDataContractAttribute && dataContractAttribute!.IsReferenceSetExplicitly)
{
- bool baseIsReference = this.BaseContract.IsReference;
+ bool baseIsReference = BaseClassContract.IsReference;
if ((baseIsReference && !dataContractAttribute.IsReference) ||
(!baseIsReference && dataContractAttribute.IsReference))
{
@@ -878,8 +746,8 @@ private void EnsureIsReferenceImported(Type type)
SR.Format(SR.InconsistentIsReference,
DataContract.GetClrTypeFullName(type),
dataContractAttribute.IsReference,
- DataContract.GetClrTypeFullName(this.BaseContract.UnderlyingType),
- this.BaseContract.IsReference),
+ DataContract.GetClrTypeFullName(BaseClassContract.UnderlyingType),
+ BaseClassContract.IsReference),
type);
}
else
@@ -889,7 +757,7 @@ private void EnsureIsReferenceImported(Type type)
}
else
{
- isReference = this.BaseContract.IsReference;
+ isReference = BaseClassContract.IsReference;
}
}
else if (hasDataContractAttribute)
@@ -909,7 +777,7 @@ private void EnsureIsReferenceImported(Type type)
return;
}
- this.IsReference = isReference;
+ IsReference = isReference;
}
[MemberNotNull(nameof(_members))]
@@ -917,16 +785,14 @@ private void EnsureIsReferenceImported(Type type)
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void ImportDataMembers()
{
- Type type = this.UnderlyingType;
+ Type type = UnderlyingType;
EnsureIsReferenceImported(type);
List tempMembers = new List();
Dictionary memberNamesTable = new Dictionary();
MemberInfo[] memberInfos;
- bool isPodSerializable = !_isNonAttributedType || IsKnownSerializableType(type);
-
- if (!isPodSerializable)
+ if (_isNonAttributedType)
{
memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
}
@@ -960,9 +826,9 @@ private void ImportDataMembers()
ThrowInvalidDataContractException(SR.Format(SR.NoGetMethodForProperty, property.DeclaringType, property.Name));
if (setMethod == null)
{
- if (!SetIfGetOnlyCollection(memberContract))
+ if (!SetIfGetOnlyCollection(memberContract, skipIfReadOnlyContract: false))
{
- ThrowInvalidDataContractException(SR.Format(SR.NoSetMethodForProperty, property.DeclaringType, property.Name));
+ _serializationExceptionMessage = SR.Format(SR.NoSetMethodForProperty, property.DeclaringType, property.Name);
}
}
if (getMethod.GetParameters().Length > 0)
@@ -984,7 +850,7 @@ private void ImportDataMembers()
memberContract.Name = DataContract.EncodeLocalName(memberContract.Name);
memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
memberContract.IsRequired = memberAttribute.IsRequired;
- if (memberAttribute.IsRequired && this.IsReference)
+ if (memberAttribute.IsRequired && IsReference)
{
ThrowInvalidDataContractException(
SR.Format(SR.IsRequiredDataMemberOnIsReferenceDataContractType,
@@ -996,7 +862,7 @@ private void ImportDataMembers()
CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
}
}
- else if (!isPodSerializable)
+ else if (_isNonAttributedType)
{
FieldInfo? field = member as FieldInfo;
PropertyInfo? property = member as PropertyInfo;
@@ -1021,7 +887,7 @@ private void ImportDataMembers()
MethodInfo? setMethod = property.SetMethod;
if (setMethod == null)
{
- if (!SetIfGetOnlyCollection(memberContract))
+ if (!SetIfGetOnlyCollection(memberContract, skipIfReadOnlyContract: true))
continue;
}
else
@@ -1029,6 +895,11 @@ private void ImportDataMembers()
if (!setMethod.IsPublic || IsMethodOverriding(setMethod))
continue;
}
+
+ //skip ExtensionData member of type ExtensionDataObject if IExtensibleDataObject is implemented in non-attributed type
+ if (_hasExtensionData && memberContract.MemberType == Globals.TypeOfExtensionDataObject
+ && member.Name == Globals.ExtensionDataObjectPropertyName)
+ continue;
}
memberContract.Name = DataContract.EncodeLocalName(member.Name);
@@ -1039,23 +910,7 @@ private void ImportDataMembers()
{
FieldInfo? field = member as FieldInfo;
- bool canSerializeMember;
-
- // Previously System.SerializableAttribute was not available in NetCore, so we had
- // a list of known [Serializable] types for type in the framework. Although now SerializableAttribute
- // is available in NetCore, some framework types still do not have [Serializable]
- // yet, e.g. ReadOnlyDictionary. So, we still need to maintain the known serializable
- // type list.
- if (IsKnownSerializableType(type))
- {
- canSerializeMember = CanSerializeMember(field);
- }
- else
- {
- canSerializeMember = field != null && !field.IsNotSerialized;
- }
-
- if (canSerializeMember)
+ if (field != null && !field.IsNotSerialized)
{
DataMember memberContract = new DataMember(member);
@@ -1063,7 +918,7 @@ private void ImportDataMembers()
object[] optionalFields = field!.GetCustomAttributes(Globals.TypeOfOptionalFieldAttribute, false);
if (optionalFields == null || optionalFields.Length == 0)
{
- if (this.IsReference)
+ if (IsReference)
{
ThrowInvalidDataContractException(
SR.Format(SR.NonOptionalFieldMemberOnIsReferenceSerializableType,
@@ -1087,16 +942,11 @@ private void ImportDataMembers()
Debug.Assert(Members != null);
}
- private static bool CanSerializeMember(FieldInfo? field)
- {
- return field != null && !ClassDataContract.IsNonSerializedMember(field.DeclaringType!, field.Name);
- }
-
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static bool SetIfGetOnlyCollection(DataMember memberContract)
+ private static bool SetIfGetOnlyCollection(DataMember memberContract, bool skipIfReadOnlyContract)
{
//OK to call IsCollection here since the use of surrogated collection types is not supported in get-only scenarios
- if (CollectionDataContract.IsCollection(memberContract.MemberType, false /*isConstructorRequired*/) && !memberContract.MemberType.IsValueType)
+ if (CollectionDataContract.IsCollection(memberContract.MemberType, false /*isConstructorRequired*/, skipIfReadOnlyContract) && !memberContract.MemberType.IsValueType)
{
memberContract.IsGetOnlyCollection = true;
return true;
@@ -1106,25 +956,25 @@ private static bool SetIfGetOnlyCollection(DataMember memberContract)
private void SetIfMembersHaveConflict(List members)
{
- if (BaseContract == null)
+ if (BaseClassContract == null)
return;
int baseTypeIndex = 0;
List membersInHierarchy = new List();
foreach (DataMember member in members)
{
- membersInHierarchy.Add(new Member(member, this.StableName!.Namespace, baseTypeIndex));
+ membersInHierarchy.Add(new Member(member, XmlName!.Namespace, baseTypeIndex));
}
- ClassDataContract? currContract = BaseContract;
+ ClassDataContract? currContract = BaseClassContract;
while (currContract != null)
{
baseTypeIndex++;
foreach (DataMember member in currContract.Members!)
{
- membersInHierarchy.Add(new Member(member, currContract.StableName!.Namespace, baseTypeIndex));
+ membersInHierarchy.Add(new Member(member, currContract.XmlName!.Namespace, baseTypeIndex));
}
- currContract = currContract.BaseContract;
+ currContract = currContract.BaseClassContract;
}
IComparer comparer = DataMemberConflictComparer.Singleton;
@@ -1136,19 +986,19 @@ private void SetIfMembersHaveConflict(List members)
int endIndex = i;
bool hasConflictingType = false;
while (endIndex < membersInHierarchy.Count - 1
- && string.CompareOrdinal(membersInHierarchy[endIndex].member.Name, membersInHierarchy[endIndex + 1].member.Name) == 0
- && string.CompareOrdinal(membersInHierarchy[endIndex].ns, membersInHierarchy[endIndex + 1].ns) == 0)
+ && string.CompareOrdinal(membersInHierarchy[endIndex]._member.Name, membersInHierarchy[endIndex + 1]._member.Name) == 0
+ && string.CompareOrdinal(membersInHierarchy[endIndex]._ns, membersInHierarchy[endIndex + 1]._ns) == 0)
{
- membersInHierarchy[endIndex].member.ConflictingMember = membersInHierarchy[endIndex + 1].member;
+ membersInHierarchy[endIndex]._member.ConflictingMember = membersInHierarchy[endIndex + 1]._member;
if (!hasConflictingType)
{
- if (membersInHierarchy[endIndex + 1].member.HasConflictingNameAndType)
+ if (membersInHierarchy[endIndex + 1]._member.HasConflictingNameAndType)
{
hasConflictingType = true;
}
else
{
- hasConflictingType = (membersInHierarchy[endIndex].member.MemberType != membersInHierarchy[endIndex + 1].member.MemberType);
+ hasConflictingType = (membersInHierarchy[endIndex]._member.MemberType != membersInHierarchy[endIndex + 1]._member.MemberType);
}
}
endIndex++;
@@ -1158,7 +1008,7 @@ private void SetIfMembersHaveConflict(List members)
{
for (int j = startIndex; j <= endIndex; j++)
{
- membersInHierarchy[j].member.HasConflictingNameAndType = true;
+ membersInHierarchy[j]._member.HasConflictingNameAndType = true;
}
}
@@ -1167,15 +1017,15 @@ private void SetIfMembersHaveConflict(List members)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private XmlQualifiedName GetStableNameAndSetHasDataContract(Type type)
+ private XmlQualifiedName GetXmlNameAndSetHasDataContract(Type type)
{
- return DataContract.GetStableName(type, out _hasDataContract);
+ return DataContract.GetXmlName(type, out _hasDataContract);
}
///
/// RequiresReview - marked SRR because callers may need to depend on isNonAttributedType for a security decision
/// isNonAttributedType must be calculated correctly
- /// SetIsNonAttributedType should not be called before GetStableNameAndSetHasDataContract since it
+ /// SetIsNonAttributedType should not be called before GetXmlNameAndSetHasDataContract since it
/// is dependent on the correct calculation of hasDataContract
/// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value
///
@@ -1199,7 +1049,7 @@ internal void EnsureMethodsImported()
{
if (!_isMethodChecked)
{
- Type type = this.UnderlyingType;
+ Type type = UnderlyingType;
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
for (int i = 0; i < methods.Length; i++)
{
@@ -1272,20 +1122,21 @@ private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameter
return false;
}
- internal ClassDataContract? BaseContract
+ internal ClassDataContract? BaseClassContract
{
- get { return _baseContract; }
+ get => _baseContract;
set
{
_baseContract = value;
if (_baseContract != null && IsValueType)
- ThrowInvalidDataContractException(SR.Format(SR.ValueTypeCannotHaveBaseType, StableName!.Name, StableName.Namespace, _baseContract.StableName!.Name, _baseContract.StableName.Namespace));
+ ThrowInvalidDataContractException(SR.Format(SR.ValueTypeCannotHaveBaseType, XmlName!.Name, XmlName.Namespace, _baseContract.XmlName!.Name, _baseContract.XmlName.Namespace));
}
}
internal List? Members
{
- get { return _members; }
+ get => _members;
+ set => _members = value;
}
internal MethodInfo? OnSerializing
@@ -1335,99 +1186,39 @@ internal MethodInfo? ExtensionDataSetMethod
internal override DataContractDictionary? KnownDataContracts
{
-
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
get
{
- if (_knownDataContracts != null)
- {
- return _knownDataContracts;
- }
-
if (!_isKnownTypeAttributeChecked && UnderlyingType != null)
{
lock (this)
{
if (!_isKnownTypeAttributeChecked)
{
- _knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
+ _knownDataContracts = DataContract.ImportKnownTypeAttributes(UnderlyingType);
Interlocked.MemoryBarrier();
_isKnownTypeAttributeChecked = true;
}
+ _knownDataContracts ??= new DataContractDictionary();
}
}
return _knownDataContracts;
}
- set
- { _knownDataContracts = value; }
- }
-
- internal override bool IsISerializable
- {
- get { return _isISerializable; }
- set { _isISerializable = value; }
- }
-
- internal bool HasDataContract
- {
- get { return _hasDataContract; }
- }
-
- internal bool HasExtensionData
- {
- get { return _hasExtensionData; }
- set { _hasExtensionData = value; }
- }
-
- internal bool IsNonAttributedType
- {
- get { return _isNonAttributedType; }
+ set { _knownDataContracts = value; }
}
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private void SetKeyValuePairAdapterFlags(
- [DynamicallyAccessedMembers(DataContractPreserveMemberTypes)]
- Type type)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfKeyValuePairAdapter)
- {
- _isKeyValuePairAdapter = true;
- _keyValuePairGenericArguments = type.GetGenericArguments();
- _keyValuePairCtorInfo = (ConstructorInfo)type.GetMemberWithSameMetadataDefinitionAs(s_ctorGenericMethod);
- _getKeyValuePairMethodInfo = (MethodInfo)type.GetMemberWithSameMetadataDefinitionAs(s_getKeyValuePairMethod);
- }
- }
+ internal string? SerializationExceptionMessage => _serializationExceptionMessage;
- private bool _isKeyValuePairAdapter;
- private Type[]? _keyValuePairGenericArguments;
- private ConstructorInfo? _keyValuePairCtorInfo;
- private MethodInfo? _getKeyValuePairMethodInfo;
+ internal string? DeserializationExceptionMessage => (_serializationExceptionMessage == null) ? null : SR.Format(SR.ReadOnlyClassDeserialization, _serializationExceptionMessage);
- internal bool IsKeyValuePairAdapter
- {
- get { return _isKeyValuePairAdapter; }
- }
+ internal override bool IsISerializable { get; set; }
- internal bool IsScriptObject
- {
- get { return _isScriptObject; }
- }
-
- internal Type[]? KeyValuePairGenericArguments
- {
- get { return _keyValuePairGenericArguments; }
- }
+ internal bool HasDataContract => _hasDataContract;
- internal ConstructorInfo? KeyValuePairAdapterConstructorInfo
- {
- get { return _keyValuePairCtorInfo; }
- }
+ internal bool HasExtensionData => _hasExtensionData;
- internal MethodInfo? GetKeyValuePairMethodInfo
- {
- get { return _getKeyValuePairMethodInfo; }
- }
+ internal bool IsNonAttributedType => _isNonAttributedType;
internal ConstructorInfo? GetISerializableConstructor()
{
@@ -1443,7 +1234,7 @@ internal MethodInfo? GetKeyValuePairMethodInfo
internal ConstructorInfo? GetNonAttributedTypeConstructor()
{
- if (!this.IsNonAttributedType)
+ if (!IsNonAttributedType)
return null;
Type type = UnderlyingType;
@@ -1458,23 +1249,11 @@ internal MethodInfo? GetKeyValuePairMethodInfo
return ctor;
}
- internal XmlFormatClassWriterDelegate? XmlFormatWriterDelegate
- {
- get { return _xmlFormatWriterDelegate; }
- set { _xmlFormatWriterDelegate = value; }
- }
+ internal XmlFormatClassWriterDelegate? XmlFormatWriterDelegate { get; set; }
- internal XmlFormatClassReaderDelegate? XmlFormatReaderDelegate
- {
- get { return _xmlFormatReaderDelegate; }
- set { _xmlFormatReaderDelegate = value; }
- }
+ internal XmlFormatClassReaderDelegate? XmlFormatReaderDelegate { get; set; }
- public XmlDictionaryString?[]? ChildElementNamespaces
- {
- get { return _childElementNamespaces; }
- set { _childElementNamespaces = value; }
- }
+ internal XmlDictionaryString?[]? ChildElementNamespaces { get; set; }
private static Type[] SerInfoCtorArgs => s_serInfoCtorArgs ??= new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
@@ -1482,70 +1261,207 @@ internal struct Member
{
internal Member(DataMember member, string ns, int baseTypeIndex)
{
- this.member = member;
- this.ns = ns;
- this.baseTypeIndex = baseTypeIndex;
+ _member = member;
+ _ns = ns;
+ _baseTypeIndex = baseTypeIndex;
}
- internal DataMember member;
- internal string ns;
- internal int baseTypeIndex;
+ internal DataMember _member;
+ internal string _ns;
+ internal int _baseTypeIndex;
}
internal sealed class DataMemberConflictComparer : IComparer
{
public int Compare(Member x, Member y)
{
- int nsCompare = string.CompareOrdinal(x.ns, y.ns);
+ int nsCompare = string.CompareOrdinal(x._ns, y._ns);
if (nsCompare != 0)
return nsCompare;
- int nameCompare = string.CompareOrdinal(x.member.Name, y.member.Name);
+ int nameCompare = string.CompareOrdinal(x._member.Name, y._member.Name);
if (nameCompare != 0)
return nameCompare;
- return x.baseTypeIndex - y.baseTypeIndex;
+ return x._baseTypeIndex - y._baseTypeIndex;
}
internal static DataMemberConflictComparer Singleton = new DataMemberConflictComparer();
}
+ }
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal ClassDataContractCriticalHelper Clone()
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary? boundContracts = null)
+ {
+ Type type = UnderlyingType;
+ if (!type.IsGenericType || !type.ContainsGenericParameters)
+ return this;
+
+ lock (this)
+ {
+ if (boundContracts != null && boundContracts.TryGetValue(this, out DataContract? boundContract))
+ return boundContract;
+
+ XmlQualifiedName xmlName;
+ object[] genericParams;
+ Type boundType;
+ if (type.IsGenericTypeDefinition)
+ {
+ xmlName = XmlName;
+ genericParams = paramContracts;
+
+ // This type-binding ('boundType') stuff is new. We did not do this in NetFx. We used to use default contract constructors and let the
+ // underlying type get filled in later. But default constructors for DataContracts runs afoul of requiring an underlying type. Our web of nullable
+ // notations make it hard to get around. But it also allows us to feel good about using .UnderlyingType from matching parameter contracts.
+ Type[] underlyingParamTypes = new Type[paramContracts.Length];
+ for (int i = 0; i < paramContracts.Length; i++)
+ underlyingParamTypes[i] = paramContracts[i].UnderlyingType;
+ boundType = type.MakeGenericType(underlyingParamTypes);
+ }
+ else
+ {
+ //partial Generic: Construct xml name from its open generic type definition
+ xmlName = DataContract.GetXmlName(type.GetGenericTypeDefinition());
+ Type[] paramTypes = type.GetGenericArguments();
+ genericParams = new object[paramTypes.Length];
+ for (int i = 0; i < paramTypes.Length; i++)
+ {
+ Type paramType = paramTypes[i];
+ if (paramType.IsGenericParameter)
+ {
+ genericParams[i] = paramContracts[paramType.GenericParameterPosition];
+ paramTypes[i] = paramContracts[paramType.GenericParameterPosition].UnderlyingType;
+ }
+ else
+ {
+ genericParams[i] = paramType;
+ }
+ }
+ boundType = type.MakeGenericType(paramTypes);
+ }
+ ClassDataContract boundClassContract = new ClassDataContract(boundType);
+ boundContracts ??= new Dictionary();
+ boundContracts.Add(this, boundClassContract);
+ boundClassContract.XmlName = CreateQualifiedName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(xmlName.Name), new GenericNameProvider(DataContract.GetClrTypeFullName(UnderlyingType), genericParams)), xmlName.Namespace);
+ if (BaseClassContract != null)
+ boundClassContract.BaseClassContract = (ClassDataContract)BaseClassContract.BindGenericParameters(paramContracts, boundContracts);
+ boundClassContract.IsISerializable = IsISerializable;
+ boundClassContract.IsValueType = IsValueType;
+ boundClassContract.IsReference = IsReference;
+ if (Members != null)
+ {
+ boundClassContract.Members = new List(Members.Count);
+ foreach (DataMember member in Members)
+ boundClassContract.Members.Add(member.BindGenericParameters(paramContracts, boundContracts));
+ }
+ return boundClassContract;
+ }
+ }
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All ctor's required to create an instance of this type are marked with RequiresUnreferencedCode.")]
+ internal override bool Equals(object? other, HashSet? checkedContracts)
+ {
+ if (IsEqualOrChecked(other, checkedContracts))
+ return true;
+
+ if (base.Equals(other, checkedContracts))
{
- ClassDataContractCriticalHelper clonedHelper = new ClassDataContractCriticalHelper(this.UnderlyingType);
-
- clonedHelper._baseContract = this._baseContract;
- clonedHelper._childElementNamespaces = this._childElementNamespaces;
- clonedHelper.ContractNamespaces = this.ContractNamespaces;
- clonedHelper._hasDataContract = this._hasDataContract;
- clonedHelper._isMethodChecked = this._isMethodChecked;
- clonedHelper._isNonAttributedType = this._isNonAttributedType;
- clonedHelper.IsReference = this.IsReference;
- clonedHelper.IsValueType = this.IsValueType;
- clonedHelper.MemberNames = this.MemberNames;
- clonedHelper.MemberNamespaces = this.MemberNamespaces;
- clonedHelper._members = this._members;
- clonedHelper.Name = this.Name;
- clonedHelper.Namespace = this.Namespace;
- clonedHelper._onDeserialized = this._onDeserialized;
- clonedHelper._onDeserializing = this._onDeserializing;
- clonedHelper._onSerialized = this._onSerialized;
- clonedHelper._onSerializing = this._onSerializing;
- clonedHelper.StableName = this.StableName;
- clonedHelper.TopLevelElementName = this.TopLevelElementName;
- clonedHelper.TopLevelElementNamespace = this.TopLevelElementNamespace;
- clonedHelper._xmlFormatReaderDelegate = this._xmlFormatReaderDelegate;
- clonedHelper._xmlFormatWriterDelegate = this._xmlFormatWriterDelegate;
-
- return clonedHelper;
+ if (other is ClassDataContract dataContract)
+ {
+ if (IsISerializable)
+ {
+ if (!dataContract.IsISerializable)
+ return false;
+ }
+ else
+ {
+ if (dataContract.IsISerializable)
+ return false;
+
+ if (Members == null)
+ {
+ if (dataContract.Members != null)
+ {
+ // check that all the datamembers in dataContract.Members are optional
+ if (!IsEveryDataMemberOptional(dataContract.Members))
+ return false;
+ }
+ }
+ else if (dataContract.Members == null)
+ {
+ // check that all the datamembers in Members are optional
+ if (!IsEveryDataMemberOptional(Members))
+ return false;
+ }
+ else
+ {
+ Dictionary membersDictionary = new Dictionary(Members.Count);
+ List dataContractMembersList = new List();
+ for (int i = 0; i < Members.Count; i++)
+ {
+ membersDictionary.Add(Members[i].Name, Members[i]);
+ }
+
+ for (int i = 0; i < dataContract.Members.Count; i++)
+ {
+ // check that all datamembers common to both datacontracts match
+ if (membersDictionary.TryGetValue(dataContract.Members[i].Name, out DataMember? dataMember))
+ {
+ if (dataMember.Equals(dataContract.Members[i], checkedContracts))
+ {
+ membersDictionary.Remove(dataMember.Name);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ // otherwise save the non-matching datamembers for later verification
+ else
+ {
+ dataContractMembersList.Add(dataContract.Members[i]);
+ }
+ }
+
+ // check that datamembers left over from either datacontract are optional
+ if (!IsEveryDataMemberOptional(membersDictionary.Values))
+ return false;
+ if (!IsEveryDataMemberOptional(dataContractMembersList))
+ return false;
+ }
+ }
+
+ if (BaseClassContract == null)
+ return (dataContract.BaseClassContract == null);
+ else if (dataContract.BaseClassContract == null)
+ return false;
+ else
+ return BaseClassContract.Equals(dataContract.BaseClassContract, checkedContracts);
+ }
}
+ return false;
+ }
+
+ private static bool IsEveryDataMemberOptional(IEnumerable dataMembers)
+ {
+ return !dataMembers.Any(dm => dm.IsRequired);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
}
internal sealed class DataMemberComparer : IComparer
{
public int Compare(DataMember? x, DataMember? y)
{
- int orderCompare = x!.Order - y!.Order;
+ if (x == null && y == null)
+ return 0;
+ if (x == null || y == null)
+ return -1;
+
+ int orderCompare = (int)(x.Order - y.Order);
if (orderCompare != 0)
return orderCompare;
@@ -1556,7 +1472,7 @@ public int Compare(DataMember? x, DataMember? y)
}
///
- /// Get object type for Xml/JsonFormmatReaderGenerator
+ /// Get object type for Xml/JsonFormatReaderGenerator
///
internal Type ObjectType
{
@@ -1570,37 +1486,5 @@ internal Type ObjectType
return type;
}
}
-
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal ClassDataContract Clone()
- {
- ClassDataContract clonedDc = new ClassDataContract(this.UnderlyingType);
- clonedDc._helper = _helper.Clone();
- clonedDc.ContractNamespaces = this.ContractNamespaces;
- clonedDc.ChildElementNamespaces = this.ChildElementNamespaces;
- clonedDc.MemberNames = this.MemberNames;
- clonedDc.MemberNamespaces = this.MemberNamespaces;
- clonedDc.XmlFormatWriterDelegate = this.XmlFormatWriterDelegate;
- clonedDc.XmlFormatReaderDelegate = this.XmlFormatReaderDelegate;
- return clonedDc;
- }
-
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal void UpdateNamespaceAndMembers(Type type, XmlDictionaryString ns, string[] memberNames)
- {
- this.StableName = new XmlQualifiedName(GetStableName(type).Name, ns.Value);
- this.Namespace = ns;
- XmlDictionary dictionary = new XmlDictionary(1 + memberNames.Length);
- this.Name = dictionary.Add(StableName.Name);
- this.Namespace = ns;
- this.ContractNamespaces = new XmlDictionaryString[] { ns };
- this.MemberNames = new XmlDictionaryString[memberNames.Length];
- this.MemberNamespaces = new XmlDictionaryString[memberNames.Length];
- for (int i = 0; i < memberNames.Length; i++)
- {
- this.MemberNames[i] = dictionary.Add(memberNames[i]);
- this.MemberNamespaces[i] = ns;
- }
- }
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs
index b39d1af3d439f..201bdc3e93e83 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs
@@ -2,17 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
-using System.Xml;
using System.Reflection;
using System.Reflection.Emit;
-using System.IO;
-using System.Security;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.Serialization.Json;
+using System.Runtime.Serialization.DataContracts;
namespace System.Runtime.Serialization
{
@@ -88,6 +84,14 @@ private static MethodInfo StringFormat
}
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
+ Justification = "The trimmer will never remove the Invoke method from delegates.")]
+ internal static MethodInfo GetInvokeMethod(Type delegateType)
+ {
+ Debug.Assert(typeof(Delegate).IsAssignableFrom(delegateType));
+ return delegateType.GetMethod("Invoke")!;
+ }
+
private Type _delegateType = null!; // initialized in BeginMethod
private static Module? s_serializationModule;
@@ -100,17 +104,9 @@ private static MethodInfo StringFormat
private Stack _blockStack = null!; // initialized in BeginMethod
private Label _methodEndLabel;
- private readonly Dictionary _localNames = new Dictionary();
-
- private enum CodeGenTrace { None, Save, Tron };
- private readonly CodeGenTrace _codeGenTrace;
private LocalBuilder? _stringFormatArray;
- internal CodeGenerator()
- {
- //Defaulting to None as thats the default value in WCF
- _codeGenTrace = CodeGenTrace.None;
- }
+ internal CodeGenerator() { }
internal void BeginMethod(DynamicMethod dynamicMethod, Type delegateType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
{
@@ -123,7 +119,7 @@ internal void BeginMethod(DynamicMethod dynamicMethod, Type delegateType, string
internal void BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)
{
- MethodInfo signature = JsonFormatWriterGenerator.GetInvokeMethod(delegateType);
+ MethodInfo signature = GetInvokeMethod(delegateType);
ParameterInfo[] parameters = signature.GetParameters();
Type[] paramTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
@@ -148,15 +144,11 @@ private void InitILGeneration(string methodName, Type[] argTypes)
_argList = new List();
for (int i = 0; i < argTypes.Length; i++)
_argList.Add(new ArgBuilder(i, argTypes[i]));
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceLabel("Begin method " + methodName + " {");
}
internal Delegate EndMethod()
{
MarkLabel(_methodEndLabel);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceLabel("} End method");
Ret();
Delegate? retVal;
@@ -180,15 +172,15 @@ internal MethodInfo CurrentMethod
internal ArgBuilder GetArg(int index)
{
- return (ArgBuilder)_argList[index];
+ return _argList[index];
}
internal static Type GetVariableType(object var)
{
- if (var is ArgBuilder)
- return ((ArgBuilder)var).ArgType;
- else if (var is LocalBuilder)
- return ((LocalBuilder)var).LocalType;
+ if (var is ArgBuilder argBuilder)
+ return argBuilder.ArgType;
+ else if (var is LocalBuilder localBuilder)
+ return localBuilder.LocalType;
else
return var.GetType();
}
@@ -203,18 +195,12 @@ internal LocalBuilder DeclareLocal(Type type, string name, object initialValue)
internal LocalBuilder DeclareLocal(Type type, string name)
{
- return DeclareLocal(type, name, false);
+ return DeclareLocal(type, false);
}
- internal LocalBuilder DeclareLocal(Type type, string name, bool isPinned)
+ internal LocalBuilder DeclareLocal(Type type, bool isPinned)
{
- LocalBuilder local = _ilGen.DeclareLocal(type, isPinned);
- if (_codeGenTrace != CodeGenTrace.None)
- {
- _localNames[local] = name;
- EmitSourceComment("Declare local '" + name + "' of type " + type);
- }
- return local;
+ return _ilGen.DeclareLocal(type, isPinned);
}
internal void Set(LocalBuilder local, object value)
@@ -277,16 +263,14 @@ internal void InternalBreakFor(object userForState, OpCode branchInstruction)
{
foreach (object block in _blockStack)
{
- ForState? forState = block as ForState;
- if (forState != null && (object)forState == userForState)
+ if (block == userForState && block is ForState forState)
{
if (!forState.RequiresEndLabel)
{
forState.EndLabel = DefineLabel();
forState.RequiresEndLabel = true;
}
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(branchInstruction + " " + forState.EndLabel.GetHashCode());
+
_ilGen.Emit(branchInstruction, forState.EndLabel);
break;
}
@@ -329,7 +313,7 @@ internal void EndForEach(MethodInfo moveNextMethod)
internal void IfNotDefaultValue(object value)
{
Type type = GetVariableType(value);
- TypeCode typeCode = type.GetTypeCode();
+ TypeCode typeCode = Type.GetTypeCode(type);
if ((typeCode == TypeCode.Object && type.IsValueType) ||
typeCode == TypeCode.DateTime || typeCode == TypeCode.Decimal)
{
@@ -507,51 +491,36 @@ internal void Call(MethodInfo methodInfo)
{
if (methodInfo.IsVirtual && !methodInfo.DeclaringType!.IsValueType)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Callvirt " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
_ilGen.Emit(OpCodes.Callvirt, methodInfo);
}
else if (methodInfo.IsStatic)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Static Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType!.ToString());
_ilGen.Emit(OpCodes.Call, methodInfo);
}
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType!.ToString());
_ilGen.Emit(OpCodes.Call, methodInfo);
}
}
internal void Call(ConstructorInfo ctor)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Call " + ctor.ToString() + " on type " + ctor.DeclaringType!.ToString());
_ilGen.Emit(OpCodes.Call, ctor);
}
internal void New(ConstructorInfo constructorInfo)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Newobj " + constructorInfo.ToString() + " on type " + constructorInfo.DeclaringType!.ToString());
_ilGen.Emit(OpCodes.Newobj, constructorInfo);
}
-
internal void InitObj(Type valueType)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Initobj " + valueType);
_ilGen.Emit(OpCodes.Initobj, valueType);
}
internal void NewArray(Type elementType, object len)
{
Load(len);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Newarr " + elementType);
_ilGen.Emit(OpCodes.Newarr, elementType);
}
@@ -605,27 +574,20 @@ internal Type LoadMember(MemberInfo memberInfo)
memberType = fieldInfo.FieldType;
if (fieldInfo.IsStatic)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
_ilGen.Emit(OpCodes.Ldsfld, fieldInfo);
}
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
_ilGen.Emit(OpCodes.Ldfld, fieldInfo);
}
}
else if (memberInfo is PropertyInfo property)
{
memberType = property.PropertyType;
- if (property != null)
- {
- MethodInfo? getMethod = property.GetMethod;
- if (getMethod == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoGetMethodForProperty, property.DeclaringType, property)));
- Call(getMethod);
- }
+ MethodInfo? getMethod = property.GetMethod;
+ if (getMethod == null)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoGetMethodForProperty, property.DeclaringType, property)));
+ Call(getMethod);
}
else if (memberInfo is MethodInfo method)
{
@@ -635,7 +597,6 @@ internal Type LoadMember(MemberInfo memberInfo)
else
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotLoadMemberType, "Unknown", memberInfo.DeclaringType, memberInfo.Name)));
- EmitStackTop(memberType);
return memberType;
}
@@ -645,30 +606,22 @@ internal void StoreMember(MemberInfo memberInfo)
{
if (fieldInfo.IsStatic)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Stsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
_ilGen.Emit(OpCodes.Stsfld, fieldInfo);
}
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Stfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
_ilGen.Emit(OpCodes.Stfld, fieldInfo);
}
}
- else if (memberInfo is PropertyInfo)
+ else if (memberInfo is PropertyInfo property)
{
- PropertyInfo? property = memberInfo as PropertyInfo;
- if (property != null)
- {
- MethodInfo? setMethod = property.SetMethod;
- if (setMethod == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoSetMethodForProperty, property.DeclaringType, property)));
- Call(setMethod);
- }
+ MethodInfo? setMethod = property.SetMethod;
+ if (setMethod == null)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoSetMethodForProperty, property.DeclaringType, property)));
+ Call(setMethod);
}
- else if (memberInfo is MethodInfo)
- Call((MethodInfo)memberInfo);
+ else if (memberInfo is MethodInfo method)
+ Call(method);
else
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotLoadMemberType, "Unknown")));
}
@@ -677,7 +630,7 @@ internal void LoadDefaultValue(Type type)
{
if (type.IsValueType)
{
- switch (type.GetTypeCode())
+ switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
Ldc(false);
@@ -719,24 +672,22 @@ internal void Load(object? obj)
{
if (obj == null)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldnull");
_ilGen.Emit(OpCodes.Ldnull);
}
- else if (obj is ArgBuilder)
- Ldarg((ArgBuilder)obj);
- else if (obj is LocalBuilder)
- Ldloc((LocalBuilder)obj);
+ else if (obj is ArgBuilder argBuilder)
+ Ldarg(argBuilder);
+ else if (obj is LocalBuilder localBuilder)
+ Ldloc(localBuilder);
else
Ldc(obj);
}
internal void Store(object var)
{
- if (var is ArgBuilder)
- Starg((ArgBuilder)var);
- else if (var is LocalBuilder)
- Stloc((LocalBuilder)var);
+ if (var is ArgBuilder argBuilder)
+ Starg(argBuilder);
+ else if (var is LocalBuilder localBuilder)
+ Stloc(localBuilder);
else
{
DiagnosticUtility.DebugAssert("Data can only be stored into ArgBuilder or LocalBuilder.");
@@ -754,10 +705,10 @@ internal void Dec(object var)
internal void LoadAddress(object obj)
{
- if (obj is ArgBuilder)
- LdargAddress((ArgBuilder)obj);
- else if (obj is LocalBuilder)
- LdlocAddress((LocalBuilder)obj);
+ if (obj is ArgBuilder argBuilder)
+ LdargAddress(argBuilder);
+ else if (obj is LocalBuilder localBuilder)
+ LdlocAddress(localBuilder);
else
Load(obj);
}
@@ -776,22 +727,16 @@ internal void ConvertValue(Type source, Type target)
internal void Castclass(Type target)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Castclass " + target);
_ilGen.Emit(OpCodes.Castclass, target);
}
internal void Box(Type type)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Box " + type);
_ilGen.Emit(OpCodes.Box, type);
}
internal void Unbox(Type type)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Unbox " + type);
_ilGen.Emit(OpCodes.Unbox, type);
}
@@ -816,67 +761,53 @@ private static OpCode GetLdindOpCode(TypeCode typeCode) =>
internal void Ldobj(Type type)
{
- OpCode opCode = GetLdindOpCode(type.GetTypeCode());
+ OpCode opCode = GetLdindOpCode(Type.GetTypeCode(type));
if (!opCode.Equals(OpCodes.Nop))
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(opCode.ToString()!);
_ilGen.Emit(opCode);
}
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldobj " + type);
_ilGen.Emit(OpCodes.Ldobj, type);
}
}
internal void Stobj(Type type)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Stobj " + type);
_ilGen.Emit(OpCodes.Stobj, type);
}
internal void Ceq()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ceq");
_ilGen.Emit(OpCodes.Ceq);
}
internal void Throw()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Throw");
_ilGen.Emit(OpCodes.Throw);
}
internal void Ldtoken(Type t)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldtoken " + t);
_ilGen.Emit(OpCodes.Ldtoken, t);
}
internal void Ldc(object o)
{
Type valueType = o.GetType();
- if (o is Type)
+ if (o is Type t)
{
- Ldtoken((Type)o);
+ Ldtoken(t);
Call(GetTypeFromHandle);
}
else if (valueType.IsEnum)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceComment("Ldc " + o.GetType() + "." + o);
Ldc(Convert.ChangeType(o, Enum.GetUnderlyingType(valueType), null));
}
else
{
- switch (valueType.GetTypeCode())
+ switch (Type.GetTypeCode(valueType))
{
case TypeCode.Boolean:
Ldc((bool)o);
@@ -915,6 +846,7 @@ internal void Ldc(object o)
case TypeCode.Decimal:
case TypeCode.DateTime:
case TypeCode.Empty:
+ case TypeCode.DBNull:
default:
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.UnknownConstantType, DataContract.GetClrTypeFullName(valueType))));
}
@@ -925,50 +857,36 @@ internal void Ldc(bool boolVar)
{
if (boolVar)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.i4 1");
_ilGen.Emit(OpCodes.Ldc_I4_1);
}
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.i4 0");
_ilGen.Emit(OpCodes.Ldc_I4_0);
}
}
internal void Ldc(int intVar)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.i4 " + intVar);
_ilGen.Emit(OpCodes.Ldc_I4, intVar);
}
internal void Ldc(long l)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.i8 " + l);
_ilGen.Emit(OpCodes.Ldc_I8, l);
}
internal void Ldc(float f)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.r4 " + f);
_ilGen.Emit(OpCodes.Ldc_R4, f);
}
internal void Ldc(double d)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldc.r8 " + d);
_ilGen.Emit(OpCodes.Ldc_R8, d);
}
internal void Ldstr(string strVar)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldstr " + strVar);
_ilGen.Emit(OpCodes.Ldstr, strVar);
}
@@ -982,27 +900,17 @@ internal void LdlocAddress(LocalBuilder localBuilder)
internal void Ldloc(LocalBuilder localBuilder)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldloc " + _localNames[localBuilder]);
_ilGen.Emit(OpCodes.Ldloc, localBuilder);
- EmitStackTop(localBuilder.LocalType);
}
internal void Stloc(LocalBuilder local)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Stloc " + _localNames[local]);
- EmitStackTop(local.LocalType);
_ilGen.Emit(OpCodes.Stloc, local);
}
-
internal void Ldloca(LocalBuilder localBuilder)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldloca " + _localNames[localBuilder]);
_ilGen.Emit(OpCodes.Ldloca, localBuilder);
- EmitStackTop(localBuilder.LocalType);
}
internal void LdargAddress(ArgBuilder argBuilder)
@@ -1025,17 +933,11 @@ internal void Starg(ArgBuilder arg)
internal void Ldarg(int slot)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldarg " + slot);
-
_ilGen.Emit(OpCodes.Ldarg, slot);
}
internal void Starg(int slot)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Starg " + slot);
-
_ilGen.Emit(OpCodes.Starg, slot);
}
@@ -1046,26 +948,19 @@ internal void Ldarga(ArgBuilder argBuilder)
internal void Ldarga(int slot)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldarga " + slot);
-
_ilGen.Emit(OpCodes.Ldarga, slot);
}
internal void Ldlen()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ldlen");
_ilGen.Emit(OpCodes.Ldlen);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Conv.i4");
_ilGen.Emit(OpCodes.Conv_I4);
}
private static OpCode GetLdelemOpCode(TypeCode typeCode) =>
typeCode switch
{
- TypeCode.Object => OpCodes.Ldelem_Ref, // TypeCode.Object:
+ TypeCode.Object or TypeCode.DBNull => OpCodes.Ldelem_Ref, // TypeCode.Object:
TypeCode.Boolean => OpCodes.Ldelem_I1, // TypeCode.Boolean:
TypeCode.Char => OpCodes.Ldelem_I2, // TypeCode.Char:
TypeCode.SByte => OpCodes.Ldelem_I1, // TypeCode.SByte:
@@ -1090,29 +985,22 @@ internal void Ldelem(Type arrayElementType)
}
else
{
- OpCode opCode = GetLdelemOpCode(arrayElementType.GetTypeCode());
+ OpCode opCode = GetLdelemOpCode(Type.GetTypeCode(arrayElementType));
if (opCode.Equals(OpCodes.Nop))
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ArrayTypeIsNotSupported_GeneratingCode, DataContract.GetClrTypeFullName(arrayElementType))));
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(opCode.ToString()!);
_ilGen.Emit(opCode);
- EmitStackTop(arrayElementType);
}
}
internal void Ldelema(Type arrayElementType)
{
OpCode opCode = OpCodes.Ldelema;
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(opCode.ToString()!);
_ilGen.Emit(opCode, arrayElementType);
-
- EmitStackTop(arrayElementType);
}
private static OpCode GetStelemOpCode(TypeCode typeCode) =>
typeCode switch
{
- TypeCode.Object => OpCodes.Stelem_Ref, // TypeCode.Object:
+ TypeCode.Object or TypeCode.DBNull => OpCodes.Stelem_Ref, // TypeCode.Object:
TypeCode.Boolean => OpCodes.Stelem_I1, // TypeCode.Boolean:
TypeCode.Char => OpCodes.Stelem_I2, // TypeCode.Char:
TypeCode.SByte => OpCodes.Stelem_I1, // TypeCode.SByte:
@@ -1135,12 +1023,10 @@ internal void Stelem(Type arrayElementType)
Stelem(Enum.GetUnderlyingType(arrayElementType));
else
{
- OpCode opCode = GetStelemOpCode(arrayElementType.GetTypeCode());
+ OpCode opCode = GetStelemOpCode(Type.GetTypeCode(arrayElementType));
if (opCode.Equals(OpCodes.Nop))
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ArrayTypeIsNotSupported_GeneratingCode, DataContract.GetClrTypeFullName(arrayElementType))));
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(opCode.ToString()!);
- EmitStackTop(arrayElementType);
+
_ilGen.Emit(opCode);
}
}
@@ -1153,92 +1039,64 @@ internal Label DefineLabel()
internal void MarkLabel(Label label)
{
_ilGen.MarkLabel(label);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceLabel(label.GetHashCode() + ":");
}
internal void Add()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Add");
_ilGen.Emit(OpCodes.Add);
}
internal void Subtract()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Sub");
_ilGen.Emit(OpCodes.Sub);
}
internal void And()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("And");
_ilGen.Emit(OpCodes.And);
}
internal void Or()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Or");
_ilGen.Emit(OpCodes.Or);
}
internal void Not()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Not");
_ilGen.Emit(OpCodes.Not);
}
internal void Ret()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Ret");
_ilGen.Emit(OpCodes.Ret);
}
internal void Br(Label label)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Br " + label.GetHashCode());
_ilGen.Emit(OpCodes.Br, label);
}
internal void Blt(Label label)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Blt " + label.GetHashCode());
_ilGen.Emit(OpCodes.Blt, label);
}
internal void Brfalse(Label label)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Brfalse " + label.GetHashCode());
_ilGen.Emit(OpCodes.Brfalse, label);
}
internal void Brtrue(Label label)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Brtrue " + label.GetHashCode());
_ilGen.Emit(OpCodes.Brtrue, label);
}
-
-
internal void Pop()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Pop");
_ilGen.Emit(OpCodes.Pop);
}
internal void Dup()
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("Dup");
_ilGen.Emit(OpCodes.Dup);
}
@@ -1296,13 +1154,11 @@ private void InternalConvert(Type source, Type target, bool isAddress)
{
if (source.IsValueType)
{
- OpCode opCode = GetConvOpCode(target.GetTypeCode());
+ OpCode opCode = GetConvOpCode(Type.GetTypeCode(target));
if (opCode.Equals(OpCodes.Nop))
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoConversionPossibleTo, DataContract.GetClrTypeFullName(target))));
else
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction(opCode.ToString()!);
_ilGen.Emit(opCode);
}
}
@@ -1351,26 +1207,6 @@ private static void ThrowMismatchException(object expected)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExpectingEnd, expected.ToString())));
}
-
- internal static void EmitSourceInstruction(string line)
- {
- }
-
- internal static void EmitSourceLabel(string line)
- {
- }
-
- internal static void EmitSourceComment(string comment)
- {
- }
-
-
- internal void EmitStackTop(Type stackTopType)
- {
- if (_codeGenTrace != CodeGenTrace.Tron)
- return;
- }
-
internal Label[] Switch(int labelCount)
{
SwitchState switchState = new SwitchState(DefineLabel(), DefineLabel());
@@ -1385,8 +1221,6 @@ internal Label[] Switch(int labelCount)
}
internal void Case(Label caseLabel1, string caseLabelName)
{
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("case " + caseLabelName + "{");
MarkLabel(caseLabel1);
}
@@ -1397,8 +1231,6 @@ internal void EndCase()
if (switchState == null)
ThrowMismatchException(stackTop);
Br(switchState.EndOfSwitchLabel);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("} //end case ");
}
internal void EndSwitch()
@@ -1407,8 +1239,6 @@ internal void EndSwitch()
SwitchState? switchState = stackTop as SwitchState;
if (switchState == null)
ThrowMismatchException(stackTop);
- if (_codeGenTrace != CodeGenTrace.None)
- EmitSourceInstruction("} //end switch");
if (!switchState.DefaultDefined)
MarkLabel(switchState.DefaultLabel);
MarkLabel(switchState.EndOfSwitchLabel);
@@ -1490,8 +1320,8 @@ internal sealed class ArgBuilder
internal Type ArgType;
internal ArgBuilder(int index, Type argType)
{
- this.Index = index;
- this.ArgType = argType;
+ Index = index;
+ ArgType = argType;
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CollectionDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CollectionDataContract.cs
index df57f68205cf2..948817e1d31a2 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CollectionDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CollectionDataContract.cs
@@ -8,62 +8,14 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Security;
using System.Threading;
using System.Xml;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+using DataContractDictionary = System.Collections.Generic.Dictionary;
namespace System.Runtime.Serialization
{
- // The interface is a perf optimization.
- // Only KeyValuePairAdapter should implement the interface.
- internal interface IKeyValuePairAdapter { }
-
- //Special Adapter class to serialize KeyValuePair as Dictionary needs it when polymorphism is involved
- [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/System.Collections.Generic")]
- internal sealed class KeyValuePairAdapter : IKeyValuePairAdapter
- {
- private K _kvpKey;
- private T _kvpValue;
-
- public KeyValuePairAdapter(KeyValuePair kvPair)
- {
- _kvpKey = kvPair.Key;
- _kvpValue = kvPair.Value;
- }
-
- [DataMember(Name = "key")]
- public K Key
- {
- get { return _kvpKey; }
- set { _kvpKey = value; }
- }
-
- [DataMember(Name = "value")]
- public T Value
- {
- get
- {
- return _kvpValue;
- }
- set
- {
- _kvpValue = value;
- }
- }
-
- internal KeyValuePair GetKeyValuePair()
- {
- return new KeyValuePair(_kvpKey, _kvpValue);
- }
-
- internal static KeyValuePairAdapter GetKeyValuePairAdapter(KeyValuePair kvPair)
- {
- return new KeyValuePairAdapter(kvPair);
- }
- }
-
internal interface IKeyValue
{
object? Key { get; set; }
@@ -73,39 +25,28 @@ internal interface IKeyValue
[DataContract(Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
internal struct KeyValue : IKeyValue
{
- private K _key;
- private V _value;
-
internal KeyValue(K key, V value)
{
- _key = key;
- _value = value;
+ Key = key;
+ Value = value;
}
[DataMember(IsRequired = true)]
- public K Key
- {
- get { return _key; }
- set { _key = value; }
- }
+ public K Key { get; set; }
[DataMember(IsRequired = true)]
- public V Value
- {
- get { return _value; }
- set { _value = value; }
- }
+ public V Value { get; set; }
object? IKeyValue.Key
{
- get { return _key; }
- set { _key = (K)value!; }
+ get => this.Key;
+ set => this.Key = (K)value!;
}
object? IKeyValue.Value
{
- get { return _value; }
- set { _value = (V)value!; }
+ get => this.Value;
+ set => this.Value = (V)value!;
}
}
@@ -122,9 +63,15 @@ internal enum CollectionKind : byte
Enumerable,
Array,
}
+}
+namespace System.Runtime.Serialization.DataContracts
+{
internal sealed class CollectionDataContract : DataContract
{
+ internal const string ContractTypeString = nameof(CollectionDataContract);
+ public override string? ContractType => ContractTypeString;
+
private XmlDictionaryString _collectionItemName;
private XmlDictionaryString? _childElementNamespace;
@@ -140,8 +87,20 @@ internal CollectionDataContract(Type type) : base(new CollectionDataContractCrit
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string? deserializationExceptionMessage)
- : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, deserializationExceptionMessage))
+ internal CollectionDataContract(Type type, DataContract itemContract) : base(new CollectionDataContractCriticalHelper(type, itemContract))
+ {
+ InitCollectionDataContract(this);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal CollectionDataContract(Type type, CollectionKind kind) : base(new CollectionDataContractCriticalHelper(type, kind))
+ {
+ InitCollectionDataContract(this);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string? serializationExceptionMessage, string? deserializationExceptionMessage)
+ : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage))
{
InitCollectionDataContract(GetSharedTypeContract(type));
}
@@ -180,32 +139,16 @@ private void InitCollectionDataContract(DataContract? sharedTypeContract)
_helper.SharedTypeContract = sharedTypeContract;
}
- private static Type[] KnownInterfaces
- {
- get
- { return CollectionDataContractCriticalHelper.KnownInterfaces; }
- }
+ private static Type[] KnownInterfaces => CollectionDataContractCriticalHelper.KnownInterfaces;
- internal CollectionKind Kind
- {
- get
- { return _helper.Kind; }
- }
+ internal CollectionKind Kind => _helper.Kind;
- public Type ItemType
- {
- get
- { return _helper.ItemType; }
- set { _helper.ItemType = value; }
- }
+ internal Type ItemType => _helper.ItemType;
- public DataContract ItemContract
+ internal DataContract ItemContract
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- {
- return _itemContract ?? _helper.ItemContract;
- }
+ get => _itemContract ?? _helper.ItemContract;
set
{
@@ -214,51 +157,45 @@ public DataContract ItemContract
}
}
- internal DataContract? SharedTypeContract
- {
- get
- { return _helper.SharedTypeContract; }
- }
+ internal DataContract? SharedTypeContract => _helper.SharedTypeContract;
- public string ItemName
+ internal string ItemName
{
- get
- { return _helper.ItemName; }
-
- set
- { _helper.ItemName = value; }
+ get => _helper.ItemName;
+ set => _helper.ItemName = value;
}
- public XmlDictionaryString CollectionItemName
+ internal XmlDictionaryString CollectionItemName => _collectionItemName;
+
+ internal string? KeyName
{
- get { return _collectionItemName; }
- set { _collectionItemName = value; }
+ get => _helper.KeyName;
+ set => _helper.KeyName = value;
}
- public string? KeyName
+ internal string? ValueName
{
- get
- { return _helper.KeyName; }
-
- set
- { _helper.KeyName = value; }
+ get => _helper.ValueName;
+ set => _helper.ValueName = value;
}
- public string? ValueName
+ public override bool IsDictionaryLike([NotNullWhen(true)] out string? keyName, [NotNullWhen(true)] out string? valueName, [NotNullWhen(true)] out string? itemName)
{
- get
- { return _helper.ValueName; }
-
- set
- { _helper.ValueName = value; }
+ keyName = KeyName;
+ valueName = ValueName;
+ itemName = ItemName;
+ return IsDictionary;
}
- internal bool IsDictionary
+ public override DataContract BaseContract
{
- get { return KeyName != null; }
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get => ItemContract;
}
- public XmlDictionaryString? ChildElementNamespace
+ internal bool IsDictionary => KeyName != null;
+
+ internal XmlDictionaryString? ChildElementNamespace
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
get
@@ -285,62 +222,38 @@ public XmlDictionaryString? ChildElementNamespace
internal bool IsItemTypeNullable
{
- get { return _helper.IsItemTypeNullable; }
- set { _helper.IsItemTypeNullable = value; }
+ get => _helper.IsItemTypeNullable;
+ set => _helper.IsItemTypeNullable = value;
}
internal bool IsConstructorCheckRequired
{
- get
- { return _helper.IsConstructorCheckRequired; }
-
- set
- { _helper.IsConstructorCheckRequired = value; }
+ get => _helper.IsConstructorCheckRequired;
+ set => _helper.IsConstructorCheckRequired = value;
}
- internal MethodInfo? GetEnumeratorMethod
- {
- get
- { return _helper.GetEnumeratorMethod; }
- }
+ internal MethodInfo? GetEnumeratorMethod => _helper.GetEnumeratorMethod;
- internal MethodInfo? AddMethod
- {
- get
- { return _helper.AddMethod; }
- }
+ internal MethodInfo? AddMethod => _helper.AddMethod;
- internal ConstructorInfo? Constructor
- {
- get
- { return _helper.Constructor; }
- }
+ internal ConstructorInfo? Constructor => _helper.Constructor;
public override DataContractDictionary? KnownDataContracts
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- { return _helper.KnownDataContracts; }
-
- set
- { _helper.KnownDataContracts = value; }
+ get => _helper.KnownDataContracts;
+ internal set => _helper.KnownDataContracts = value;
}
- internal string? InvalidCollectionInSharedContractMessage
- {
- get
- { return _helper.InvalidCollectionInSharedContractMessage; }
- }
+ internal string? InvalidCollectionInSharedContractMessage => _helper.InvalidCollectionInSharedContractMessage;
- internal string? DeserializationExceptionMessage
- {
- get { return _helper.DeserializationExceptionMessage; }
- }
+ internal string? SerializationExceptionMessage => _helper.SerializationExceptionMessage;
- internal bool IsReadOnlyContract
- {
- get { return DeserializationExceptionMessage != null; }
- }
+ internal string? DeserializationExceptionMessage => _helper.DeserializationExceptionMessage;
+
+ internal bool IsReadOnlyContract => DeserializationExceptionMessage != null;
+
+ private bool ItemNameSetExplicit => _helper.ItemNameSetExplicit;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private XmlFormatCollectionWriterDelegate CreateXmlFormatWriterDelegate()
@@ -367,9 +280,6 @@ internal XmlFormatCollectionWriterDelegate XmlFormatWriterDelegate
}
return _helper.XmlFormatWriterDelegate;
}
- set
- {
- }
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -402,9 +312,6 @@ internal XmlFormatCollectionReaderDelegate XmlFormatReaderDelegate
}
return _helper.XmlFormatReaderDelegate;
}
- set
- {
- }
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -479,6 +386,7 @@ private sealed class CollectionDataContractCriticalHelper : DataContract.DataCon
private readonly MethodInfo? _getEnumeratorMethod;
private readonly MethodInfo? _addMethod;
private readonly ConstructorInfo? _constructor;
+ private readonly string? _serializationExceptionMessage;
private readonly string? _deserializationExceptionMessage;
private DataContract? _itemContract;
private DataContract? _sharedTypeContract;
@@ -549,9 +457,9 @@ private void Init(CollectionKind kind, Type? itemType, CollectionDataContractAtt
}
XmlDictionary dictionary = isDictionary ? new XmlDictionary(5) : new XmlDictionary(3);
- this.Name = dictionary.Add(this.StableName.Name);
- this.Namespace = dictionary.Add(this.StableName.Namespace);
- _itemName = itemName ?? DataContract.GetStableName(DataContract.UnwrapNullableType(itemType)).Name;
+ Name = dictionary.Add(XmlName.Name);
+ Namespace = dictionary.Add(XmlName.Namespace);
+ _itemName = itemName ?? DataContract.GetXmlName(DataContract.UnwrapNullableType(itemType)).Name;
_collectionItemName = dictionary.Add(_itemName);
if (isDictionary)
{
@@ -561,11 +469,10 @@ private void Init(CollectionKind kind, Type? itemType, CollectionDataContractAtt
}
if (collectionContractAttribute != null)
{
- this.IsReference = collectionContractAttribute.IsReference;
+ IsReference = collectionContractAttribute.IsReference;
}
}
- // array
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal CollectionDataContractCriticalHelper(
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
@@ -575,7 +482,31 @@ internal CollectionDataContractCriticalHelper(
type = Globals.TypeOfObjectArray;
if (type.GetArrayRank() > 1)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SupportForMultidimensionalArraysNotPresent));
- this.StableName = DataContract.GetStableName(type);
+ XmlName = DataContract.GetXmlName(type);
+ Init(CollectionKind.Array, type.GetElementType(), null);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal CollectionDataContractCriticalHelper(
+ [DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
+ Type type,
+ CollectionKind kind) : base(type)
+ {
+ XmlName = DataContract.GetXmlName(type);
+ Init(kind, type.GetElementType(), null);
+ }
+
+ // array
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal CollectionDataContractCriticalHelper(
+ [DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
+ Type type,
+ DataContract itemContract) : base(type)
+ {
+ if (type.GetArrayRank() > 1)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SupportForMultidimensionalArraysNotPresent));
+ XmlName = CreateQualifiedName(Globals.ArrayPrefix + itemContract.XmlName.Name, itemContract.XmlName.Namespace);
+ _itemContract = itemContract;
Init(CollectionKind.Array, type.GetElementType(), null);
}
@@ -584,7 +515,7 @@ internal CollectionDataContractCriticalHelper(
internal CollectionDataContractCriticalHelper(
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
Type type,
- CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string? deserializationExceptionMessage)
+ CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string? serializationExceptionMessage, string? deserializationExceptionMessage)
: base(type)
{
if (getEnumeratorMethod == null)
@@ -593,10 +524,11 @@ internal CollectionDataContractCriticalHelper(
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionMustHaveItemType, GetClrTypeFullName(type))));
CollectionDataContractAttribute? collectionContractAttribute;
- this.StableName = DataContract.GetCollectionStableName(type, itemType, out collectionContractAttribute);
+ XmlName = DataContract.GetCollectionXmlName(type, itemType, out collectionContractAttribute);
Init(kind, itemType, collectionContractAttribute);
_getEnumeratorMethod = getEnumeratorMethod;
+ _serializationExceptionMessage = serializationExceptionMessage;
_deserializationExceptionMessage = deserializationExceptionMessage;
}
@@ -605,20 +537,12 @@ internal CollectionDataContractCriticalHelper(
internal CollectionDataContractCriticalHelper(
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
Type type,
- CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo? addMethod, ConstructorInfo? constructor) : base(type)
+ CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo? addMethod, ConstructorInfo? constructor)
+ : this(type, kind, itemType, getEnumeratorMethod, (string?)null, (string?)null)
{
- if (getEnumeratorMethod == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionMustHaveGetEnumeratorMethod, DataContract.GetClrTypeFullName(type))));
if (addMethod == null && !type.IsInterface)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(type))));
- if (itemType == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionMustHaveItemType, DataContract.GetClrTypeFullName(type))));
-
- CollectionDataContractAttribute? collectionContractAttribute;
- this.StableName = DataContract.GetCollectionStableName(type, itemType, out collectionContractAttribute);
- Init(kind, itemType, collectionContractAttribute);
- _getEnumeratorMethod = getEnumeratorMethod;
_addMethod = addMethod;
_constructor = constructor;
}
@@ -641,16 +565,9 @@ internal CollectionDataContractCriticalHelper(
_invalidCollectionInSharedContractMessage = invalidCollectionInSharedContractMessage;
}
- internal CollectionKind Kind
- {
- get { return _kind; }
- }
+ internal CollectionKind Kind => _kind;
- internal Type ItemType
- {
- get { return _itemType; }
- set { _itemType = value; }
- }
+ internal Type ItemType => _itemType;
internal DataContract ItemContract
{
@@ -675,9 +592,7 @@ internal DataContract ItemContract
}
else
{
- _itemContract =
- DataContract.GetDataContractFromGeneratedAssembly(ItemType) ??
- DataContract.GetDataContract(ItemType);
+ _itemContract = DataContract.GetDataContract(ItemType);
}
}
return _itemContract;
@@ -690,53 +605,52 @@ internal DataContract ItemContract
internal DataContract? SharedTypeContract
{
- get { return _sharedTypeContract; }
- set { _sharedTypeContract = value; }
+ get => _sharedTypeContract;
+ set => _sharedTypeContract = value;
}
internal string ItemName
{
- get { return _itemName; }
- set { _itemName = value; }
+ get => _itemName;
+ set => _itemName = value;
}
internal bool IsConstructorCheckRequired
{
- get { return _isConstructorCheckRequired; }
- set { _isConstructorCheckRequired = value; }
+ get => _isConstructorCheckRequired;
+ set => _isConstructorCheckRequired = value;
}
- public XmlDictionaryString CollectionItemName
- {
- get { return _collectionItemName; }
- }
+ internal XmlDictionaryString CollectionItemName => _collectionItemName;
internal string? KeyName
{
- get { return _keyName; }
- set { _keyName = value; }
+ get => _keyName;
+ set => _keyName = value;
}
internal string? ValueName
{
- get { return _valueName; }
- set { _valueName = value; }
+ get => _valueName;
+ set => _valueName = value;
}
internal bool IsDictionary => KeyName != null;
- public string? DeserializationExceptionMessage => _deserializationExceptionMessage;
+ internal string? SerializationExceptionMessage => _serializationExceptionMessage;
+
+ internal string? DeserializationExceptionMessage => _deserializationExceptionMessage;
- public XmlDictionaryString? ChildElementNamespace
+ internal XmlDictionaryString? ChildElementNamespace
{
- get { return _childElementNamespace; }
- set { _childElementNamespace = value; }
+ get => _childElementNamespace;
+ set => _childElementNamespace = value;
}
internal bool IsItemTypeNullable
{
- get { return _isItemTypeNullable; }
- set { _isItemTypeNullable = value; }
+ get => _isItemTypeNullable;
+ set => _isItemTypeNullable = value;
}
internal MethodInfo? GetEnumeratorMethod => _getEnumeratorMethod;
@@ -756,10 +670,11 @@ internal override DataContractDictionary? KnownDataContracts
{
if (!_isKnownTypeAttributeChecked)
{
- _knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
+ _knownDataContracts = DataContract.ImportKnownTypeAttributes(UnderlyingType);
Interlocked.MemoryBarrier();
_isKnownTypeAttributeChecked = true;
}
+ _knownDataContracts ??= new DataContractDictionary();
}
}
return _knownDataContracts;
@@ -775,20 +690,20 @@ internal override DataContractDictionary? KnownDataContracts
internal XmlFormatCollectionWriterDelegate? XmlFormatWriterDelegate
{
- get { return _xmlFormatWriterDelegate; }
- set { _xmlFormatWriterDelegate = value; }
+ get => _xmlFormatWriterDelegate;
+ set => _xmlFormatWriterDelegate = value;
}
internal XmlFormatCollectionReaderDelegate? XmlFormatReaderDelegate
{
- get { return _xmlFormatReaderDelegate; }
- set { _xmlFormatReaderDelegate = value; }
+ get => _xmlFormatReaderDelegate;
+ set => _xmlFormatReaderDelegate = value;
}
internal XmlFormatGetOnlyCollectionReaderDelegate? XmlFormatGetOnlyCollectionReaderDelegate
{
- get { return _xmlFormatGetOnlyCollectionReaderDelegate; }
- set { _xmlFormatGetOnlyCollectionReaderDelegate = value; }
+ get => _xmlFormatGetOnlyCollectionReaderDelegate;
+ set => _xmlFormatGetOnlyCollectionReaderDelegate = value;
}
private delegate void IncrementCollectionCountDelegate(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context);
@@ -816,13 +731,13 @@ internal void IncrementCollectionCount(XmlWriterDelegator xmlWriter, object obj,
case CollectionKind.GenericCollection:
case CollectionKind.GenericList:
{
- var buildIncrementCollectionCountDelegate = GetBuildIncrementCollectionCountGenericDelegate(ItemType);
+ MethodInfo? buildIncrementCollectionCountDelegate = GetBuildIncrementCollectionCountGenericDelegate(ItemType);
_incrementCollectionCountDelegate = (IncrementCollectionCountDelegate)buildIncrementCollectionCountDelegate.Invoke(null, Array.Empty())!;
}
break;
case CollectionKind.GenericDictionary:
{
- var buildIncrementCollectionCountDelegate = GetBuildIncrementCollectionCountGenericDelegate(typeof(KeyValuePair<,>).MakeGenericType(ItemType.GetGenericArguments()));
+ MethodInfo? buildIncrementCollectionCountDelegate = GetBuildIncrementCollectionCountGenericDelegate(typeof(KeyValuePair<,>).MakeGenericType(ItemType.GetGenericArguments()));
_incrementCollectionCountDelegate = (IncrementCollectionCountDelegate)buildIncrementCollectionCountDelegate.Invoke(null, Array.Empty())!;
}
break;
@@ -868,7 +783,7 @@ internal IEnumerator GetEnumeratorForCollection(object obj)
{
if (_createGenericDictionaryEnumeratorDelegate == null)
{
- var keyValueTypes = ItemType.GetGenericArguments();
+ Type[]? keyValueTypes = ItemType.GetGenericArguments();
MethodInfo buildCreateGenericDictionaryEnumerator = GetBuildCreateGenericDictionaryEnumeratorGenericMethod(keyValueTypes);
_createGenericDictionaryEnumeratorDelegate = (CreateGenericDictionaryEnumeratorDelegate)buildCreateGenericDictionaryEnumerator.Invoke(null, Array.Empty())!;
}
@@ -962,7 +877,7 @@ private static CreateGenericDictionaryEnumeratorDelegate BuildCreateGenericDicti
{
return this;
}
- if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
+ if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false))
{
return new ClassDataContract(type);
}
@@ -989,20 +904,20 @@ internal static bool IsCollection(Type type, [NotNullWhen(true)] out Type? itemT
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static bool IsCollection(Type type, bool constructorRequired)
+ internal static bool IsCollection(Type type, bool constructorRequired, bool skipIfReadOnlyContract)
{
- return IsCollectionHelper(type, out _, constructorRequired);
+ return IsCollectionHelper(type, out _, constructorRequired, skipIfReadOnlyContract);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static bool IsCollectionHelper(Type type, [NotNullWhen(true)] out Type? itemType, bool constructorRequired)
+ private static bool IsCollectionHelper(Type type, [NotNullWhen(true)] out Type? itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
{
if (type.IsArray && DataContract.GetBuiltInDataContract(type) == null)
{
itemType = type.GetElementType()!;
return true;
}
- return IsCollectionOrTryCreate(type, tryCreate: false, out _, out itemType, constructorRequired);
+ return IsCollectionOrTryCreate(type, tryCreate: false, out _, out itemType, constructorRequired, skipIfReadOnlyContract);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -1012,7 +927,7 @@ internal static bool TryCreate(Type type, [NotNullWhen(true)] out DataContract?
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static bool CreateGetOnlyCollectionDataContract(Type type, [NotNullWhen(true)] out DataContract? dataContract)
+ internal static bool TryCreateGetOnlyCollectionDataContract(Type type, [NotNullWhen(true)] out DataContract? dataContract)
{
if (type.IsArray)
{
@@ -1025,36 +940,6 @@ internal static bool CreateGetOnlyCollectionDataContract(Type type, [NotNullWhen
}
}
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static bool TryCreateGetOnlyCollectionDataContract(Type type, [NotNullWhen(true)] out DataContract? dataContract)
- {
- dataContract = DataContract.GetDataContractFromGeneratedAssembly(type);
- if (dataContract == null)
- {
- if (type.IsArray)
- {
- dataContract = new CollectionDataContract(type);
- return true;
- }
- else
- {
- return IsCollectionOrTryCreate(type, tryCreate: true, out dataContract!, out _, constructorRequired: false);
- }
- }
- else
- {
- if (dataContract is CollectionDataContract)
- {
- return true;
- }
- else
- {
- dataContract = null;
- return false;
- }
- }
- }
-
// Once https://github.com/mono/linker/issues/1731 is fixed we can remove the suppression from here as it won't be needed any longer.
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:GetMethod",
Justification = "The DynamicallyAccessedMembers declarations will ensure the interface methods will be preserved.")]
@@ -1074,7 +959,7 @@ private static bool IsArraySegment(Type t)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataContract? dataContract, out Type itemType, bool constructorRequired)
+ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataContract? dataContract, out Type itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
{
dataContract = null;
itemType = Globals.TypeOfObject;
@@ -1088,6 +973,7 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
MethodInfo? addMethod, getEnumeratorMethod;
bool hasCollectionDataContract = IsCollectionDataContract(type);
bool isReadOnlyContract = false;
+ string? serializationExceptionMessage = null;
string? deserializationExceptionMessage = null;
Type? baseType = type.BaseType;
bool isBaseTypeCollection = (baseType != null && baseType != Globals.TypeOfObject
@@ -1184,7 +1070,7 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
else
{
isReadOnlyContract = true;
- GetReadOnlyCollectionExceptionMessages(type, SR.CollectionTypeDoesNotHaveDefaultCtor, null, out deserializationExceptionMessage);
+ GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveDefaultCtor, null, out serializationExceptionMessage, out deserializationExceptionMessage);
}
}
}
@@ -1238,22 +1124,22 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
// All collection types could be considered read-only collections except collection types that are marked [Serializable].
// Collection types marked [Serializable] cannot be read-only collections for backward compatibility reasons.
// DataContract types and POCO types cannot be collection types, so they don't need to be factored in.
- if (type.IsSerializable)
+ if (type.IsSerializable || skipIfReadOnlyContract)
{
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
+ return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException && !skipIfReadOnlyContract,
SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), ref dataContract);
}
else
{
isReadOnlyContract = true;
- GetReadOnlyCollectionExceptionMessages(type, SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), out deserializationExceptionMessage);
+ GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), out serializationExceptionMessage, out deserializationExceptionMessage);
}
}
if (tryCreate)
{
dataContract = isReadOnlyContract ?
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, deserializationExceptionMessage) :
+ new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
}
}
@@ -1298,12 +1184,12 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
Debug.Assert(getEnumeratorMethod != null);
dataContract = isReadOnlyContract ?
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, deserializationExceptionMessage) :
+ new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
}
}
- return true;
+ return !(isReadOnlyContract && skipIfReadOnlyContract);
}
internal static bool IsCollectionDataContract(Type type)
@@ -1331,8 +1217,9 @@ private static bool HandleIfInvalidCollection(Type type, bool tryCreate, bool ha
return false;
}
- private static void GetReadOnlyCollectionExceptionMessages(Type type, string message, string? param, out string deserializationExceptionMessage)
+ private static void GetReadOnlyCollectionExceptionMessages(Type type, bool hasCollectionDataContract, string message, string? param, out string serializationExceptionMessage, out string deserializationExceptionMessage)
{
+ serializationExceptionMessage = GetInvalidCollectionMessage(message, SR.Format(hasCollectionDataContract ? SR.InvalidCollectionDataContract : SR.InvalidCollectionType, GetClrTypeFullName(type)), param);
deserializationExceptionMessage = GetInvalidCollectionMessage(message, SR.Format(SR.ReadOnlyCollectionDeserialization, GetClrTypeFullName(type)), param);
}
@@ -1435,36 +1322,64 @@ private static bool IsKnownInterface(Type type)
return false;
}
- internal override DataContract GetValidContract(SerializationMode mode)
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary? boundContracts = null)
{
- if (InvalidCollectionInSharedContractMessage != null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(InvalidCollectionInSharedContractMessage));
+ DataContract boundContract;
+ if (boundContracts != null && boundContracts.TryGetValue(this, out boundContract!))
+ return boundContract;
- return this;
+ // This type-binding ('boundType') stuff is new. We did not do this in NetFx. We used to use default contract constructors and let the
+ // underlying type get filled in later. But default constructors for DataContracts runs afoul of requiring an underlying type. Our web of nullable
+ // notations make it hard to get around. But it also allows us to feel good about using .UnderlyingType from matching parameter contracts.
+ Type type = UnderlyingType;
+ Type[] paramTypes = type.GetGenericArguments();
+ for (int i = 0; i < paramTypes.Length; i++)
+ {
+ if (paramTypes[i].IsGenericParameter)
+ paramTypes[i] = paramContracts[paramTypes[i].GenericParameterPosition].UnderlyingType;
+ }
+ Type boundType = type.MakeGenericType(paramTypes);
+
+ CollectionDataContract boundCollectionContract = new CollectionDataContract(boundType);
+ boundContracts ??= new Dictionary();
+ boundContracts.Add(this, boundCollectionContract);
+ boundCollectionContract.ItemContract = ItemContract.BindGenericParameters(paramContracts, boundContracts);
+ boundCollectionContract.IsItemTypeNullable = !boundCollectionContract.ItemContract.IsValueType;
+ boundCollectionContract.ItemName = ItemNameSetExplicit ? ItemName : boundCollectionContract.ItemContract.XmlName.Name;
+ boundCollectionContract.KeyName = KeyName;
+ boundCollectionContract.ValueName = ValueName;
+ boundCollectionContract.XmlName = CreateQualifiedName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(XmlName.Name), new GenericNameProvider(DataContract.GetClrTypeFullName(UnderlyingType), paramContracts)),
+ IsCollectionDataContract(UnderlyingType) ? XmlName.Namespace : DataContract.GetCollectionNamespace(boundCollectionContract.ItemContract.XmlName.Namespace));
+ return boundCollectionContract;
}
- internal override DataContract GetValidContract()
+ internal override DataContract GetValidContract(bool verifyConstructor = false)
{
- if (this.IsConstructorCheckRequired)
+ if (verifyConstructor && IsConstructorCheckRequired)
{
CheckConstructor();
+ return this;
}
+
+ if (InvalidCollectionInSharedContractMessage != null)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(InvalidCollectionInSharedContractMessage));
return this;
}
private void CheckConstructor()
{
- if (this.Constructor == null)
+ if (Constructor == null)
{
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionTypeDoesNotHaveDefaultCtor, DataContract.GetClrTypeFullName(this.UnderlyingType))));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionTypeDoesNotHaveDefaultCtor, DataContract.GetClrTypeFullName(UnderlyingType))));
}
else
{
- this.IsConstructorCheckRequired = false;
+ IsConstructorCheckRequired = false;
}
}
- internal override bool IsValidContract(SerializationMode mode)
+ internal override bool IsValidContract()
{
return (InvalidCollectionInSharedContractMessage == null);
}
@@ -1512,7 +1427,7 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
}
return true;
}
- if (MethodRequiresMemberAccess(this.AddMethod))
+ if (MethodRequiresMemberAccess(AddMethod))
{
if (securityException != null)
{
@@ -1520,7 +1435,7 @@ internal bool RequiresMemberAccessForRead(SecurityException? securityException)
new SecurityException(SR.Format(
SR.PartialTrustCollectionContractAddMethodNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
- this.AddMethod!.Name),
+ AddMethod!.Name),
securityException));
}
return true;
@@ -1564,8 +1479,31 @@ internal bool RequiresMemberAccessForWrite(SecurityException? securityException)
return false;
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All ctor's required to create an instance of this type are marked with RequiresUnreferencedCode.")]
+ internal override bool Equals(object? other, HashSet? checkedContracts)
+ {
+ if (IsEqualOrChecked(other, checkedContracts))
+ return true;
+
+ if (base.Equals(other, checkedContracts))
+ {
+ if (other is CollectionDataContract dataContract)
+ {
+ bool thisItemTypeIsNullable = (ItemContract == null) ? false : !ItemContract.IsValueType;
+ bool otherItemTypeIsNullable = (dataContract.ItemContract == null) ? false : !dataContract.ItemContract.IsValueType;
+ return ItemName == dataContract.ItemName &&
+ (IsItemTypeNullable || thisItemTypeIsNullable) == (dataContract.IsItemTypeNullable || otherItemTypeIsNullable) &&
+ ItemContract != null && ItemContract.Equals(dataContract.ItemContract, checkedContracts);
+ }
+ }
+ return false;
+ }
+
+ public override int GetHashCode() => base.GetHashCode();
+
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
+ internal override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
{
Debug.Assert(context != null);
@@ -1575,7 +1513,7 @@ public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, Xml
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
+ internal override object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
{
Debug.Assert(context != null);
@@ -1614,15 +1552,9 @@ public bool MoveNext()
return _enumerator.MoveNext();
}
- public KeyValue Current
- {
- get { return new KeyValue(_enumerator.Key, _enumerator.Value); }
- }
+ public KeyValue Current => new KeyValue(_enumerator.Key, _enumerator.Value);
- object System.Collections.IEnumerator.Current
- {
- get { return Current; }
- }
+ object System.Collections.IEnumerator.Current => Current;
public void Reset()
{
@@ -1658,10 +1590,7 @@ public KeyValue Current
}
}
- object System.Collections.IEnumerator.Current
- {
- get { return Current; }
- }
+ object System.Collections.IEnumerator.Current => Current;
public void Reset()
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
index f859f2f518cef..d61002c23a123 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs
@@ -3,39 +3,40 @@
using System;
using System.Buffers.Binary;
-using System.Collections.Concurrent;
+using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.Serialization.DataContracts;
using System.Text;
-using System.Text.RegularExpressions;
using System.Xml;
-using System.Xml.Schema;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
-namespace System.Runtime.Serialization
+using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+namespace System.Runtime.Serialization.DataContracts
{
- internal abstract class DataContract
+ public abstract class DataContract
{
- private XmlDictionaryString _name;
-
- private XmlDictionaryString _ns;
-
- // this the global dictionary for data contracts introduced for multi-file.
- private static readonly Dictionary s_dataContracts = new Dictionary();
-
internal const string SerializerTrimmerWarning = "Data Contract Serialization and Deserialization might require types that cannot be statically analyzed. Make sure all of the " +
"required types are preserved.";
- public static Dictionary GetDataContracts()
- {
- return s_dataContracts;
- }
+ internal const DynamicallyAccessedMemberTypes DataContractPreserveMemberTypes =
+ DynamicallyAccessedMemberTypes.PublicMethods |
+ DynamicallyAccessedMemberTypes.NonPublicMethods |
+ DynamicallyAccessedMemberTypes.PublicConstructors |
+ DynamicallyAccessedMemberTypes.NonPublicConstructors |
+ DynamicallyAccessedMemberTypes.PublicFields |
+ DynamicallyAccessedMemberTypes.PublicProperties;
+
+ internal static ReadOnlyCollection s_emptyDataMemberList = new List().AsReadOnly();
+ private XmlDictionaryString _name;
+ private XmlDictionaryString _ns;
private readonly DataContractCriticalHelper _helper;
internal DataContract(DataContractCriticalHelper helper)
@@ -45,29 +46,9 @@ internal DataContract(DataContractCriticalHelper helper)
_ns = helper.Namespace;
}
- private static DataContract? GetGeneratedDataContract(Type type)
- {
- // this method used to be rewritten by an IL transform
- // with the restructuring for multi-file, it has become a regular method
- DataContract? result;
- return s_dataContracts.TryGetValue(type, out result) ? result : null;
- }
-
- internal static bool TryGetDataContractFromGeneratedAssembly(Type type, out DataContract? dataContract)
- {
- dataContract = GetGeneratedDataContract(type);
- return dataContract != null;
- }
+ public virtual string? ContractType => null;
- internal static DataContract? GetDataContractFromGeneratedAssembly(Type? type)
- {
- return null;
- }
-
- internal MethodInfo? ParseMethod
- {
- get { return _helper.ParseMethod; }
- }
+ internal MethodInfo? ParseMethod => _helper.ParseMethod;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal static DataContract GetDataContract(Type type)
@@ -76,24 +57,18 @@ internal static DataContract GetDataContract(Type type)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
- {
- return GetDataContract(typeHandle, type, SerializationMode.SharedContract);
- }
-
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type? type, SerializationMode mode)
+ internal static DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type? type)
{
int id = GetId(typeHandle);
DataContract dataContract = GetDataContractSkipValidation(id, typeHandle, null);
- return dataContract.GetValidContract(mode);
+ return dataContract.GetValidContract();
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle, SerializationMode mode)
+ internal static DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
{
DataContract dataContract = GetDataContractSkipValidation(id, typeHandle, null);
- return dataContract.GetValidContract(mode);
+ return dataContract.GetValidContract();
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -103,10 +78,10 @@ internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHa
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetGetOnlyCollectionDataContract(int id, RuntimeTypeHandle typeHandle, Type? type, SerializationMode mode)
+ internal static DataContract GetGetOnlyCollectionDataContract(int id, RuntimeTypeHandle typeHandle, Type? type)
{
DataContract dataContract = GetGetOnlyCollectionDataContractSkipValidation(id, typeHandle, type);
- dataContract = dataContract.GetValidContract(mode);
+ dataContract = dataContract.GetValidContract();
if (dataContract is ClassDataContract)
{
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.ErrorDeserializing, SR.Format(SR.ErrorTypeInfo, DataContract.GetClrTypeFullName(dataContract.UnderlyingType)), SR.Format(SR.NoSetMethodForProperty, string.Empty, string.Empty))));
@@ -136,7 +111,7 @@ internal static int GetId(RuntimeTypeHandle typeHandle)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static DataContract? GetBuiltInDataContract(Type type)
+ internal static DataContract? GetBuiltInDataContract(Type type)
{
return DataContractCriticalHelper.GetBuiltInDataContract(type);
}
@@ -148,7 +123,7 @@ internal static int GetId(RuntimeTypeHandle typeHandle)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static DataContract? GetBuiltInDataContract(string typeName)
+ internal static DataContract? GetBuiltInDataContract(string typeName)
{
return DataContractCriticalHelper.GetBuiltInDataContract(typeName);
}
@@ -169,157 +144,118 @@ internal static void ThrowInvalidDataContractException(string? message, Type? ty
DataContractCriticalHelper.ThrowInvalidDataContractException(message, type);
}
- protected DataContractCriticalHelper Helper
- {
- get
- { return _helper; }
- }
+ internal DataContractCriticalHelper Helper => _helper;
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
- public Type UnderlyingType
- {
- get
- { return _helper.UnderlyingType; }
- set { _helper.UnderlyingType = value; }
- }
+ public virtual Type UnderlyingType => _helper.UnderlyingType;
- public Type OriginalUnderlyingType
- {
- get { return _helper.OriginalUnderlyingType; }
- set { _helper.OriginalUnderlyingType = value; }
- }
+ public virtual Type OriginalUnderlyingType => _helper.OriginalUnderlyingType;
- public virtual bool IsBuiltInDataContract
- {
- get
- { return _helper.IsBuiltInDataContract; }
- set { }
- }
+ public virtual bool IsBuiltInDataContract => _helper.IsBuiltInDataContract;
- internal Type TypeForInitialization
- {
- get
- { return _helper.TypeForInitialization; }
- }
+ internal Type TypeForInitialization => _helper.TypeForInitialization;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public virtual void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
+ internal virtual void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
{
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public virtual object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
+ internal virtual object? ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
{
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public virtual void WriteXmlElement(XmlWriterDelegator xmlWriter, object? obj, XmlObjectSerializerWriteContext context, XmlDictionaryString name, XmlDictionaryString? ns)
+ internal virtual void WriteXmlElement(XmlWriterDelegator xmlWriter, object? obj, XmlObjectSerializerWriteContext context, XmlDictionaryString name, XmlDictionaryString? ns)
{
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
- public virtual object ReadXmlElement(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
+ internal virtual object ReadXmlElement(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
{
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
- public bool IsValueType
+ public virtual bool IsValueType
{
- get
- { return _helper.IsValueType; }
-
- set
- { _helper.IsValueType = value; }
+ get => _helper.IsValueType;
+ internal set => _helper.IsValueType = value;
}
- public bool IsReference
+ public virtual bool IsReference
{
- get
- { return _helper.IsReference; }
-
- set
- { _helper.IsReference = value; }
+ get => _helper.IsReference;
+ internal set => _helper.IsReference = value;
}
- public XmlQualifiedName StableName
+ public virtual XmlQualifiedName XmlName
{
- get
- { return _helper.StableName; }
-
- set
- { _helper.StableName = value; }
+ get => _helper.XmlName;
+ internal set => _helper.XmlName = value;
}
- public virtual DataContractDictionary? KnownDataContracts
+ public virtual DataContract? BaseContract
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- { return _helper.KnownDataContracts; }
-
- set
- { _helper.KnownDataContracts = value; }
+ get => null;
}
- public virtual bool IsISerializable
+ internal GenericInfo? GenericInfo
{
- get { return _helper.IsISerializable; }
-
- set { _helper.IsISerializable = value; }
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get => _helper.GenericInfo;
+ set => _helper.GenericInfo = value;
}
- public XmlDictionaryString Name
+ public virtual DataContractDictionary? KnownDataContracts
{
- get
- { return _name; }
- set { _name = value; }
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get => _helper.KnownDataContracts;
+ internal set => _helper.KnownDataContracts = value;
}
- public virtual XmlDictionaryString Namespace
+ public virtual bool IsISerializable
{
- get
- { return _ns; }
- set { _ns = value; }
+ get => _helper.IsISerializable;
+ internal set => _helper.IsISerializable = value;
}
- public virtual bool HasRoot
- {
- get
- { return true; }
+ internal XmlDictionaryString Name => _name;
+
+ internal virtual XmlDictionaryString Namespace => _ns;
- set
- { }
+ internal virtual bool HasRoot
+ {
+ get => _helper.HasRoot;
+ set => _helper.HasRoot = value;
}
public virtual XmlDictionaryString? TopLevelElementName
{
- get
- { return _helper.TopLevelElementName; }
-
- set
- { _helper.TopLevelElementName = value; }
+ get => _helper.TopLevelElementName;
+ internal set => _helper.TopLevelElementName = value;
}
public virtual XmlDictionaryString? TopLevelElementNamespace
{
- get
- { return _helper.TopLevelElementNamespace; }
-
- set
- { _helper.TopLevelElementNamespace = value; }
+ get => _helper.TopLevelElementNamespace;
+ internal set => _helper.TopLevelElementNamespace = value;
}
- internal virtual bool CanContainReferences
- {
- get { return true; }
- }
+ internal virtual bool CanContainReferences => true;
- internal virtual bool IsPrimitive
+ internal virtual bool IsPrimitive => false;
+
+ public virtual bool IsDictionaryLike([NotNullWhen(true)] out string? keyName, [NotNullWhen(true)] out string? valueName, [NotNullWhen(true)] out string? itemName)
{
- get { return false; }
+ keyName = valueName = itemName = null;
+ return false;
}
+ public virtual ReadOnlyCollection DataMembers => s_emptyDataMemberList;
+
internal virtual void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryString name, XmlDictionaryString? ns)
{
if (object.ReferenceEquals(ns, DictionaryGlobals.SerializationNamespace) && !IsPrimitive)
@@ -328,32 +264,36 @@ internal virtual void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryS
writer.WriteStartElement(name, ns);
}
- internal virtual DataContract GetValidContract(SerializationMode mode)
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal virtual DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary? boundContracts = null)
{
return this;
}
- internal virtual DataContract GetValidContract()
+ internal virtual DataContract GetValidContract(bool verifyConstructor = false)
{
return this;
}
- internal virtual bool IsValidContract(SerializationMode mode)
+ internal virtual bool IsValidContract()
{
return true;
}
internal class DataContractCriticalHelper
{
- private static readonly Dictionary s_typeToIDCache = new Dictionary(new TypeHandleRefEqualityComparer());
+ private static readonly Hashtable s_typeToIDCache = new Hashtable(new HashTableEqualityComparer());
private static DataContract[] s_dataContractCache = new DataContract[32];
private static int s_dataContractID;
private static Dictionary? s_typeToBuiltInContract;
private static Dictionary? s_nameToBuiltInContract;
- private static Dictionary? s_namespaces;
+ private static Dictionary? s_typeNameToBuiltInContract;
+ private static Hashtable s_namespaces = new Hashtable();
private static Dictionary? s_clrTypeStrings;
private static XmlDictionary? s_clrTypeStringsDictionary;
- private static readonly TypeHandleRef s_typeHandleRef = new TypeHandleRef();
+
+ [ThreadStatic]
+ private static TypeHandleRef? s_typeHandleRef;
private static readonly object s_cacheLock = new object();
private static readonly object s_createDataContractLock = new object();
@@ -362,11 +302,11 @@ internal class DataContractCriticalHelper
private static readonly object s_clrTypeStringsLock = new object();
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
- private Type _underlyingType;
+ private readonly Type _underlyingType;
private Type? _originalUnderlyingType;
- private bool _isReference;
private bool _isValueType;
- private XmlQualifiedName _stableName = null!; // StableName is always set in concrete ctors set except for the "invalid" CollectionDataContract
+ private GenericInfo? _genericInfo;
+ private XmlQualifiedName _xmlName = null!; // XmlName is always set in concrete ctors set except for the "invalid" CollectionDataContract
private XmlDictionaryString _name = null!; // Name is always set in concrete ctors set except for the "invalid" CollectionDataContract
private XmlDictionaryString _ns = null!; // Namespace is always set in concrete ctors set except for the "invalid" CollectionDataContract
@@ -385,11 +325,10 @@ internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHa
if (dataContract == null)
{
dataContract = CreateDataContract(id, typeHandle, type);
- AssignDataContractToId(dataContract, id);
}
else
{
- return dataContract.GetValidContract();
+ return dataContract.GetValidContract(verifyConstructor: true);
}
return dataContract;
}
@@ -401,7 +340,6 @@ internal static DataContract GetGetOnlyCollectionDataContractSkipValidation(int
if (dataContract == null)
{
dataContract = CreateGetOnlyCollectionDataContract(id, typeHandle, type);
- s_dataContractCache[id] = dataContract;
}
return dataContract;
}
@@ -418,7 +356,7 @@ internal static DataContract GetDataContractForInitialization(int id)
internal static int GetIdForInitialization(ClassDataContract classContract)
{
- int id = DataContract.GetId(classContract.TypeForInitialization!.TypeHandle);
+ int id = DataContract.GetId(classContract.TypeForInitialization.TypeHandle);
if (id < s_dataContractCache.Length && ContractMatches(classContract, s_dataContractCache[id]))
{
return id;
@@ -441,35 +379,45 @@ private static bool ContractMatches(DataContract contract, DataContract cachedCo
internal static int GetId(RuntimeTypeHandle typeHandle)
{
- lock (s_cacheLock)
+ typeHandle = GetDataContractAdapterTypeHandle(typeHandle);
+ s_typeHandleRef ??= new TypeHandleRef();
+ s_typeHandleRef.Value = typeHandle;
+
+ object? value = s_typeToIDCache[s_typeHandleRef];
+ if (value != null)
+ return ((IntRef)value).Value;
+
+ try
{
- IntRef? id;
- typeHandle = GetDataContractAdapterTypeHandle(typeHandle);
- s_typeHandleRef.Value = typeHandle;
- if (!s_typeToIDCache.TryGetValue(s_typeHandleRef, out id))
+ lock (s_cacheLock)
{
- int value = s_dataContractID++;
- if (value >= s_dataContractCache.Length)
+ value = s_typeToIDCache[s_typeHandleRef];
+ if (value != null)
+ return ((IntRef)value).Value;
+
+ int nextId = s_dataContractID++;
+ if (nextId >= s_dataContractCache.Length)
{
- int newSize = (value < int.MaxValue / 2) ? value * 2 : int.MaxValue;
- if (newSize <= value)
+ int newSize = (nextId < int.MaxValue / 2) ? nextId * 2 : int.MaxValue;
+ if (newSize <= nextId)
{
DiagnosticUtility.DebugAssert("DataContract cache overflow");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.DataContractCacheOverflow));
}
Array.Resize(ref s_dataContractCache, newSize);
}
- id = new IntRef(value);
- try
- {
- s_typeToIDCache.Add(new TypeHandleRef(typeHandle), id);
- }
- catch (Exception ex)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
- }
+ IntRef id = new IntRef(nextId);
+
+ s_typeToIDCache.Add(new TypeHandleRef(typeHandle), id);
+ return id.Value;
}
- return id.Value;
+ }
+ catch (Exception ex)
+ {
+ if (Fx.IsFatal(ex))
+ throw;
+
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
}
@@ -486,16 +434,8 @@ private static DataContract CreateDataContract(int id, RuntimeTypeHandle typeHan
if (dataContract == null)
{
type ??= Type.GetTypeFromHandle(typeHandle)!;
- type = UnwrapNullableType(type);
-
- dataContract = DataContract.GetDataContractFromGeneratedAssembly(type);
- if (dataContract != null)
- {
- AssignDataContractToId(dataContract, id);
- return dataContract;
- }
-
dataContract = CreateDataContract(type);
+ AssignDataContractToId(dataContract, id);
}
}
}
@@ -517,18 +457,18 @@ private static DataContract CreateDataContract(Type type)
dataContract = new CollectionDataContract(type);
else if (type.IsEnum)
dataContract = new EnumDataContract(type);
+ else if (type.IsGenericParameter)
+ dataContract = new GenericParameterDataContract(type);
else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
dataContract = new XmlDataContract(type);
- else if (Globals.TypeOfScriptObject_IsAssignableFrom(type))
- dataContract = Globals.CreateScriptObjectClassDataContract();
else
{
- //if (type.ContainsGenericParameters)
- // ThrowInvalidDataContractException(SR.Format(SR.TypeMustNotBeOpenGeneric, type), type);
+ if (type.IsPointer)
+ type = Globals.TypeOfReflectionPointer;
if (!CollectionDataContract.TryCreate(type, out dataContract))
{
- if (!type.IsSerializable && !type.IsDefined(Globals.TypeOfDataContractAttribute, false) && !ClassDataContract.IsNonAttributedTypeValidForSerialization(type) && !ClassDataContract.IsKnownSerializableType(type))
+ if (!type.IsSerializable && !type.IsDefined(Globals.TypeOfDataContractAttribute, false) && !ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
{
ThrowInvalidDataContractException(SR.Format(SR.TypeNotSerializable, type), type);
}
@@ -536,10 +476,10 @@ private static DataContract CreateDataContract(Type type)
if (type != originalType)
{
var originalDataContract = new ClassDataContract(originalType);
- if (dataContract.StableName != originalDataContract.StableName)
+ if (dataContract.XmlName != originalDataContract.XmlName)
{
- // for non-DC types, type adapters will not have the same stable name (contract name).
- dataContract.StableName = originalDataContract.StableName;
+ // for non-DC types, type adapters will not have the same xml name (contract name).
+ dataContract.XmlName = originalDataContract.XmlName;
}
}
}
@@ -574,8 +514,10 @@ private static DataContract CreateGetOnlyCollectionDataContract(int id, RuntimeT
{
ThrowInvalidDataContractException(SR.Format(SR.TypeNotSerializable, type), type);
}
+ AssignDataContractToId(dataContract, id);
}
}
+ // !; // If null after the lookup and creation attempts above, the 'ThrowInvalidDataContractException' kicks in.
return dataContract;
}
@@ -594,10 +536,6 @@ internal static Type GetDataContractAdapterType(Type type)
{
return Globals.TypeOfMemoryStreamAdapter;
}
- if (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfKeyValuePair)
- {
- return Globals.TypeOfKeyValuePairAdapter.MakeGenericType(type.GetGenericArguments());
- }
return type;
}
@@ -629,7 +567,7 @@ private static RuntimeTypeHandle GetDataContractAdapterTypeHandle(RuntimeTypeHan
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static DataContract? GetBuiltInDataContract(Type type)
+ internal static DataContract? GetBuiltInDataContract(Type type)
{
if (type.IsInterface && !CollectionDataContract.IsCollectionInterface(type))
type = Globals.TypeOfObject;
@@ -638,8 +576,7 @@ private static RuntimeTypeHandle GetDataContractAdapterTypeHandle(RuntimeTypeHan
{
s_typeToBuiltInContract ??= new Dictionary();
- DataContract? dataContract;
- if (!s_typeToBuiltInContract.TryGetValue(type, out dataContract))
+ if (!s_typeToBuiltInContract.TryGetValue(type, out DataContract? dataContract))
{
TryCreateBuiltInDataContract(type, out dataContract);
s_typeToBuiltInContract.Add(type, dataContract);
@@ -649,36 +586,35 @@ private static RuntimeTypeHandle GetDataContractAdapterTypeHandle(RuntimeTypeHan
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static DataContract? GetBuiltInDataContract(string name, string ns)
+ internal static DataContract? GetBuiltInDataContract(string name, string ns)
{
lock (s_initBuiltInContractsLock)
{
s_nameToBuiltInContract ??= new Dictionary();
- DataContract? dataContract;
XmlQualifiedName qname = new XmlQualifiedName(name, ns);
- if (!s_nameToBuiltInContract.TryGetValue(qname, out dataContract))
+ if (!s_nameToBuiltInContract.TryGetValue(qname, out DataContract? dataContract))
{
- TryCreateBuiltInDataContract(name, ns, out dataContract);
- s_nameToBuiltInContract.Add(qname, dataContract);
+ if (TryCreateBuiltInDataContract(name, ns, out dataContract))
+ {
+ s_nameToBuiltInContract.Add(qname, dataContract);
+ }
}
return dataContract;
}
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static DataContract? GetBuiltInDataContract(string typeName)
+ internal static DataContract? GetBuiltInDataContract(string typeName)
{
if (!typeName.StartsWith("System.", StringComparison.Ordinal))
return null;
lock (s_initBuiltInContractsLock)
{
- s_nameToBuiltInContract ??= new Dictionary();
+ s_typeNameToBuiltInContract ??= new Dictionary();
- DataContract? dataContract;
- XmlQualifiedName qname = new XmlQualifiedName(typeName);
- if (!s_nameToBuiltInContract.TryGetValue(qname, out dataContract))
+ if (!s_typeNameToBuiltInContract.TryGetValue(typeName, out DataContract? dataContract))
{
Type? type = null;
string name = typeName.Substring(7);
@@ -738,14 +674,14 @@ private static RuntimeTypeHandle GetDataContractAdapterTypeHandle(RuntimeTypeHan
if (type != null)
TryCreateBuiltInDataContract(type, out dataContract);
- s_nameToBuiltInContract.Add(qname, dataContract);
+ s_typeNameToBuiltInContract.Add(typeName, dataContract);
}
return dataContract;
}
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static bool TryCreateBuiltInDataContract(Type type, [NotNullWhen(true)] out DataContract? dataContract)
+ internal static bool TryCreateBuiltInDataContract(Type type, [NotNullWhen(true)] out DataContract? dataContract)
{
if (type.IsEnum) // Type.GetTypeCode will report Enums as TypeCode.IntXX
{
@@ -753,7 +689,7 @@ public static bool TryCreateBuiltInDataContract(Type type, [NotNullWhen(true)] o
return false;
}
dataContract = null;
- switch (type.GetTypeCode())
+ switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean:
dataContract = new BooleanDataContract();
@@ -827,7 +763,7 @@ public static bool TryCreateBuiltInDataContract(Type type, [NotNullWhen(true)] o
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public static bool TryCreateBuiltInDataContract(string name, string ns, [NotNullWhen(true)] out DataContract? dataContract)
+ internal static bool TryCreateBuiltInDataContract(string name, string ns, [NotNullWhen(true)] out DataContract? dataContract)
{
dataContract = null;
if (ns == DictionaryGlobals.SchemaNamespace.Value)
@@ -951,23 +887,30 @@ public static bool TryCreateBuiltInDataContract(string name, string ns, [NotNull
internal static string GetNamespace(string key)
{
- lock (s_namespacesLock)
+ object? value = s_namespaces[key];
+
+ if (value != null)
+ return (string)value;
+
+ try
{
- s_namespaces ??= new Dictionary();
- if (s_namespaces.TryGetValue(key, out string? value))
+ lock (s_namespacesLock)
{
- return value;
- }
+ value = s_namespaces[key];
+
+ if (value != null)
+ return (string)value;
- try
- {
s_namespaces.Add(key, key);
+ return key;
}
- catch (Exception ex)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
- }
- return key;
+ }
+ catch (Exception ex)
+ {
+ if (Fx.IsFatal(ex))
+ throw;
+
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
}
@@ -985,11 +928,13 @@ internal static XmlDictionaryString GetClrTypeString(string key)
}
catch (Exception ex)
{
+ if (Fx.IsFatal(ex))
+ throw;
+
throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
}
- XmlDictionaryString? value;
- if (s_clrTypeStrings.TryGetValue(key, out value))
+ if (s_clrTypeStrings.TryGetValue(key, out XmlDictionaryString? value))
return value;
value = s_clrTypeStringsDictionary!.Add(key);
try
@@ -998,6 +943,9 @@ internal static XmlDictionaryString GetClrTypeString(string key)
}
catch (Exception ex)
{
+ if (Fx.IsFatal(ex))
+ throw;
+
throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
return value;
@@ -1011,14 +959,15 @@ internal static void ThrowInvalidDataContractException(string? message, Type? ty
{
lock (s_cacheLock)
{
+ s_typeHandleRef ??= new TypeHandleRef();
s_typeHandleRef.Value = GetDataContractAdapterTypeHandle(type.TypeHandle);
- try
- {
- s_typeToIDCache.Remove(s_typeHandleRef);
- }
- catch (Exception ex)
+
+ if (s_typeToIDCache.ContainsKey(s_typeHandleRef))
{
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
+ lock (s_cacheLock)
+ {
+ s_typeToIDCache.Remove(s_typeHandleRef);
+ }
}
}
}
@@ -1036,95 +985,78 @@ internal DataContractCriticalHelper(
}
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
- internal Type UnderlyingType
- {
- get { return _underlyingType; }
- set { _underlyingType = value; }
- }
+ internal Type UnderlyingType => _underlyingType;
- internal Type OriginalUnderlyingType
- {
- get => _originalUnderlyingType ??= GetDataContractOriginalType(this._underlyingType);
- set => _originalUnderlyingType = value;
- }
+ internal Type OriginalUnderlyingType => _originalUnderlyingType ??= GetDataContractOriginalType(_underlyingType);
- internal virtual bool IsBuiltInDataContract
- {
- get
- {
- return false;
- }
- }
+ internal virtual bool IsBuiltInDataContract => false;
- internal Type TypeForInitialization
- {
- get { return _typeForInitialization; }
- }
+ internal Type TypeForInitialization => _typeForInitialization;
[MemberNotNull(nameof(_typeForInitialization))]
private void SetTypeForInitialization(Type classType)
{
+ // TODO - This 'if' was not commented out in 4.8. But 4.8 was not dealing with nullable notations, which we do have here in Core.
+ // With the absence of schema importing, it does not make sense to have a data contract without a valid serializable underlying type. (Even
+ // with schema importing it doesn't make sense, but there is a building period while we're still figuring out all the data types and contracts
+ // where the underlying type may be null.) Anyway... might it make sense to re-instate this if clause - but use it to throw an exception if
+ // we don't meet the criteria? That way we can maintain nullable semantics and not do anything silly trying to keep them simple.
//if (classType.IsSerializable || classType.IsDefined(Globals.TypeOfDataContractAttribute, false))
{
_typeForInitialization = classType;
}
}
- internal bool IsReference
+ internal bool IsReference { get; set; }
+
+ internal bool IsValueType
{
- get { return _isReference; }
- set
- {
- _isReference = value;
- }
+ get => _isValueType;
+ set => _isValueType = value;
}
- internal bool IsValueType
+ internal XmlQualifiedName XmlName
{
- get { return _isValueType; }
- set { _isValueType = value; }
+ get => _xmlName;
+ set => _xmlName = value;
}
- internal XmlQualifiedName StableName
+ internal GenericInfo? GenericInfo
{
- get { return _stableName; }
- set { _stableName = value; }
+ get => _genericInfo;
+ set => _genericInfo = value;
}
internal virtual DataContractDictionary? KnownDataContracts
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get { return null; }
+ get => null;
set { /* do nothing */ }
}
internal virtual bool IsISerializable
{
- get { return false; }
- set { ThrowInvalidDataContractException(SR.RequiresClassDataContractToSetIsISerializable); }
+ get => false;
+ set => ThrowInvalidDataContractException(SR.RequiresClassDataContractToSetIsISerializable);
}
internal XmlDictionaryString Name
{
- get { return _name; }
- set { _name = value; }
+ get => _name;
+ set => _name = value;
}
- public XmlDictionaryString Namespace
+ internal XmlDictionaryString Namespace
{
- get { return _ns; }
- set { _ns = value; }
+ get => _ns;
+ set => _ns = value;
}
- internal virtual bool HasRoot
- {
- get { return true; }
- set { }
- }
+ internal virtual bool HasRoot { get; set; } = true;
internal virtual XmlDictionaryString? TopLevelElementName
{
- get { return _name; }
+ get => _name;
set
{
Debug.Assert(value != null);
@@ -1134,7 +1066,7 @@ internal virtual XmlDictionaryString? TopLevelElementName
internal virtual XmlDictionaryString? TopLevelElementNamespace
{
- get { return _ns; }
+ get => _ns;
set
{
Debug.Assert(value != null);
@@ -1142,15 +1074,9 @@ internal virtual XmlDictionaryString? TopLevelElementNamespace
}
}
- internal virtual bool CanContainReferences
- {
- get { return true; }
- }
+ internal virtual bool CanContainReferences => true;
- internal virtual bool IsPrimitive
- {
- get { return false; }
- }
+ internal virtual bool IsPrimitive => false;
internal MethodInfo? ParseMethod
{
@@ -1171,19 +1097,19 @@ internal MethodInfo? ParseMethod
}
}
- internal void SetDataContractName(XmlQualifiedName stableName)
+ internal void SetDataContractName(XmlQualifiedName xmlName)
{
XmlDictionary dictionary = new XmlDictionary(2);
- this.Name = dictionary.Add(stableName.Name);
- this.Namespace = dictionary.Add(stableName.Namespace);
- this.StableName = stableName;
+ Name = dictionary.Add(xmlName.Name);
+ Namespace = dictionary.Add(xmlName.Namespace);
+ XmlName = xmlName;
}
internal void SetDataContractName(XmlDictionaryString name, XmlDictionaryString ns)
{
- this.Name = name;
- this.Namespace = ns;
- this.StableName = CreateQualifiedName(name.Value, ns.Value);
+ Name = name;
+ Namespace = ns;
+ XmlName = CreateQualifiedName(name.Value, ns.Value);
}
[DoesNotReturn]
@@ -1194,10 +1120,14 @@ internal void ThrowInvalidDataContractException(string message)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static bool IsTypeSerializable(Type type, HashSet? previousCollectionTypes = null)
+ internal static bool IsTypeSerializable(Type type)
{
- Type? itemType;
+ return IsTypeSerializable(type, null);
+ }
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private static bool IsTypeSerializable(Type type, HashSet? previousCollectionTypes)
+ {
if (type.IsSerializable ||
type.IsEnum ||
type.IsDefined(Globals.TypeOfDataContractAttribute, false) ||
@@ -1209,7 +1139,7 @@ internal static bool IsTypeSerializable(Type type, HashSet? previousCollec
{
return true;
}
- if (CollectionDataContract.IsCollection(type, out itemType))
+ if (CollectionDataContract.IsCollection(type, out Type? itemType))
{
previousCollectionTypes ??= new HashSet();
ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
@@ -1229,9 +1159,34 @@ private static void ValidatePreviousCollectionTypes(Type collectionType, Type it
{
itemType = itemType.GetElementType()!;
}
- if (previousCollectionTypes.Contains(itemType))
+
+ // Do a breadth first traversal of the generic type tree to
+ // produce the closure of all generic argument types and
+ // check that none of these is in the previousCollectionTypes
+ List itemTypeClosure = new List();
+ Queue itemTypeQueue = new Queue();
+
+ itemTypeQueue.Enqueue(itemType);
+ itemTypeClosure.Add(itemType);
+
+ while (itemTypeQueue.Count > 0)
{
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.RecursiveCollectionType, GetClrTypeFullName(itemType))));
+ itemType = itemTypeQueue.Dequeue();
+ if (previousCollectionTypes.Contains(itemType))
+ {
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.RecursiveCollectionType, GetClrTypeFullName(itemType))));
+ }
+ if (itemType.IsGenericType)
+ {
+ foreach (Type argType in itemType.GetGenericArguments())
+ {
+ if (!itemTypeClosure.Contains(argType))
+ {
+ itemTypeQueue.Enqueue(argType);
+ itemTypeClosure.Add(argType);
+ }
+ }
+ }
}
}
@@ -1290,47 +1245,47 @@ internal static bool IsValidNCName(string name)
{
return false;
}
- catch (Exception)
- {
- return false;
- }
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static XmlQualifiedName GetStableName(Type type)
+ public static XmlQualifiedName GetXmlName(Type type)
+ {
+ return GetXmlName(type, out _);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal static XmlQualifiedName GetXmlName(Type type, out bool hasDataContract)
{
- return GetStableName(type, out _);
+ return GetXmlName(type, new HashSet(), out hasDataContract);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static XmlQualifiedName GetStableName(Type type, out bool hasDataContract)
+ internal static XmlQualifiedName GetXmlName(Type type, HashSet previousCollectionTypes, out bool hasDataContract)
{
type = UnwrapRedundantNullableType(type);
- XmlQualifiedName? stableName;
- if (TryGetBuiltInXmlAndArrayTypeStableName(type, out stableName))
+ if (TryGetBuiltInXmlAndArrayTypeXmlName(type, previousCollectionTypes, out XmlQualifiedName? xmlName))
{
hasDataContract = false;
}
else
{
- DataContractAttribute? dataContractAttribute;
- if (TryGetDCAttribute(type, out dataContractAttribute))
+ if (TryGetDCAttribute(type, out DataContractAttribute? dataContractAttribute))
{
- stableName = GetDCTypeStableName(type, dataContractAttribute);
+ xmlName = GetDCTypeXmlName(type, dataContractAttribute);
hasDataContract = true;
}
else
{
- stableName = GetNonDCTypeStableName(type);
+ xmlName = GetNonDCTypeXmlName(type, previousCollectionTypes);
hasDataContract = false;
}
}
- return stableName;
+ return xmlName;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static XmlQualifiedName GetDCTypeStableName(Type type, DataContractAttribute dataContractAttribute)
+ private static XmlQualifiedName GetDCTypeXmlName(Type type, DataContractAttribute dataContractAttribute)
{
string? name, ns;
if (dataContractAttribute.IsNameSetExplicitly)
@@ -1343,7 +1298,7 @@ private static XmlQualifiedName GetDCTypeStableName(Type type, DataContractAttri
name = DataContract.EncodeLocalName(name);
}
else
- name = GetDefaultStableLocalName(type);
+ name = GetDefaultXmlLocalName(type);
if (dataContractAttribute.IsNamespaceSetExplicitly)
{
@@ -1359,14 +1314,16 @@ private static XmlQualifiedName GetDCTypeStableName(Type type, DataContractAttri
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static XmlQualifiedName GetNonDCTypeStableName(Type type)
+ private static XmlQualifiedName GetNonDCTypeXmlName(Type type, HashSet previousCollectionTypes)
{
string? name, ns;
- Type? itemType;
- if (CollectionDataContract.IsCollection(type, out itemType))
- return GetCollectionStableName(type, itemType, out _);
- name = GetDefaultStableLocalName(type);
+ if (CollectionDataContract.IsCollection(type, out Type? itemType))
+ {
+ ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
+ return GetCollectionXmlName(type, itemType, previousCollectionTypes, out _);
+ }
+ name = GetDefaultXmlLocalName(type);
// ensures that ContractNamespaceAttribute is honored when used with non-attributed types
if (ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
@@ -1375,32 +1332,33 @@ private static XmlQualifiedName GetNonDCTypeStableName(Type type)
}
else
{
- ns = GetDefaultStableNamespace(type);
+ ns = GetDefaultXmlNamespace(type);
}
return CreateQualifiedName(name, ns);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static bool TryGetBuiltInXmlAndArrayTypeStableName(Type type, [NotNullWhen(true)] out XmlQualifiedName? stableName)
+ private static bool TryGetBuiltInXmlAndArrayTypeXmlName(Type type, HashSet previousCollectionTypes, [NotNullWhen(true)] out XmlQualifiedName? xmlName)
{
- stableName = null;
+ xmlName = null;
DataContract? builtInContract = GetBuiltInDataContract(type);
if (builtInContract != null)
{
- stableName = builtInContract.StableName;
+ xmlName = builtInContract.XmlName;
}
else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
{
- XmlQualifiedName xmlTypeStableName;
- SchemaExporter.GetXmlTypeInfo(type, out xmlTypeStableName, out _, out _);
- stableName = xmlTypeStableName;
+ SchemaExporter.GetXmlTypeInfo(type, out XmlQualifiedName xmlTypeName, out _, out _);
+ xmlName = xmlTypeName;
}
else if (type.IsArray)
{
- stableName = GetCollectionStableName(type, type.GetElementType()!, out _);
+ Type itemType = type.GetElementType()!;
+ ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
+ xmlName = GetCollectionXmlName(type, itemType, previousCollectionTypes, out _);
}
- return stableName != null;
+ return xmlName != null;
}
internal static bool TryGetDCAttribute(Type type, [NotNullWhen(true)] out DataContractAttribute? dataContractAttribute)
@@ -1421,7 +1379,13 @@ internal static bool TryGetDCAttribute(Type type, [NotNullWhen(true)] out DataCo
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static XmlQualifiedName GetCollectionStableName(Type type, Type itemType, out CollectionDataContractAttribute? collectionContractAttribute)
+ internal static XmlQualifiedName GetCollectionXmlName(Type type, Type itemType, out CollectionDataContractAttribute? collectionContractAttribute)
+ {
+ return GetCollectionXmlName(type, itemType, new HashSet(), out collectionContractAttribute);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal static XmlQualifiedName GetCollectionXmlName(Type type, Type itemType, HashSet previousCollectionTypes, out CollectionDataContractAttribute? collectionContractAttribute)
{
string? name, ns;
object[] collectionContractAttributes = type.GetCustomAttributes(Globals.TypeOfCollectionDataContractAttribute, false).ToArray();
@@ -1442,7 +1406,7 @@ internal static XmlQualifiedName GetCollectionStableName(Type type, Type itemTyp
name = DataContract.EncodeLocalName(name);
}
else
- name = GetDefaultStableLocalName(type);
+ name = GetDefaultXmlLocalName(type);
if (collectionContractAttribute.IsNamespaceSetExplicitly)
{
@@ -1458,9 +1422,9 @@ internal static XmlQualifiedName GetCollectionStableName(Type type, Type itemTyp
{
collectionContractAttribute = null;
string arrayOfPrefix = Globals.ArrayPrefix + GetArrayPrefix(ref itemType);
- XmlQualifiedName elementStableName = GetStableName(itemType);
- name = arrayOfPrefix + elementStableName.Name;
- ns = GetCollectionNamespace(elementStableName.Namespace);
+ XmlQualifiedName elementXmlName = GetXmlName(itemType, previousCollectionTypes, out _);
+ name = arrayOfPrefix + elementXmlName.Name;
+ ns = GetCollectionNamespace(elementXmlName.Namespace);
}
return CreateQualifiedName(name, ns);
}
@@ -1485,13 +1449,33 @@ internal static string GetCollectionNamespace(string elementNs)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static XmlQualifiedName GetDefaultStableName(Type type)
+ public virtual XmlQualifiedName GetArrayTypeName(bool isNullable)
+ {
+ XmlQualifiedName itemName;
+ if (IsValueType && isNullable)
+ {
+ GenericInfo genericInfo = new GenericInfo(DataContract.GetXmlName(Globals.TypeOfNullable), Globals.TypeOfNullable.FullName!);
+ genericInfo.Add(new GenericInfo(XmlName, null));
+ genericInfo.AddToLevel(0, 1);
+ itemName = genericInfo.GetExpandedXmlName();
+ }
+ else
+ {
+ itemName = XmlName;
+ }
+ string ns = GetCollectionNamespace(itemName.Namespace);
+ string name = Globals.ArrayPrefix + itemName.Name;
+ return new XmlQualifiedName(name, ns);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal static XmlQualifiedName GetDefaultXmlName(Type type)
{
- return CreateQualifiedName(GetDefaultStableLocalName(type), GetDefaultStableNamespace(type));
+ return CreateQualifiedName(GetDefaultXmlLocalName(type), GetDefaultXmlNamespace(type));
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static string GetDefaultStableLocalName(Type type)
+ private static string GetDefaultXmlLocalName(Type type)
{
if (type.IsGenericParameter)
return "{" + type.GenericParameterPosition + "}";
@@ -1528,7 +1512,7 @@ private static string GetDefaultStableLocalName(Type type)
localName.Append('{').Append(i).Append('}');
else
{
- XmlQualifiedName qname = DataContract.GetStableName(genParam);
+ XmlQualifiedName qname = DataContract.GetXmlName(genParam);
localName.Append(qname.Name);
namespaces.Append(' ').Append(qname.Namespace);
if (parametersFromBuiltInNamespaces)
@@ -1557,7 +1541,7 @@ private static string GetDefaultDataContractNamespace(Type type)
if (ns == null)
{
- ns = GetDefaultStableNamespace(type);
+ ns = GetDefaultXmlNamespace(type);
}
else
{
@@ -1582,7 +1566,7 @@ internal static List GetDataContractNameForGenericName(string typeName, Str
if (localName != null)
{
string tempLocalName = typeName.Substring(startIndex, endIndex - startIndex);
- localName.Append((tempLocalName.Equals("KeyValuePairAdapter") ? "KeyValuePair" : tempLocalName));
+ localName.Append(tempLocalName);
}
while ((startIndex = typeName.IndexOf('.', startIndex + 1, endIndex - startIndex - 1)) >= 0)
nestedParamCounts.Add(0);
@@ -1604,11 +1588,11 @@ internal static bool IsBuiltInNamespace(string ns)
return (ns == Globals.SchemaNamespace || ns == Globals.SerializationNamespace);
}
- internal static string GetDefaultStableNamespace(Type type)
+ internal static string GetDefaultXmlNamespace(Type type)
{
if (type.IsGenericParameter)
return "{ns}";
- return GetDefaultStableNamespace(type.Namespace);
+ return GetDefaultXmlNamespace(type.Namespace);
}
internal static XmlQualifiedName CreateQualifiedName(string localName, string ns)
@@ -1616,27 +1600,27 @@ internal static XmlQualifiedName CreateQualifiedName(string localName, string ns
return new XmlQualifiedName(localName, GetNamespace(ns));
}
- internal static string GetDefaultStableNamespace(string? clrNs)
+ internal static string GetDefaultXmlNamespace(string? clrNs)
{
return new Uri(Globals.DataContractXsdBaseNamespaceUri, clrNs ?? string.Empty).AbsoluteUri;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static void GetDefaultStableName(string fullTypeName, out string localName, out string ns)
+ internal static void GetDefaultXmlName(string fullTypeName, out string localName, out string ns)
{
CodeTypeReference typeReference = new CodeTypeReference(fullTypeName);
- GetDefaultStableName(typeReference, out localName, out ns);
+ GetDefaultName(typeReference, out localName, out ns);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private static void GetDefaultStableName(CodeTypeReference typeReference, out string localName, out string ns)
+ private static void GetDefaultName(CodeTypeReference typeReference, out string localName, out string ns)
{
string fullTypeName = typeReference.BaseType;
DataContract? dataContract = GetBuiltInDataContract(fullTypeName);
if (dataContract != null)
{
- localName = dataContract.StableName.Name;
- ns = dataContract.StableName.Namespace;
+ localName = dataContract.XmlName.Name;
+ ns = dataContract.XmlName.Namespace;
return;
}
@@ -1649,8 +1633,7 @@ private static void GetDefaultStableName(CodeTypeReference typeReference, out st
List nestedParamCounts = GetDataContractNameForGenericName(localName, localNameBuilder);
foreach (CodeTypeReference typeArg in typeReference.TypeArguments)
{
- string typeArgName, typeArgNs;
- GetDefaultStableName(typeArg, out typeArgName, out typeArgNs);
+ GetDefaultName(typeArg, out string typeArgName, out string typeArgNs);
localNameBuilder.Append(typeArgName);
argNamespacesBuilder.Append(' ').Append(typeArgNs);
if (parametersFromBuiltInNamespaces)
@@ -1663,7 +1646,7 @@ private static void GetDefaultStableName(CodeTypeReference typeReference, out st
{
foreach (int count in nestedParamCounts)
{
- argNamespacesBuilder.Insert(0, count).Insert(0, ' ');
+ argNamespacesBuilder.Insert(0, count.ToString(CultureInfo.InvariantCulture)).Insert(0, ' ');
}
localNameBuilder.Append(GetNamespacesDigest(argNamespacesBuilder.ToString()));
@@ -1673,7 +1656,7 @@ private static void GetDefaultStableName(CodeTypeReference typeReference, out st
}
localName = DataContract.EncodeLocalName(localName);
- ns = GetDefaultStableNamespace(ns);
+ ns = GetDefaultXmlNamespace(ns);
}
private static void CheckExplicitDataContractNamespaceUri(string dataContractNs, Type type)
@@ -1686,8 +1669,7 @@ private static void CheckExplicitDataContractNamespaceUri(string dataContractNs,
ThrowInvalidDataContractException(SR.Format(SR.DataContractNamespaceIsNotValid, dataContractNs), type);
dataContractNs = trimmedNs;
}
- Uri? uri;
- if (Uri.TryCreate(dataContractNs, UriKind.RelativeOrAbsolute, out uri))
+ if (Uri.TryCreate(dataContractNs, UriKind.RelativeOrAbsolute, out Uri? uri))
{
if (uri.ToString() == Globals.SerializationNamespace)
ThrowInvalidDataContractException(SR.Format(SR.DataContractNamespaceReserved, Globals.SerializationNamespace), type);
@@ -1933,8 +1915,7 @@ internal static string ExpandGenericParameters(string format, IGenericNameProvid
}
else
{
- int paramIndex;
- if (!int.TryParse(format.AsSpan(start, i - start), out paramIndex) || paramIndex < 0 || paramIndex >= genericNameProvider.GetParameterCount())
+ if (!int.TryParse(format.AsSpan(start, i - start), out int paramIndex) || paramIndex < 0 || paramIndex >= genericNameProvider.GetParameterCount())
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.GenericParameterNotValid, format.Substring(start, i - start), genericNameProvider.GetGenericTypeName(), genericNameProvider.GetParameterCount() - 1)));
typeName.Append(genericNameProvider.GetParameterName(paramIndex));
}
@@ -2030,25 +2011,36 @@ private static void ImportKnownTypeAttributes(Type? type, Dictionary
}
}
- //For Json we need to add KeyValuePair to KnownTypes if the UnderLyingType is a Dictionary
- try
+ // After careful consideration, I don't think this code is necessary anymore. After trying to
+ // decipher the intent of the comments here, my best guess is that this was DCJS's way of working
+ // around a non-[Serializable] KVP in Silverlight/early .Net Core. The regular DCS went with a
+ // KVPAdapter approach. Neither is needed now.
+ //
+ // But this code does produce additional artifacts in schema handling. To be cautious, just in case
+ // somebody needs a KVP contract in addition to the KV contract in their schema, I've kept this
+ // here behind this AppContext switch.
+ AppContext.TryGetSwitch("Switch.System.Runtime.Serialization.DataContracts.Auto_Import_KVP", out bool autoImportKVP);
+ if (autoImportKVP)
{
- CollectionDataContract? collectionDataContract = DataContract.GetDataContract(type) as CollectionDataContract;
- if (collectionDataContract != null && collectionDataContract.IsDictionary &&
- collectionDataContract.ItemType.GetGenericTypeDefinition() == Globals.TypeOfKeyValue)
+ //For Json we need to add KeyValuePair to KnownTypes if the UnderLyingType is a Dictionary
+ try
{
- DataContract itemDataContract = DataContract.GetDataContract(Globals.TypeOfKeyValuePair.MakeGenericType(collectionDataContract.ItemType.GetGenericArguments()));
- knownDataContracts ??= new DataContractDictionary();
+ if (DataContract.GetDataContract(type) is CollectionDataContract collectionDataContract && collectionDataContract.IsDictionary &&
+ collectionDataContract.ItemType.GetGenericTypeDefinition() == Globals.TypeOfKeyValue)
+ {
+ DataContract itemDataContract = DataContract.GetDataContract(Globals.TypeOfKeyValuePair.MakeGenericType(collectionDataContract.ItemType.GetGenericArguments()));
+ knownDataContracts ??= new DataContractDictionary();
- knownDataContracts.TryAdd(itemDataContract.StableName, itemDataContract);
+ knownDataContracts.TryAdd(itemDataContract.XmlName, itemDataContract);
+ }
+ }
+ catch (InvalidDataContractException)
+ {
+ //Ignore any InvalidDataContractException as this phase is a workaround for lack of ISerializable.
+ //InvalidDataContractException may happen as we walk the type hierarchy back to Object and encounter
+ //types that may not be valid DC. This step is purely for KeyValuePair and shouldn't fail the (de)serialization.
+ //Any IDCE in this case fails the serialization/deserialization process which is not the optimal experience.
}
- }
- catch (InvalidDataContractException)
- {
- //Ignore any InvalidDataContractException as this phase is a workaround for lack of ISerializable.
- //InvalidDataContractException may happen as we walk the type hierarchy back to Object and encounter
- //types that may not be valid DC. This step is purely for KeyValuePair and shouldn't fail the (de)serialization.
- //Any IDCE in this case fails the serialization/deserialization process which is not the optimal experience.
}
type = type.BaseType;
@@ -2060,23 +2052,62 @@ internal static void CheckAndAdd(Type type, Dictionary typesChecked,
{
type = DataContract.UnwrapNullableType(type);
DataContract dataContract = DataContract.GetDataContract(type);
- DataContract? alreadyExistingContract;
if (nameToDataContractTable == null)
{
nameToDataContractTable = new DataContractDictionary();
}
- else if (nameToDataContractTable.TryGetValue(dataContract.StableName, out alreadyExistingContract))
+ else if (nameToDataContractTable.TryGetValue(dataContract.XmlName, out DataContract? alreadyExistingContract))
{
+ // The alreadyExistingContract type was used as-is in NetFx. The call to get the appropriate adapter type was added in CoreFx with https://github.com/dotnet/runtime/commit/50c0a70c52fa66fafa1227be552ccdab5e4cf8e4
// Don't throw duplicate if its a KeyValuePair as it could have been added by Dictionary
- if (DataContractCriticalHelper.GetDataContractAdapterType(alreadyExistingContract.UnderlyingType) != DataContractCriticalHelper.GetDataContractAdapterType(type) &&
- !(alreadyExistingContract is ClassDataContract && ((ClassDataContract)alreadyExistingContract).IsKeyValuePairAdapter))
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupContractInKnownTypes, type, alreadyExistingContract.UnderlyingType, dataContract.StableName.Namespace, dataContract.StableName.Name)));
+ if (DataContractCriticalHelper.GetDataContractAdapterType(alreadyExistingContract.UnderlyingType) != DataContractCriticalHelper.GetDataContractAdapterType(type))
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupContractInKnownTypes, type, alreadyExistingContract.UnderlyingType, dataContract.XmlName.Namespace, dataContract.XmlName.Name)));
return;
}
- nameToDataContractTable.Add(dataContract.StableName, dataContract);
+ nameToDataContractTable.Add(dataContract.XmlName, dataContract);
ImportKnownTypeAttributes(type, typesChecked, ref nameToDataContractTable);
}
+ public sealed override bool Equals(object? obj)
+ {
+ if ((object)this == obj)
+ return true;
+ return Equals(obj, new HashSet());
+ }
+
+ internal virtual bool Equals(object? other, HashSet? checkedContracts)
+ {
+ if (other is DataContract dataContract)
+ {
+ return (XmlName.Name == dataContract.XmlName.Name && XmlName.Namespace == dataContract.XmlName.Namespace && IsReference == dataContract.IsReference);
+ }
+ return false;
+ }
+
+ internal bool IsEqualOrChecked(object? other, HashSet? checkedContracts)
+ {
+ if (other == null)
+ return false;
+
+ if ((object)this == other)
+ return true;
+
+ if (checkedContracts != null)
+ {
+ DataContractPairKey contractPairKey = new DataContractPairKey(this, other);
+ if (checkedContracts.Contains(contractPairKey))
+ return true;
+ checkedContracts.Add(contractPairKey);
+ }
+
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
///
/// Review - checks type visibility to calculate if access to it requires MemberAccessPermission.
/// since this information is used to determine whether to give the generated code access
@@ -2084,18 +2115,46 @@ internal static void CheckAndAdd(Type type, Dictionary typesChecked,
///
internal static bool IsTypeVisible(Type t)
{
- if (!t.IsVisible && !IsTypeVisibleInSerializationModule(t))
+ // Generic parameters are always considered visible.
+ if (t.IsGenericParameter)
+ {
+ return true;
+ }
+
+ // The normal Type.IsVisible check requires all nested types to be IsNestedPublic.
+ // This does not comply with our convention where they can also have InternalsVisibleTo
+ // with our assembly. The following method performs a recursive walk back the declaring
+ // type hierarchy to perform this enhanced IsVisible check.
+ if (!IsTypeAndDeclaringTypeVisible(t))
return false;
foreach (Type genericType in t.GetGenericArguments())
{
- if (!genericType.IsGenericParameter && !IsTypeVisible(genericType))
+ if (!IsTypeVisible(genericType))
return false;
}
return true;
}
+ internal static bool IsTypeAndDeclaringTypeVisible(Type t)
+ {
+ // Arrays, etc. must consider the underlying element type because the
+ // non-element type does not reflect the same type nesting. For example,
+ // MyClass[] would not show as a nested type, even when MyClass is nested.
+ if (t.HasElementType)
+ {
+ return IsTypeVisible(t.GetElementType()!);
+ }
+
+ // Nested types are not visible unless their declaring type is visible.
+ // Additionally, they must be either IsNestedPublic or in an assembly with InternalsVisibleTo this current assembly.
+ // Non-nested types must be public or have this same InternalsVisibleTo relation.
+ return t.IsNested
+ ? (t.IsNestedPublic || IsTypeVisibleInSerializationModule(t)) && IsTypeVisible(t.DeclaringType!)
+ : t.IsPublic || IsTypeVisibleInSerializationModule(t);
+ }
+
///
/// Review - checks constructor visibility to calculate if access to it requires MemberAccessPermission.
/// note: does local check for visibility, assuming that the declaring Type visibility has been checked.
@@ -2200,7 +2259,7 @@ internal interface IGenericNameProvider
string GetParameterName(int paramIndex);
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
string GetNamespaces();
- string GetGenericTypeName();
+ string? GetGenericTypeName();
bool ParametersFromBuiltInNamespaces
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -2224,8 +2283,7 @@ internal GenericNameProvider(string genericTypeName, object[] genericParams)
_genericParams = new object[genericParams.Length];
genericParams.CopyTo(_genericParams, 0);
- string name;
- DataContract.GetClrNameAndNamespace(genericTypeName, out name, out _);
+ DataContract.GetClrNameAndNamespace(genericTypeName, out string name, out _);
_nestedParamCounts = DataContract.GetDataContractNameForGenericName(name, null);
}
@@ -2242,7 +2300,7 @@ public IList GetNestedParameterCounts()
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
public string GetParameterName(int paramIndex)
{
- return GetStableName(paramIndex).Name;
+ return GetXmlName(paramIndex).Name;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -2250,11 +2308,11 @@ public string GetNamespaces()
{
StringBuilder namespaces = new StringBuilder();
for (int j = 0; j < GetParameterCount(); j++)
- namespaces.Append(' ').Append(GetStableName(j).Namespace);
+ namespaces.Append(' ').Append(GetXmlName(j).Namespace);
return namespaces.ToString();
}
- public string GetGenericTypeName()
+ public string? GetGenericTypeName()
{
return _genericTypeName;
}
@@ -2268,7 +2326,7 @@ public bool ParametersFromBuiltInNamespaces
for (int j = 0; j < GetParameterCount(); j++)
{
if (parametersFromBuiltInNamespaces)
- parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(GetStableName(j).Namespace);
+ parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(GetXmlName(j).Namespace);
else
break;
}
@@ -2277,7 +2335,7 @@ public bool ParametersFromBuiltInNamespaces
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- private XmlQualifiedName GetStableName(int i)
+ private XmlQualifiedName GetXmlName(int i)
{
object o = _genericParams[i];
XmlQualifiedName? qname = o as XmlQualifiedName;
@@ -2285,15 +2343,158 @@ private XmlQualifiedName GetStableName(int i)
{
Type? paramType = o as Type;
if (paramType != null)
- _genericParams[i] = qname = DataContract.GetStableName(paramType);
+ _genericParams[i] = qname = DataContract.GetXmlName(paramType);
else
- _genericParams[i] = qname = ((DataContract)o).StableName;
+ _genericParams[i] = qname = ((DataContract)o).XmlName;
}
return qname;
}
}
+ internal sealed class GenericInfo : IGenericNameProvider
+ {
+ private string? _genericTypeName;
+ private XmlQualifiedName _xmlName;
+ private List? _paramGenericInfos;
+ private List _nestedParamCounts;
+
+ internal GenericInfo(XmlQualifiedName xmlName, string? genericTypeName)
+ {
+ _xmlName = xmlName;
+ _genericTypeName = genericTypeName;
+ _nestedParamCounts = new List();
+ _nestedParamCounts.Add(0);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public XmlQualifiedName GetExpandedXmlName()
+ {
+ if (_paramGenericInfos == null)
+ return _xmlName;
+ return new XmlQualifiedName(DataContract.EncodeLocalName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(_xmlName.Name), this)), _xmlName.Namespace);
+ }
+
+ public XmlQualifiedName XmlName => _xmlName;
+
+ public IList? Parameters => _paramGenericInfos;
+
+ internal void Add(GenericInfo actualParamInfo)
+ {
+ if (_paramGenericInfos == null)
+ _paramGenericInfos = new List();
+ _paramGenericInfos.Add(actualParamInfo);
+ }
+
+ internal void AddToLevel(int level, int count)
+ {
+ if (level >= _nestedParamCounts.Count)
+ {
+ do
+ {
+ _nestedParamCounts.Add((level == _nestedParamCounts.Count) ? count : 0);
+ } while (level >= _nestedParamCounts.Count);
+ }
+ else
+ _nestedParamCounts[level] = _nestedParamCounts[level] + count;
+ }
+
+ internal string GetXmlNamespace()
+ {
+ return _xmlName.Namespace;
+ }
+
+ int IGenericNameProvider.GetParameterCount()
+ {
+ return _paramGenericInfos?.Count ?? 0;
+ }
+
+ IList IGenericNameProvider.GetNestedParameterCounts()
+ {
+ return _nestedParamCounts;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ string IGenericNameProvider.GetParameterName(int paramIndex)
+ {
+ Debug.Assert(_paramGenericInfos != null);
+ return _paramGenericInfos[paramIndex].GetExpandedXmlName().Name;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ string IGenericNameProvider.GetNamespaces()
+ {
+ if (_paramGenericInfos == null || _paramGenericInfos.Count == 0)
+ return "";
+
+ StringBuilder namespaces = new StringBuilder();
+ for (int j = 0; j < _paramGenericInfos.Count; j++)
+ namespaces.Append(' ').Append(_paramGenericInfos[j].GetXmlNamespace());
+ return namespaces.ToString();
+ }
+
+ string? IGenericNameProvider.GetGenericTypeName()
+ {
+ return _genericTypeName;
+ }
+
+ bool IGenericNameProvider.ParametersFromBuiltInNamespaces
+ {
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get
+ {
+ bool parametersFromBuiltInNamespaces = true;
+
+ if (_paramGenericInfos == null || _paramGenericInfos.Count == 0)
+ return parametersFromBuiltInNamespaces;
+
+ for (int j = 0; j < _paramGenericInfos.Count; j++)
+ {
+ if (parametersFromBuiltInNamespaces)
+ parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(_paramGenericInfos[j].GetXmlNamespace());
+ else
+ break;
+ }
+ return parametersFromBuiltInNamespaces;
+ }
+ }
+ }
+
+ internal sealed class DataContractPairKey
+ {
+ private object _object1;
+ private object _object2;
+
+ internal DataContractPairKey(object object1, object object2)
+ {
+ _object1 = object1;
+ _object2 = object2;
+ }
+
+ public override bool Equals(object? other)
+ {
+ if (other is not DataContractPairKey otherKey)
+ return false;
+ return ((otherKey._object1 == _object1 && otherKey._object2 == _object2) || (otherKey._object1 == _object2 && otherKey._object2 == _object1));
+ }
+
+ public override int GetHashCode()
+ {
+ return _object1.GetHashCode() ^ _object2.GetHashCode();
+ }
+ }
+
+ internal sealed class HashTableEqualityComparer : IEqualityComparer
+ {
+ bool IEqualityComparer.Equals(object? x, object? y)
+ {
+ return ((TypeHandleRef)x!).Value.Equals(((TypeHandleRef)y!).Value);
+ }
+ public int GetHashCode(object obj)
+ {
+ return ((TypeHandleRef)obj).Value.GetHashCode();
+ }
+ }
internal sealed class TypeHandleRefEqualityComparer : IEqualityComparer
{
@@ -2323,14 +2524,8 @@ public TypeHandleRef(RuntimeTypeHandle value)
public RuntimeTypeHandle Value
{
- get
- {
- return _value;
- }
- set
- {
- _value = value;
- }
+ get => _value;
+ set => _value = value;
}
}
@@ -2343,12 +2538,6 @@ public IntRef(int value)
_value = value;
}
- public int Value
- {
- get
- {
- return _value;
- }
- }
+ public int Value => _value;
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractResolver.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractResolver.cs
index 2b9345dc2c5f2..6983923059fb4 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractResolver.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractResolver.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization.DataContracts;
using System.Xml;
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSerializer.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSerializer.cs
index cd8b099284e33..97596f18babdf 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSerializer.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSerializer.cs
@@ -2,18 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Text;
+using System.Runtime.Serialization.DataContracts;
using System.Xml;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+using DataContractDictionary = System.Collections.Generic.Dictionary;
namespace System.Runtime.Serialization
{
@@ -28,25 +24,25 @@ public sealed class DataContractSerializer : XmlObjectSerializer
private bool _ignoreExtensionDataObject;
private bool _preserveObjectReferences;
private ReadOnlyCollection? _knownTypeCollection;
- internal IList? knownTypeList;
- internal DataContractDictionary? knownDataContracts;
+ internal IList? _knownTypeList;
+ internal DataContractDictionary? _knownDataContracts;
private DataContractResolver? _dataContractResolver;
private ISerializationSurrogateProvider? _serializationSurrogateProvider;
private bool _serializeReadOnlyTypes;
- private static SerializationOption _option = IsReflectionBackupAllowed() ? SerializationOption.ReflectionAsBackup : SerializationOption.CodeGenOnly;
- private static bool _optionAlreadySet;
+ private static SerializationOption s_option = IsReflectionBackupAllowed() ? SerializationOption.ReflectionAsBackup : SerializationOption.CodeGenOnly;
+ private static bool s_optionAlreadySet;
internal static SerializationOption Option
{
- get { return RuntimeFeature.IsDynamicCodeSupported ? _option : SerializationOption.ReflectionOnly; }
+ get { return RuntimeFeature.IsDynamicCodeSupported ? s_option : SerializationOption.ReflectionOnly; }
set
{
- if (_optionAlreadySet)
+ if (s_optionAlreadySet)
{
throw new InvalidOperationException(SR.CannotSetTwice);
}
- _optionAlreadySet = true;
- _option = value;
+ s_optionAlreadySet = true;
+ s_option = value;
}
}
@@ -61,22 +57,26 @@ public DataContractSerializer(Type type)
}
public DataContractSerializer(Type type, IEnumerable? knownTypes)
+ : this(type, knownTypes, int.MaxValue, false, false)
{
- Initialize(type, knownTypes, int.MaxValue, false, false, null, false);
}
-
public DataContractSerializer(Type type, string rootName, string rootNamespace)
: this(type, rootName, rootNamespace, null)
{
}
public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable? knownTypes)
+ : this(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false)
{
- XmlDictionary dictionary = new XmlDictionary(2);
- Initialize(type, dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), knownTypes, int.MaxValue, false, false, null, false);
}
+ internal DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable? knownTypes, int maxItemsInObjectGraph,
+ bool ignoreExtensionDataObject, bool preserveObjectReferences)
+ {
+ XmlDictionary dictionary = new XmlDictionary(2);
+ Initialize(type, dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), knownTypes, int.MaxValue, ignoreExtensionDataObject, preserveObjectReferences, null, false);
+ }
public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
: this(type, rootName, rootNamespace, null)
@@ -88,7 +88,7 @@ public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictio
Initialize(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false, null, false);
}
- internal DataContractSerializer(Type type, IEnumerable knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences)
+ internal DataContractSerializer(Type type, IEnumerable? knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences)
{
Initialize(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, null, false);
}
@@ -96,7 +96,7 @@ internal DataContractSerializer(Type type, IEnumerable knownTypes, int max
public DataContractSerializer(Type type, DataContractSerializerSettings? settings)
{
settings ??= new DataContractSerializerSettings();
- Initialize(type, settings.RootName, settings.RootNamespace, settings.KnownTypes, settings.MaxItemsInObjectGraph, false,
+ Initialize(type, settings.RootName, settings.RootNamespace, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
settings.PreserveObjectReferences, settings.DataContractResolver, settings.SerializeReadOnlyTypes);
}
@@ -115,10 +115,10 @@ private void Initialize(Type type,
if (knownTypes != null)
{
- this.knownTypeList = new List();
+ _knownTypeList = new List();
foreach (Type knownType in knownTypes)
{
- this.knownTypeList.Add(knownType);
+ _knownTypeList.Add(knownType);
}
}
@@ -154,9 +154,9 @@ public ReadOnlyCollection KnownTypes
{
if (_knownTypeCollection == null)
{
- if (knownTypeList != null)
+ if (_knownTypeList != null)
{
- _knownTypeCollection = new ReadOnlyCollection(knownTypeList);
+ _knownTypeCollection = new ReadOnlyCollection(_knownTypeList);
}
else
{
@@ -172,15 +172,15 @@ internal override DataContractDictionary? KnownDataContracts
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
get
{
- if (this.knownDataContracts == null && this.knownTypeList != null)
+ if (_knownDataContracts == null && _knownTypeList != null)
{
// This assignment may be performed concurrently and thus is a race condition.
// It's safe, however, because at worse a new (and identical) dictionary of
// data contracts will be created and re-assigned to this field. Introduction
// of a lock here could lead to deadlocks.
- this.knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(this.knownTypeList);
+ _knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(_knownTypeList);
}
- return this.knownDataContracts;
+ return _knownDataContracts;
}
}
@@ -354,7 +354,7 @@ internal void InternalWriteObjectContent(XmlWriterDelegator writer, object? grap
graph = SurrogateToDataContractType(_serializationSurrogateProvider, graph, declaredType, ref graphType);
}
- dataContractResolver ??= this.DataContractResolver;
+ dataContractResolver ??= DataContractResolver;
if (graph == null)
{
@@ -408,7 +408,7 @@ internal static DataContract GetDataContract(DataContract declaredTypeContract,
}
else
{
- return DataContract.GetDataContract(objectType.TypeHandle, objectType, SerializationMode.SharedContract);
+ return DataContract.GetDataContract(objectType.TypeHandle, objectType);
}
}
@@ -433,7 +433,7 @@ internal override void InternalWriteEndObject(XmlWriterDelegator writer)
if (MaxItemsInObjectGraph == 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
- dataContractResolver ??= this.DataContractResolver;
+ dataContractResolver ??= DataContractResolver;
if (verifyObjectName)
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSet.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSet.cs
index 41bae413f816a..129540177a69d 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSet.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSet.cs
@@ -1,48 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Xml;
using System.Collections;
using System.Collections.Generic;
-using System.Text;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
-namespace System.Runtime.Serialization
+using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+namespace System.Runtime.Serialization.DataContracts
{
- internal sealed class DataContractSet
+ public sealed class DataContractSet
{
- private Dictionary? _contracts;
+ private DataContractDictionary? _contracts;
private Dictionary? _processedContracts;
- private readonly ICollection _referencedTypes;
- private readonly ICollection _referencedCollectionTypes;
-
-#if SUPPORT_SURROGATE
- private IDataContractSurrogate _dataContractSurrogate;
- private Hashtable _surrogateDataTable;
-
- internal DataContractSet(IDataContractSurrogate dataContractSurrogate) : this(dataContractSurrogate, null, null) { }
-
- internal DataContractSet(IDataContractSurrogate dataContractSurrogate, ICollection referencedTypes, ICollection referencedCollectionTypes)
+ private readonly ISerializationSurrogateProvider? _surrogateProvider;
+ private readonly ISerializationSurrogateProvider2? _extendedSurrogateProvider;
+ private Hashtable? _surrogateData;
+ private DataContractDictionary? _knownTypesForObject;
+ private readonly List? _referencedTypes;
+ private readonly List? _referencedCollectionTypes;
+
+ public DataContractSet(ISerializationSurrogateProvider? dataContractSurrogate, IEnumerable? referencedTypes, IEnumerable? referencedCollectionTypes)
{
- _dataContractSurrogate = dataContractSurrogate;
- _referencedTypes = referencedTypes;
- _referencedCollectionTypes = referencedCollectionTypes;
+ _surrogateProvider = dataContractSurrogate;
+ _extendedSurrogateProvider = dataContractSurrogate as ISerializationSurrogateProvider2;
+ _referencedTypes = referencedTypes != null ? new List(referencedTypes) : null;
+ _referencedCollectionTypes = referencedCollectionTypes != null ? new List(referencedCollectionTypes) : null;
}
-#endif
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal DataContractSet(DataContractSet dataContractSet)
+ public DataContractSet(DataContractSet dataContractSet)
{
ArgumentNullException.ThrowIfNull(dataContractSet);
- //this.dataContractSurrogate = dataContractSet.dataContractSurrogate;
_referencedTypes = dataContractSet._referencedTypes;
_referencedCollectionTypes = dataContractSet._referencedCollectionTypes;
+ _extendedSurrogateProvider = dataContractSet._extendedSurrogateProvider;
- foreach (KeyValuePair pair in dataContractSet)
+ foreach (KeyValuePair pair in dataContractSet.Contracts)
{
- Add(pair.Key, pair.Value);
+ InternalAdd(pair.Key, pair.Value);
}
if (dataContractSet._processedContracts != null)
@@ -54,22 +54,18 @@ internal DataContractSet(DataContractSet dataContractSet)
}
}
- private Dictionary Contracts =>
- _contracts ??= new Dictionary();
+ public DataContractDictionary Contracts =>
+ _contracts ??= new DataContractDictionary();
- private Dictionary ProcessedContracts =>
+ public Dictionary ProcessedContracts =>
_processedContracts ??= new Dictionary();
-#if SUPPORT_SURROGATE
- private Hashtable SurrogateDataTable => _surrogateDataTable ??= new Hashtable();
-#endif
+ public Hashtable SurrogateData => _surrogateData ??= new Hashtable();
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal void Add(Type type)
+ public DataContractDictionary? KnownTypesForObject
{
- DataContract dataContract = GetDataContract(type);
- EnsureTypeNotGeneric(dataContract.UnderlyingType);
- Add(dataContract);
+ get => _knownTypesForObject;
+ internal set => _knownTypesForObject = value;
}
internal static void EnsureTypeNotGeneric(Type type)
@@ -78,14 +74,22 @@ internal static void EnsureTypeNotGeneric(Type type)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.GenericTypeNotExportable, type)));
}
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal void Add(Type type)
+ {
+ DataContract dataContract = GetDataContract(type);
+ EnsureTypeNotGeneric(dataContract.UnderlyingType);
+ Add(dataContract);
+ }
+
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void Add(DataContract dataContract)
{
- Add(dataContract.StableName, dataContract);
+ Add(dataContract.XmlName, dataContract);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public void Add(XmlQualifiedName name, DataContract dataContract)
+ internal void Add(XmlQualifiedName name, DataContract dataContract)
{
if (dataContract.IsBuiltInDataContract)
return;
@@ -95,17 +99,16 @@ public void Add(XmlQualifiedName name, DataContract dataContract)
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal void InternalAdd(XmlQualifiedName name, DataContract dataContract)
{
- DataContract? dataContractInSet;
- if (Contracts.TryGetValue(name, out dataContractInSet))
+ if (Contracts.TryGetValue(name, out DataContract? dataContractInSet))
{
if (!dataContractInSet.Equals(dataContract))
{
if (dataContract.UnderlyingType == null || dataContractInSet.UnderlyingType == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupContractInDataContractSet, dataContract.StableName.Name, dataContract.StableName.Namespace)));
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupContractInDataContractSet, dataContract.XmlName.Name, dataContract.XmlName.Namespace)));
else
{
bool typeNamesEqual = (DataContract.GetClrTypeFullName(dataContract.UnderlyingType) == DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType));
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupTypeContractInDataContractSet, (typeNamesEqual ? dataContract.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContract.UnderlyingType)), (typeNamesEqual ? dataContractInSet.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType)), dataContract.StableName.Name, dataContract.StableName.Namespace)));
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.DupTypeContractInDataContractSet, (typeNamesEqual ? dataContract.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContract.UnderlyingType)), (typeNamesEqual ? dataContractInSet.UnderlyingType.AssemblyQualifiedName : DataContract.GetClrTypeFullName(dataContractInSet.UnderlyingType)), dataContract.XmlName.Name, dataContract.XmlName.Namespace)));
}
}
}
@@ -113,17 +116,17 @@ internal void InternalAdd(XmlQualifiedName name, DataContract dataContract)
{
Contracts.Add(name, dataContract);
- if (dataContract is ClassDataContract)
+ if (dataContract is ClassDataContract classDC)
{
- AddClassDataContract((ClassDataContract)dataContract);
+ AddClassDataContract(classDC);
}
- else if (dataContract is CollectionDataContract)
+ else if (dataContract is CollectionDataContract collectionDC)
{
- AddCollectionDataContract((CollectionDataContract)dataContract);
+ AddCollectionDataContract(collectionDC);
}
- else if (dataContract is XmlDataContract)
+ else if (dataContract is XmlDataContract xmlDC)
{
- AddXmlDataContract((XmlDataContract)dataContract);
+ AddXmlDataContract(xmlDC);
}
}
}
@@ -131,9 +134,9 @@ internal void InternalAdd(XmlQualifiedName name, DataContract dataContract)
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void AddClassDataContract(ClassDataContract classDataContract)
{
- if (classDataContract.BaseContract != null)
+ if (classDataContract.BaseClassContract != null)
{
- Add(classDataContract.BaseContract.StableName, classDataContract.BaseContract);
+ Add(classDataContract.BaseClassContract.XmlName, classDataContract.BaseClassContract);
}
if (!classDataContract.IsISerializable)
{
@@ -143,18 +146,18 @@ private void AddClassDataContract(ClassDataContract classDataContract)
{
DataMember dataMember = classDataContract.Members[i];
DataContract memberDataContract = GetMemberTypeDataContract(dataMember);
-#if SUPPORT_SURROGATE
- if (_dataContractSurrogate != null && dataMember.MemberInfo != null)
+
+ if (_extendedSurrogateProvider != null && dataMember.MemberInfo != null)
{
- object customData = DataContractSurrogateCaller.GetCustomDataToExport(
- _dataContractSurrogate,
- dataMember.MemberInfo,
- memberDataContract.UnderlyingType);
+ object? customData = DataContractSurrogateCaller.GetCustomDataToExport(
+ _extendedSurrogateProvider,
+ dataMember.MemberInfo,
+ memberDataContract.UnderlyingType);
if (customData != null)
- SurrogateDataTable.Add(dataMember, customData);
+ SurrogateData.Add(dataMember, customData);
}
-#endif
- Add(memberDataContract.StableName, memberDataContract);
+
+ Add(memberDataContract.XmlName, memberDataContract);
}
}
}
@@ -164,16 +167,19 @@ private void AddClassDataContract(ClassDataContract classDataContract)
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void AddCollectionDataContract(CollectionDataContract collectionDataContract)
{
- if (collectionDataContract.IsDictionary)
+ if (collectionDataContract.UnderlyingType != Globals.TypeOfSchemaDefinedType)
{
- ClassDataContract keyValueContract = (collectionDataContract.ItemContract as ClassDataContract)!;
- AddClassDataContract(keyValueContract);
- }
- else
- {
- DataContract itemContract = GetItemTypeDataContract(collectionDataContract);
- if (itemContract != null)
- Add(itemContract.StableName, itemContract);
+ if (collectionDataContract.IsDictionary)
+ {
+ ClassDataContract keyValueContract = (collectionDataContract.ItemContract as ClassDataContract)!;
+ AddClassDataContract(keyValueContract);
+ }
+ else
+ {
+ DataContract itemContract = GetItemTypeDataContract(collectionDataContract);
+ if (itemContract != null)
+ Add(itemContract.XmlName, itemContract);
+ }
}
AddKnownDataContracts(collectionDataContract.KnownDataContracts);
}
@@ -187,7 +193,7 @@ private void AddXmlDataContract(XmlDataContract xmlDataContract)
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
private void AddKnownDataContracts(DataContractDictionary? knownDataContracts)
{
- if (knownDataContracts != null)
+ if (knownDataContracts?.Count > 0)
{
foreach (DataContract knownDataContract in knownDataContracts.Values)
{
@@ -197,88 +203,406 @@ private void AddKnownDataContracts(DataContractDictionary? knownDataContracts)
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetDataContract(Type clrType)
+ internal XmlQualifiedName GetXmlName(Type clrType)
+ {
+ if (_surrogateProvider != null)
+ {
+ Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, clrType);
+ return DataContract.GetXmlName(dcType);
+ }
+ return DataContract.GetXmlName(clrType);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public DataContract GetDataContract(Type type)
{
-#if SUPPORT_SURROGATE
- if (_dataContractSurrogate == null)
- return DataContract.GetDataContract(clrType);
-#endif
- DataContract? dataContract = DataContract.GetBuiltInDataContract(clrType);
+ if (_surrogateProvider == null)
+ return DataContract.GetDataContract(type);
+
+ DataContract? dataContract = DataContract.GetBuiltInDataContract(type);
if (dataContract != null)
return dataContract;
-#if SUPPORT_SURROGATE
- Type dcType = DataContractSurrogateCaller.GetDataContractType(_dataContractSurrogate, clrType);
- if (clrType.IsValueType != dcType.IsValueType)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.ValueTypeMismatchInSurrogatedType, dcType, clrType)));
-#endif
- Type dcType = clrType;
+ Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, type);
dataContract = DataContract.GetDataContract(dcType);
-#if SUPPORT_SURROGATE
- if (!SurrogateDataTable.Contains(dataContract))
+ if (_extendedSurrogateProvider != null && !SurrogateData.Contains(dataContract))
{
- object customData = DataContractSurrogateCaller.GetCustomDataToExport(
- _dataContractSurrogate, clrType, dcType);
+ object? customData = DataContractSurrogateCaller.GetCustomDataToExport(_extendedSurrogateProvider, type, dcType);
if (customData != null)
- SurrogateDataTable.Add(dataContract, customData);
+ SurrogateData.Add(dataContract, customData);
+ }
+
+ return dataContract;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public DataContract? GetDataContract(XmlQualifiedName key)
+ {
+ DataContract? dataContract = DataContract.GetBuiltInDataContract(key.Name, key.Namespace);
+ if (dataContract == null)
+ {
+ Contracts.TryGetValue(key, out dataContract);
}
-#endif
return dataContract;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetMemberTypeDataContract(DataMember dataMember)
+ internal DataContract GetMemberTypeDataContract(DataMember dataMember)
{
- Type dataMemberType = dataMember.MemberType;
- if (dataMember.IsGetOnlyCollection)
+ if (dataMember.MemberInfo is not Type)
{
-#if SUPPORT_SURROGATE
- if (_dataContractSurrogate != null)
+ Type dataMemberType = dataMember.MemberType;
+ if (dataMember.IsGetOnlyCollection)
+ {
+ if (_surrogateProvider != null)
{
- Type dcType = DataContractSurrogateCaller.GetDataContractType(_dataContractSurrogate, dataMemberType);
+ Type dcType = DataContractSurrogateCaller.GetDataContractType(_surrogateProvider, dataMemberType);
if (dcType != dataMemberType)
{
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SurrogatesWithGetOnlyCollectionsNotSupported,
- DataContract.GetClrTypeFullName(dataMemberType), DataContract.GetClrTypeFullName(dataMember.MemberInfo.DeclaringType), dataMember.MemberInfo.Name)));
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.SurrogatesWithGetOnlyCollectionsNotSupported,
+ DataContract.GetClrTypeFullName(dataMemberType),
+ (dataMember.MemberInfo.DeclaringType != null) ? DataContract.GetClrTypeFullName(dataMember.MemberInfo.DeclaringType) : dataMember.MemberInfo.DeclaringType,
+ dataMember.MemberInfo.Name)));
}
}
-#endif
- return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(dataMemberType.TypeHandle), dataMemberType.TypeHandle, dataMemberType, SerializationMode.SharedContract);
- }
- else
- {
- return GetDataContract(dataMemberType);
+ return DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(dataMemberType.TypeHandle), dataMemberType.TypeHandle, dataMemberType);
+ }
+ else
+ {
+ return GetDataContract(dataMemberType);
+ }
}
+ return dataMember.MemberTypeContract;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static DataContract GetItemTypeDataContract(CollectionDataContract collectionContract)
+ internal DataContract GetItemTypeDataContract(CollectionDataContract collectionContract)
{
if (collectionContract.ItemType != null)
return GetDataContract(collectionContract.ItemType);
return collectionContract.ItemContract;
}
-#if SUPPORT_SURROGATE
- internal object GetSurrogateData(object key)
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal bool Remove(XmlQualifiedName key)
{
- return SurrogateDataTable[key];
+ if (DataContract.GetBuiltInDataContract(key.Name, key.Namespace) != null)
+ return false;
+ return Contracts.Remove(key);
}
- internal void SetSurrogateData(object key, object surrogateData)
+ private Dictionary? _referencedTypesDictionary;
+ private Dictionary? _referencedCollectionTypesDictionary;
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private Dictionary GetReferencedTypes()
{
- SurrogateDataTable[key] = surrogateData;
+ if (_referencedTypesDictionary == null)
+ {
+ _referencedTypesDictionary = new Dictionary();
+ //Always include Nullable as referenced type
+ //Do not allow surrogating Nullable
+ _referencedTypesDictionary.Add(DataContract.GetXmlName(Globals.TypeOfNullable), Globals.TypeOfNullable);
+ if (_referencedTypes != null)
+ {
+ foreach (Type type in _referencedTypes)
+ {
+ if (type == null)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.ReferencedTypesCannotContainNull)));
+
+ AddReferencedType(_referencedTypesDictionary, type);
+ }
+ }
+ }
+ return _referencedTypesDictionary;
}
- public IDataContractSurrogate DataContractSurrogate
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private Dictionary GetReferencedCollectionTypes()
{
- get { return _dataContractSurrogate; }
+ if (_referencedCollectionTypesDictionary == null)
+ {
+ _referencedCollectionTypesDictionary = new Dictionary();
+ if (_referencedCollectionTypes != null)
+ {
+ foreach (Type type in _referencedCollectionTypes)
+ {
+ if (type == null)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.ReferencedCollectionTypesCannotContainNull)));
+ AddReferencedType(_referencedCollectionTypesDictionary, type);
+ }
+ }
+ XmlQualifiedName genericDictionaryName = DataContract.GetXmlName(Globals.TypeOfDictionaryGeneric);
+ if (!_referencedCollectionTypesDictionary.ContainsKey(genericDictionaryName) && GetReferencedTypes().ContainsKey(genericDictionaryName))
+ AddReferencedType(_referencedCollectionTypesDictionary, Globals.TypeOfDictionaryGeneric);
+ }
+ return _referencedCollectionTypesDictionary;
}
-#endif
- public IEnumerator> GetEnumerator()
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private void AddReferencedType(Dictionary referencedTypes, Type type)
{
- return Contracts.GetEnumerator();
+ if (IsTypeReferenceable(type))
+ {
+ XmlQualifiedName xmlName;
+ try
+ {
+ xmlName = GetXmlName(type);
+ }
+ catch (InvalidDataContractException)
+ {
+ // Type not referenceable if we can't get a xml name.
+ return;
+ }
+ catch (InvalidOperationException)
+ {
+ // Type not referenceable if we can't get a xml name.
+ return;
+ }
+
+ if (referencedTypes.TryGetValue(xmlName, out object? value))
+ {
+ if (value is Type referencedType)
+ {
+ if (referencedType != type)
+ {
+ referencedTypes.Remove(xmlName);
+ List types = new List();
+ types.Add(referencedType);
+ types.Add(type);
+ referencedTypes.Add(xmlName, types);
+ }
+ }
+ else
+ {
+ List types = (List)value;
+ if (!types.Contains(type))
+ types.Add(type);
+ }
+ }
+ else
+ referencedTypes.Add(xmlName, type);
+ }
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private static bool IsTypeReferenceable(Type type)
+ {
+ try
+ {
+ return (type.IsSerializable ||
+ type.IsDefined(Globals.TypeOfDataContractAttribute, false) ||
+ (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type) && !type.IsGenericTypeDefinition) ||
+ CollectionDataContract.IsCollection(type, out _) ||
+ ClassDataContract.IsNonAttributedTypeValidForSerialization(type));
+ }
+ catch (Exception ex)
+ {
+ // An exception can be thrown in the designer when a project has a runtime binding redirection for a referenced assembly or a reference dependent assembly.
+ // Type.IsDefined is known to throw System.IO.FileLoadException.
+ // ClassDataContract.IsNonAttributedTypeValidForSerialization is known to throw System.IO.FileNotFoundException.
+ // We guard against all non-critical exceptions.
+ if (Fx.IsFatal(ex))
+ throw;
+ }
+
+ return false;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public Type? GetReferencedType(XmlQualifiedName xmlName, DataContract dataContract, out DataContract? referencedContract, out object[]? genericParameters, bool? supportGenericTypes = null)
+ {
+ Type? type = GetReferencedTypeInternal(xmlName, dataContract);
+ referencedContract = null;
+ genericParameters = null;
+
+ if (supportGenericTypes == null)
+ return type;
+
+ if (type != null && !type.IsGenericTypeDefinition && !type.ContainsGenericParameters)
+ return type;
+
+ if (dataContract.GenericInfo == null)
+ return null;
+
+ XmlQualifiedName genericXmlName = dataContract.GenericInfo.GetExpandedXmlName();
+ if (genericXmlName != dataContract.XmlName)
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.GenericTypeNameMismatch, dataContract.XmlName.Name, dataContract.XmlName.Namespace, genericXmlName.Name, genericXmlName.Namespace)));
+
+ // This check originally came "here" in the old code. Its tempting to move it up with the GenericInfo check.
+ if (!supportGenericTypes.Value)
+ return null;
+
+ type = GetReferencedGenericTypeInternal(dataContract.GenericInfo, out referencedContract, out genericParameters);
+ return type;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private Type? GetReferencedGenericTypeInternal(GenericInfo genInfo, out DataContract? referencedContract, out object[]? genericParameters)
+ {
+ genericParameters = null;
+ referencedContract = null;
+
+ Type? type = GetReferencedTypeInternal(genInfo.XmlName, null);
+
+ if (type == null)
+ {
+ if (genInfo.Parameters != null)
+ return null;
+
+ referencedContract = GetDataContract(genInfo.XmlName);
+ if (referencedContract != null && referencedContract.GenericInfo != null)
+ referencedContract = null;
+
+ return null; // No type, but maybe we found a suitable referenced contract?
+ }
+
+ // We've got a type. But its generic. So we need some parameter contracts.
+ // referencedContract is still null, but will be set if we can verify all parameters.
+ if (genInfo.Parameters != null)
+ {
+ bool enableStructureCheck = (type != Globals.TypeOfNullable);
+ genericParameters = new object[genInfo.Parameters.Count];
+ DataContract[] structureCheckContracts = new DataContract[genInfo.Parameters.Count];
+ for (int i = 0; i < genInfo.Parameters.Count; i++)
+ {
+ GenericInfo paramInfo = genInfo.Parameters[i];
+ XmlQualifiedName paramXmlName = paramInfo.GetExpandedXmlName();
+ DataContract? paramContract = GetDataContract(paramXmlName);
+
+ if (paramContract != null)
+ {
+ genericParameters[i] = paramContract;
+ }
+ else
+ {
+ Type? paramType = GetReferencedGenericTypeInternal(paramInfo, out paramContract, out object[]? paramParameters);
+ if (paramType != null)
+ {
+ genericParameters[i] = new Tuple(paramType, paramParameters);
+ }
+ else
+ {
+ genericParameters[i] = paramContract!;
+ }
+ }
+
+ structureCheckContracts[i] = paramContract!; // This is ok. If it's null, we disable the use of this array in the next line.
+ if (paramContract == null)
+ enableStructureCheck = false;
+ }
+ if (enableStructureCheck)
+ referencedContract = DataContract.GetDataContract(type).BindGenericParameters(structureCheckContracts);
+ }
+
+ return type;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private Type? GetReferencedTypeInternal(XmlQualifiedName xmlName, DataContract? dataContract)
+ {
+ Type? type;
+
+ if (dataContract == null)
+ {
+ if (TryGetReferencedCollectionType(xmlName, null, out type))
+ return type;
+ if (TryGetReferencedType(xmlName, null, out type))
+ {
+ // enforce that collection types only be specified via ReferencedCollectionTypes
+ if (CollectionDataContract.IsCollection(type))
+ return null;
+
+ return type;
+ }
+ }
+ else if (dataContract is CollectionDataContract)
+ {
+ if (TryGetReferencedCollectionType(xmlName, dataContract, out type))
+ return type;
+ }
+ else
+ {
+ if (dataContract is XmlDataContract xmlDataContract && xmlDataContract.IsAnonymous)
+ xmlName = SchemaImporter.ImportActualType(xmlDataContract.XsdType?.Annotation, xmlName, dataContract.XmlName);
+
+ if (TryGetReferencedType(xmlName, dataContract, out type))
+ return type;
+ }
+ return null;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal bool TryGetReferencedType(XmlQualifiedName xmlName, DataContract? dataContract, [NotNullWhen(true)] out Type? type)
+ {
+ return TryGetReferencedType(xmlName, dataContract, false/*useReferencedCollectionTypes*/, out type);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal bool TryGetReferencedCollectionType(XmlQualifiedName xmlName, DataContract? dataContract, [NotNullWhen(true)] out Type? type)
+ {
+ return TryGetReferencedType(xmlName, dataContract, true/*useReferencedCollectionTypes*/, out type);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ private bool TryGetReferencedType(XmlQualifiedName xmlName, DataContract? dataContract, bool useReferencedCollectionTypes, [NotNullWhen(true)] out Type? type)
+ {
+ Dictionary referencedTypes = useReferencedCollectionTypes ? GetReferencedCollectionTypes() : GetReferencedTypes();
+ if (referencedTypes.TryGetValue(xmlName, out object? value))
+ {
+ type = value as Type;
+ if (type != null)
+ {
+ return true;
+ }
+ else
+ {
+ // Throw ambiguous type match exception
+ List types = (List)value;
+ StringBuilder errorMessage = new StringBuilder();
+ bool containsGenericType = false;
+ for (int i = 0; i < types.Count; i++)
+ {
+ Type conflictingType = types[i];
+ if (!containsGenericType)
+ containsGenericType = conflictingType.IsGenericTypeDefinition;
+ errorMessage.AppendFormat("{0}\"{1}\" ", Environment.NewLine, conflictingType.AssemblyQualifiedName);
+ if (dataContract != null)
+ {
+ DataContract other = GetDataContract(conflictingType);
+ errorMessage.Append(SR.Format(((other != null && other.Equals(dataContract)) ? SR.ReferencedTypeMatchingMessage : SR.ReferencedTypeNotMatchingMessage)));
+ }
+ }
+ if (containsGenericType)
+ {
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(
+ (useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes1 : SR.AmbiguousReferencedTypes1),
+ errorMessage.ToString())));
+ }
+ else
+ {
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(
+ (useReferencedCollectionTypes ? SR.AmbiguousReferencedCollectionTypes3 : SR.AmbiguousReferencedTypes3),
+ XmlConvert.DecodeName(xmlName.Name),
+ xmlName.Namespace,
+ errorMessage.ToString())));
+ }
+ }
+ }
+ type = null;
+ return false;
+ }
+
+ internal ISerializationSurrogateProvider2? SerializationExtendedSurrogateProvider => _extendedSurrogateProvider;
+
+ internal object? GetSurrogateData(object key)
+ {
+ return SurrogateData[key];
+ }
+
+ internal void SetSurrogateData(object key, object? surrogateData)
+ {
+ SurrogateData[key] = surrogateData;
}
internal bool IsContractProcessed(DataContract dataContract)
@@ -291,19 +615,24 @@ internal void SetContractProcessed(DataContract dataContract)
ProcessedContracts.Add(dataContract, dataContract);
}
-#if SUPPORT_SURROGATE
- internal ContractCodeDomInfo GetContractCodeDomInfo(DataContract dataContract)
+ internal IEnumerator> GetEnumerator()
{
- object info;
- if (ProcessedContracts.TryGetValue(dataContract, out info))
- return (ContractCodeDomInfo)info;
- return null;
+ return Contracts.GetEnumerator();
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public void ImportSchemaSet(XmlSchemaSet schemaSet, IEnumerable? typeNames, bool importXmlDataType)
+ {
+ SchemaImporter importer = new SchemaImporter(schemaSet, typeNames, null, this, importXmlDataType);
+ importer.Import(out List _);
}
- internal void SetContractCodeDomInfo(DataContract dataContract, ContractCodeDomInfo info)
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ public List ImportSchemaSet(XmlSchemaSet schemaSet, IEnumerable elements, bool importXmlDataType)
{
- ProcessedContracts.Add(dataContract, info);
+ SchemaImporter importer = new SchemaImporter(schemaSet, Array.Empty() /* Needs to be empty, not null for 'elements' to be used. */, elements, this, importXmlDataType);
+ importer.Import(out List? elementNames);
+ return elementNames!; // Not null when we have provided non-null 'typeNames' and 'elements'
}
-#endif
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSurrogateCaller.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSurrogateCaller.cs
index 03d145ba53b88..a0554e10fd628 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSurrogateCaller.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContractSurrogateCaller.cs
@@ -2,10 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.CodeDom;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
+using System.Runtime.Serialization.DataContracts;
namespace System.Runtime.Serialization
{
@@ -40,5 +40,31 @@ internal static Type GetDataContractType(ISerializationSurrogateProvider surroga
return obj;
return surrogateProvider.GetDeserializedObject(obj, memberType);
}
+
+ internal static object? GetCustomDataToExport(ISerializationSurrogateProvider2 surrogateProvider, MemberInfo memberInfo, Type dataContractType)
+ {
+ return surrogateProvider.GetCustomDataToExport(memberInfo, dataContractType);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal static object? GetCustomDataToExport(ISerializationSurrogateProvider2 surrogateProvider, Type clrType, Type dataContractType)
+ {
+ if (DataContract.GetBuiltInDataContract(clrType) != null)
+ return null;
+ return surrogateProvider.GetCustomDataToExport(clrType, dataContractType);
+ }
+
+ internal static void GetKnownCustomDataTypes(ISerializationSurrogateProvider2 surrogateProvider, Collection customDataTypes)
+ {
+ surrogateProvider.GetKnownCustomDataTypes(customDataTypes);
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal static Type? GetReferencedTypeOnImport(ISerializationSurrogateProvider2 surrogateProvider, string typeName, string typeNamespace, object? customData)
+ {
+ if (DataContract.GetBuiltInDataContract(typeName, typeNamespace) != null)
+ return null;
+ return surrogateProvider.GetReferencedTypeOnImport(typeName, typeNamespace, customData);
+ }
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataMember.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataMember.cs
index 251e896e86488..2f1ed959e98dc 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataMember.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataMember.cs
@@ -2,17 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Globalization;
-using System.Reflection;
-using System.Xml;
-using System.Security;
using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
-namespace System.Runtime.Serialization
+namespace System.Runtime.Serialization.DataContracts
{
- internal sealed class DataMember
+ public sealed class DataMember
{
private readonly CriticalHelper _helper;
@@ -21,104 +17,73 @@ internal DataMember(MemberInfo memberInfo)
_helper = new CriticalHelper(memberInfo);
}
- internal MemberInfo MemberInfo
+ internal DataMember(DataContract memberTypeContract, string name, bool isNullable, bool isRequired, bool emitDefaultValue, long order)
{
- get
- { return _helper.MemberInfo; }
+ _helper = new CriticalHelper(memberTypeContract, name, isNullable, isRequired, emitDefaultValue, order);
}
+ internal MemberInfo MemberInfo => _helper.MemberInfo;
+
public string Name
{
- get
- { return _helper.Name; }
-
- set
- { _helper.Name = value; }
+ get => _helper.Name;
+ internal set => _helper.Name = value;
}
- public int Order
+ public long Order
{
- get
- { return _helper.Order; }
-
- set
- { _helper.Order = value; }
+ get => _helper.Order;
+ internal set => _helper.Order = value;
}
public bool IsRequired
{
- get
- { return _helper.IsRequired; }
-
- set
- { _helper.IsRequired = value; }
+ get => _helper.IsRequired;
+ internal set => _helper.IsRequired = value;
}
public bool EmitDefaultValue
{
- get
- { return _helper.EmitDefaultValue; }
-
- set
- { _helper.EmitDefaultValue = value; }
+ get => _helper.EmitDefaultValue;
+ internal set => _helper.EmitDefaultValue = value;
}
public bool IsNullable
{
- get
- { return _helper.IsNullable; }
-
- set
- { _helper.IsNullable = value; }
+ get => _helper.IsNullable;
+ internal set => _helper.IsNullable = value;
}
- public bool IsGetOnlyCollection
+ internal bool IsGetOnlyCollection
{
- get
- { return _helper.IsGetOnlyCollection; }
-
- set
- { _helper.IsGetOnlyCollection = value; }
+ get => _helper.IsGetOnlyCollection;
+ set => _helper.IsGetOnlyCollection = value;
}
- internal Type MemberType
- {
- get
- { return _helper.MemberType; }
- }
+ internal Type MemberType => _helper.MemberType;
- internal DataContract MemberTypeContract
+ public DataContract MemberTypeContract
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- { return _helper.MemberTypeContract; }
+ get => _helper.MemberTypeContract;
}
internal PrimitiveDataContract? MemberPrimitiveContract
{
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- get
- {
- return _helper.MemberPrimitiveContract;
- }
+ get => _helper.MemberPrimitiveContract;
}
- public bool HasConflictingNameAndType
+ internal bool HasConflictingNameAndType
{
- get
- { return _helper.HasConflictingNameAndType; }
-
- set
- { _helper.HasConflictingNameAndType = value; }
+ get => _helper.HasConflictingNameAndType;
+ set => _helper.HasConflictingNameAndType = value;
}
internal DataMember? ConflictingMember
{
- get
- { return _helper.ConflictingMember; }
-
- set
- { _helper.ConflictingMember = value; }
+ get => _helper.ConflictingMember;
+ set => _helper.ConflictingMember = value;
}
private FastInvokerBuilder.Getter? _getter;
@@ -131,12 +96,13 @@ private sealed class CriticalHelper
{
private DataContract? _memberTypeContract;
private string _name = null!; // Name is always initialized right after construction
- private int _order;
+ private long _order;
private bool _isRequired;
private bool _emitDefaultValue;
private bool _isNullable;
private bool _isGetOnlyCollection;
private readonly MemberInfo _memberInfo;
+ private Type? _memberType;
private bool _hasConflictingNameAndType;
private DataMember? _conflictingMember;
@@ -147,60 +113,67 @@ internal CriticalHelper(MemberInfo memberInfo)
_memberPrimitiveContract = PrimitiveDataContract.NullContract;
}
- internal MemberInfo MemberInfo
+ internal CriticalHelper(DataContract memberTypeContract, string name, bool isNullable, bool isRequired, bool emitDefaultValue, long order)
{
- get { return _memberInfo; }
+ _memberTypeContract = memberTypeContract;
+ _name = name;
+ _isNullable = isNullable;
+ _isRequired = isRequired;
+ _emitDefaultValue = emitDefaultValue;
+ _order = order;
+ _memberInfo = memberTypeContract.UnderlyingType;
}
+ internal MemberInfo MemberInfo => _memberInfo;
+
internal string Name
{
- get { return _name; }
- set { _name = value; }
+ get => _name;
+ set => _name = value;
}
- internal int Order
+ internal long Order
{
- get { return _order; }
- set { _order = value; }
+ get => _order;
+ set => _order = value;
}
internal bool IsRequired
{
- get { return _isRequired; }
- set { _isRequired = value; }
+ get => _isRequired;
+ set => _isRequired = value;
}
internal bool EmitDefaultValue
{
- get { return _emitDefaultValue; }
- set { _emitDefaultValue = value; }
+ get => _emitDefaultValue;
+ set => _emitDefaultValue = value;
}
internal bool IsNullable
{
- get { return _isNullable; }
- set { _isNullable = value; }
+ get => _isNullable;
+ set => _isNullable = value;
}
internal bool IsGetOnlyCollection
{
- get { return _isGetOnlyCollection; }
- set { _isGetOnlyCollection = value; }
+ get => _isGetOnlyCollection;
+ set => _isGetOnlyCollection = value;
}
- private Type? _memberType;
-
internal Type MemberType
{
get
{
if (_memberType == null)
{
- FieldInfo? field = MemberInfo as FieldInfo;
- if (field != null)
+ if (MemberInfo is FieldInfo field)
_memberType = field.FieldType;
+ else if (MemberInfo is PropertyInfo prop)
+ _memberType = prop.PropertyType;
else
- _memberType = ((PropertyInfo)MemberInfo).PropertyType;
+ _memberType = (Type)MemberInfo!;
}
return _memberType;
@@ -214,9 +187,9 @@ internal DataContract MemberTypeContract
{
if (_memberTypeContract == null)
{
- if (this.IsGetOnlyCollection)
+ if (IsGetOnlyCollection)
{
- _memberTypeContract = DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(MemberType.TypeHandle), MemberType.TypeHandle, MemberType, SerializationMode.SharedContract);
+ _memberTypeContract = DataContract.GetGetOnlyCollectionDataContract(DataContract.GetId(MemberType.TypeHandle), MemberType.TypeHandle, MemberType);
}
else
{
@@ -234,14 +207,14 @@ internal DataContract MemberTypeContract
internal bool HasConflictingNameAndType
{
- get { return _hasConflictingNameAndType; }
- set { _hasConflictingNameAndType = value; }
+ get => _hasConflictingNameAndType;
+ set => _hasConflictingNameAndType = value;
}
internal DataMember? ConflictingMember
{
- get { return _conflictingMember; }
- set { _conflictingMember = value; }
+ get => _conflictingMember;
+ set => _conflictingMember = value;
}
private PrimitiveDataContract? _memberPrimitiveContract;
@@ -310,5 +283,38 @@ internal bool RequiresMemberAccessForSet()
}
return false;
}
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal DataMember BindGenericParameters(DataContract[] paramContracts, Dictionary? boundContracts = null)
+ {
+ DataContract memberTypeContract = MemberTypeContract.BindGenericParameters(paramContracts, boundContracts);
+ DataMember boundDataMember = new DataMember(memberTypeContract,
+ Name,
+ !memberTypeContract.IsValueType,
+ IsRequired,
+ EmitDefaultValue,
+ Order);
+ return boundDataMember;
+ }
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal bool Equals(object? other, HashSet? checkedContracts)
+ {
+ if (this == other)
+ return true;
+
+ if (other is DataMember dataMember)
+ {
+ // Note: comparison does not use Order hint since it influences element order but does not specify exact order
+ bool thisIsNullable = (MemberTypeContract == null) ? false : !MemberTypeContract.IsValueType;
+ bool dataMemberIsNullable = (dataMember.MemberTypeContract == null) ? false : !dataMember.MemberTypeContract.IsValueType;
+ return (Name == dataMember.Name
+ && (IsNullable || thisIsNullable) == (dataMember.IsNullable || dataMemberIsNullable)
+ && IsRequired == dataMember.IsRequired
+ && EmitDefaultValue == dataMember.EmitDefaultValue
+ && MemberTypeContract!.Equals(dataMember.MemberTypeContract, checkedContracts));
+ }
+ return false;
+ }
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DateTimeOffsetAdapter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DateTimeOffsetAdapter.cs
index 20cb05471fe63..da469b0c337c6 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DateTimeOffsetAdapter.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DateTimeOffsetAdapter.cs
@@ -66,7 +66,7 @@ public static DateTimeOffsetAdapter GetDateTimeOffsetAdapter(DateTimeOffset valu
public string ToString(IFormatProvider provider)
{
- return "DateTime: " + this.UtcDateTime + ", Offset: " + this.OffsetMinutes;
+ return "DateTime: " + UtcDateTime + ", Offset: " + OffsetMinutes;
}
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DiagnosticUtility.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DiagnosticUtility.cs
index 012b8ec54929b..a6217253340dc 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DiagnosticUtility.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DiagnosticUtility.cs
@@ -3,6 +3,8 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Threading;
namespace System.Runtime.Serialization
{
@@ -20,6 +22,50 @@ public static void Assert(string message)
{
Assert(false, message);
}
+
+ public static bool IsFatal(Exception exception)
+ {
+ while (exception != null)
+ {
+ // NetFx checked for FatalException and FatalInternalException as well, which were ServiceModel constructs.
+ if ((exception is OutOfMemoryException && !(exception is InsufficientMemoryException)) ||
+ exception is ThreadAbortException)
+ {
+ return true;
+ }
+
+ // These exceptions aren't themselves fatal, but since the CLR uses them to wrap other exceptions,
+ // we want to check to see whether they've been used to wrap a fatal exception. If so, then they
+ // count as fatal.
+ if (exception is TypeInitializationException ||
+ exception is TargetInvocationException)
+ {
+ exception = exception.InnerException!;
+ }
+ else if (exception is AggregateException)
+ {
+ // AggregateExceptions have a collection of inner exceptions, which may themselves be other
+ // wrapping exceptions (including nested AggregateExceptions). Recursively walk this
+ // hierarchy. The (singular) InnerException is included in the collection.
+ var innerExceptions = ((AggregateException)exception).InnerExceptions;
+ foreach (Exception innerException in innerExceptions)
+ {
+ if (IsFatal(innerException))
+ {
+ return true;
+ }
+ }
+
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return false;
+ }
}
internal static class DiagnosticUtility
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
index 9014a71b47d40..ac13799e9e78f 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/EnumDataContract.cs
@@ -2,75 +2,80 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Globalization;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using System.Reflection;
using System.Threading;
-using System.Text;
using System.Xml;
-using System.Security;
-using System.Linq;
-using System.Diagnostics.CodeAnalysis;
-namespace System.Runtime.Serialization
+namespace System.Runtime.Serialization.DataContracts
{
internal sealed class EnumDataContract : DataContract
{
- private readonly EnumDataContractCriticalHelper _helper;
+ internal const string ContractTypeString = nameof(EnumDataContract);
+ public override string? ContractType => ContractTypeString;
- public XmlQualifiedName? BaseContractName { get; set; }
+ private readonly EnumDataContractCriticalHelper _helper;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
internal EnumDataContract(Type type) : base(new EnumDataContractCriticalHelper(type))
{
_helper = (base.Helper as EnumDataContractCriticalHelper)!;
}
- public List Members
+
+ internal static Type? GetBaseType(XmlQualifiedName baseContractName)
{
- get
- { return _helper.Members; }
- set { _helper.Members = value; }
+ return EnumDataContractCriticalHelper.GetBaseType(baseContractName);
}
- public List? Values
+ public override DataContract BaseContract
{
- get
- { return _helper.Values; }
- set { _helper.Values = value; }
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ get => _helper.BaseContract;
}
- public bool IsFlags
+ internal XmlQualifiedName BaseContractName
{
- get
- { return _helper.IsFlags; }
- set { _helper.IsFlags = value; }
+ get => _helper.BaseContractName;
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ set => _helper.BaseContractName = value;
}
- public bool IsULong
+ internal List Members
{
- get
- { return _helper.IsULong; }
- set { _helper.IsULong = value; }
+ get => _helper.Members;
+ set => _helper.Members = value;
}
- public XmlDictionaryString[]? ChildElementNames
+ public override ReadOnlyCollection DataMembers => (Members == null) ? DataContract.s_emptyDataMemberList : Members.AsReadOnly();
+
+ internal List? Values
{
- get
- { return _helper.ChildElementNames; }
- set { _helper.ChildElementNames = value; }
+ get => _helper.Values;
+ set => _helper.Values = value;
}
- internal override bool CanContainReferences
+ internal bool IsFlags
{
- get { return false; }
+ get => _helper.IsFlags;
+ set => _helper.IsFlags = value;
}
+ internal bool IsULong => _helper.IsULong;
+
+ internal XmlDictionaryString[]? ChildElementNames => _helper.ChildElementNames;
+
+ internal override bool CanContainReferences => false;
+
private sealed class EnumDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private static readonly Dictionary s_typeToName = new Dictionary();
private static readonly Dictionary s_nameToType = new Dictionary();
+ private DataContract _baseContract;
private List _members;
private List? _values;
private bool _isULong;
@@ -80,21 +85,35 @@ private sealed class EnumDataContractCriticalHelper : DataContract.DataContractC
static EnumDataContractCriticalHelper()
{
- Add(typeof(sbyte), "byte");
- Add(typeof(byte), "unsignedByte");
- Add(typeof(short), "short");
- Add(typeof(ushort), "unsignedShort");
- Add(typeof(int), "int");
- Add(typeof(uint), "unsignedInt");
- Add(typeof(long), "long");
- Add(typeof(ulong), "unsignedLong");
+ Add(typeof(sbyte), DictionaryGlobals.SignedByteLocalName.Value); // "byte"
+ Add(typeof(byte), DictionaryGlobals.UnsignedByteLocalName.Value); // "unsignedByte"
+ Add(typeof(short), DictionaryGlobals.ShortLocalName.Value); // "short"
+ Add(typeof(ushort), DictionaryGlobals.UnsignedShortLocalName.Value); // "unsignedShort"
+ Add(typeof(int), DictionaryGlobals.IntLocalName.Value); // "int"
+ Add(typeof(uint), DictionaryGlobals.UnsignedIntLocalName.Value); // "unsignedInt"
+ Add(typeof(long), DictionaryGlobals.LongLocalName.Value); // "long"
+ Add(typeof(ulong), DictionaryGlobals.UnsignedLongLocalName.Value); // "unsignedLong"
}
internal static void Add(Type type, string localName)
{
- XmlQualifiedName stableName = CreateQualifiedName(localName, Globals.SchemaNamespace);
- s_typeToName.Add(type, stableName);
- s_nameToType.Add(stableName, type);
+ XmlQualifiedName xmlName = CreateQualifiedName(localName, Globals.SchemaNamespace);
+ s_typeToName.Add(type, xmlName);
+ s_nameToType.Add(xmlName, type);
+ }
+
+ internal static XmlQualifiedName GetBaseContractName(Type type)
+ {
+ s_typeToName.TryGetValue(type, out XmlQualifiedName? retVal);
+
+ Debug.Assert(retVal != null); // Enums can only have certain base types. We shouldn't come up empty here.
+ return retVal;
+ }
+
+ internal static Type? GetBaseType(XmlQualifiedName baseContractName)
+ {
+ s_nameToType.TryGetValue(baseContractName, out Type? retVal);
+ return retVal;
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
@@ -102,20 +121,23 @@ internal EnumDataContractCriticalHelper(
[DynamicallyAccessedMembers(ClassDataContract.DataContractPreserveMemberTypes)]
Type type) : base(type)
{
- this.StableName = DataContract.GetStableName(type, out _hasDataContract);
+ XmlName = DataContract.GetXmlName(type, out _hasDataContract);
Type baseType = Enum.GetUnderlyingType(type);
+ XmlQualifiedName baseTypeName = GetBaseContractName(baseType);
+ _baseContract = DataContract.GetBuiltInDataContract(baseTypeName.Name, baseTypeName.Namespace)!;
+ // Setting XmlName might be redundant. But I don't want to miss an edge case.
+ _baseContract.XmlName = baseTypeName;
ImportBaseType(baseType);
IsFlags = type.IsDefined(Globals.TypeOfFlagsAttribute, false);
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
- Name = dictionary.Add(StableName.Name);
- Namespace = dictionary.Add(StableName.Namespace);
+ Name = dictionary.Add(XmlName.Name);
+ Namespace = dictionary.Add(XmlName.Namespace);
_childElementNames = new XmlDictionaryString[Members.Count];
for (int i = 0; i < Members.Count; i++)
_childElementNames[i] = dictionary.Add(Members[i].Name);
- DataContractAttribute? dataContractAttribute;
- if (TryGetDCAttribute(type, out dataContractAttribute))
+ if (TryGetDCAttribute(type, out DataContractAttribute? dataContractAttribute))
{
if (dataContractAttribute.IsReference)
{
@@ -128,34 +150,55 @@ internal EnumDataContractCriticalHelper(
}
}
}
+
+ internal DataContract BaseContract => _baseContract;
+
+ internal XmlQualifiedName BaseContractName
+ {
+ get => _baseContract.XmlName;
+
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ set
+ {
+ Type? baseType = GetBaseType(value);
+ if (baseType == null)
+ ThrowInvalidDataContractException(
+ SR.Format(SR.InvalidEnumBaseType, value.Name, value.Namespace, XmlName.Name, XmlName.Namespace));
+ ImportBaseType(baseType);
+ _baseContract = DataContract.GetBuiltInDataContract(value.Name, value.Namespace)!;
+ // Setting XmlName might be redundant. But I don't want to miss an edge case.
+ _baseContract.XmlName = value;
+ }
+ }
+
internal List Members
{
- get { return _members; }
- set { _members = value; }
+ get => _members;
+ set => _members = value;
}
internal List? Values
{
- get { return _values; }
- set { _values = value; }
+ get => _values;
+ set => _values = value;
}
internal bool IsFlags
{
- get { return _isFlags; }
- set { _isFlags = value; }
+ get => _isFlags;
+ set => _isFlags = value;
}
internal bool IsULong
{
- get { return _isULong; }
- set { _isULong = value; }
+ get => _isULong;
+ set => _isULong = value;
}
internal XmlDictionaryString[]? ChildElementNames
{
- get { return _childElementNames; }
- set { _childElementNames = value; }
+ get => _childElementNames;
+ set => _childElementNames = value;
}
private void ImportBaseType(Type baseType)
@@ -166,7 +209,7 @@ private void ImportBaseType(Type baseType)
[MemberNotNull(nameof(_members))]
private void ImportDataMembers()
{
- Type type = this.UnderlyingType;
+ Type type = UnderlyingType;
FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public);
Dictionary memberValuesTable = new Dictionary();
List tempMembers = new List(fields.Length);
@@ -194,6 +237,7 @@ private void ImportDataMembers()
}
else
memberContract.Name = field.Name;
+ memberContract.Order = _isULong ? (long)Convert.ToUInt64(field.GetValue(null)) : Convert.ToInt64(field.GetValue(null));
ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable);
enumMemberValid = true;
}
@@ -206,8 +250,8 @@ private void ImportDataMembers()
{
if (!field.IsNotSerialized)
{
- DataMember memberContract = new DataMember(field);
- memberContract.Name = field.Name;
+ DataMember memberContract = new DataMember(field) { Name = field.Name };
+ memberContract.Order = _isULong ? (long)Convert.ToUInt64(field.GetValue(null)) : Convert.ToInt64(field.GetValue(null));
ClassDataContract.CheckAndAddMember(tempMembers, memberContract, memberValuesTable);
enumMemberValid = true;
}
@@ -359,14 +403,45 @@ internal long GetEnumValueFromString(string value)
}
}
+ internal override bool Equals(object? other, HashSet? checkedContracts)
+ {
+ if (IsEqualOrChecked(other, checkedContracts))
+ return true;
+
+ if (base.Equals(other, null))
+ {
+ if (other is EnumDataContract enumContract)
+ {
+ if (Members.Count != enumContract.Members.Count || Values?.Count != enumContract.Values?.Count)
+ return false;
+ string[] memberNames1 = new string[Members.Count], memberNames2 = new string[Members.Count];
+ for (int i = 0; i < Members.Count; i++)
+ {
+ memberNames1[i] = Members[i].Name;
+ memberNames2[i] = enumContract.Members[i].Name;
+ }
+ Array.Sort(memberNames1);
+ Array.Sort(memberNames2);
+ for (int i = 0; i < Members.Count; i++)
+ {
+ if (memberNames1[i] != memberNames2[i])
+ return false;
+ }
+
+ return (IsFlags == enumContract.IsFlags);
+ }
+ }
+ return false;
+ }
+
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
+ internal override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext? context)
{
WriteEnumValue(xmlWriter, obj);
}
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
+ internal override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext? context)
{
object obj = ReadEnumValue(xmlReader);
context?.AddNewObject(obj);
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExportOptions.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExportOptions.cs
index 435415d1ca565..8034f326ea09e 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExportOptions.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExportOptions.cs
@@ -5,24 +5,26 @@
namespace System.Runtime.Serialization
{
+ ///
+ /// Represents the options that can be set for an .
+ ///
+ ///
+ /// The is used to generate XSD schemas from a type or assembly. You can also use the XsdDataContractImporter to generate .NET Framework code from a schema document.
+ ///
+ /// The property is used by the to include types that can be read in an object graph.
+ ///
public class ExportOptions
{
private Collection? _knownTypes;
-#if SUPPORT_SURROGATE
- private IDataContractSurrogate? _dataContractSurrogate;
- public IDataContractSurrogate? DataContractSurrogate
- {
- get { return _dataContractSurrogate; }
- set { _dataContractSurrogate = value; }
- }
-
- internal IDataContractSurrogate? GetSurrogate()
- {
- return _dataContractSurrogate;
- }
-#endif
+ ///
+ /// Gets or sets a serialization surrogate provider.
+ ///
+ public ISerializationSurrogateProvider? DataContractSurrogate { get; set; }
+ ///
+ /// Gets the collection of types that may be encountered during serialization or deserialization.
+ ///
public Collection KnownTypes => _knownTypes ??= new Collection();
}
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataObject.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataObject.cs
index be5723fb3b09a..6004b41c84e3c 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataObject.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataObject.cs
@@ -36,7 +36,7 @@ public ExtensionDataMember(string name, string ns)
public string Name { get; }
- public string? Namespace { get; }
+ public string Namespace { get; }
public IDataNode? Value
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataReader.cs
index df8b296a45713..d4309b86b3d4c 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataReader.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ExtensionDataReader.cs
@@ -1,9 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Xml;
using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Runtime.Serialization.DataContracts;
+using System.Xml;
namespace System.Runtime.Serialization
{
@@ -27,7 +31,7 @@ private enum ExtensionDataNodeType
private ElementData? _nextElement;
private ReadState _readState = ReadState.Initial;
- private readonly ExtensionDataNodeType _internalNodeType;
+ private ExtensionDataNodeType _internalNodeType;
private XmlNodeType _nodeType;
private int _depth;
private string? _localName;
@@ -37,11 +41,12 @@ private enum ExtensionDataNodeType
private int _attributeCount;
private int _attributeIndex;
+ private Hashtable _cache = new Hashtable();
+ private XmlNodeReader? _xmlNodeReader;
+ private Queue? _deserializedDataNodes;
+
private static readonly object s_prefixLock = new object();
-#pragma warning disable 0649
- private readonly XmlNodeReader? _xmlNodeReader;
-#pragma warning restore 0649
private readonly XmlObjectSerializerReadContext _context;
@@ -62,6 +67,16 @@ internal ExtensionDataReader(XmlObjectSerializerReadContext context)
_context = context;
}
+ internal void SetDeserializedValue(object? obj)
+ {
+ IDataNode? deserializedDataNode = (_deserializedDataNodes == null || _deserializedDataNodes.Count == 0) ? null : _deserializedDataNodes.Dequeue();
+ if (deserializedDataNode != null && !(obj is IDataNode))
+ {
+ deserializedDataNode.Value = obj;
+ deserializedDataNode.IsFinalValue = true;
+ }
+ }
+
internal IDataNode? GetCurrentNode()
{
IDataNode? retVal = _element!.dataNode;
@@ -69,6 +84,14 @@ internal ExtensionDataReader(XmlObjectSerializerReadContext context)
return retVal;
}
+ internal void SetDataNode(IDataNode dataNode, string? name, string? ns)
+ {
+ SetNextElement(dataNode, name, ns, null);
+ _element = _nextElement;
+ _nextElement = null;
+ SetElement();
+ }
+
internal void Reset()
{
_localName = null;
@@ -83,11 +106,9 @@ internal void Reset()
_elements = null;
}
-#pragma warning disable CS8775 // Member must have a non-null value when exiting in some condition.
[MemberNotNullWhen(true, nameof(_xmlNodeReader))]
[MemberNotNullWhen(false, nameof(_element))]
private bool IsXmlDataNode { get { return (_internalNodeType == ExtensionDataNodeType.Xml); } }
-#pragma warning restore CS8775 // Member must have a non-null value when exiting in some condition.
public override XmlNodeType NodeType { get { return IsXmlDataNode ? _xmlNodeReader.NodeType : _nodeType; } }
public override string LocalName { get { return IsXmlDataNode ? _xmlNodeReader.LocalName : _localName!; } }
@@ -427,9 +448,294 @@ public override bool ReadAttributeValue()
return false;
}
- private static void MoveNext(IDataNode? dataNode)
+ private void MoveNext(IDataNode? dataNode)
+ {
+ switch (_internalNodeType)
+ {
+ case ExtensionDataNodeType.Text:
+ case ExtensionDataNodeType.ReferencedElement:
+ case ExtensionDataNodeType.NullElement:
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ return;
+ default:
+ Type? dataNodeType = dataNode?.DataType;
+ if (dataNodeType == Globals.TypeOfClassDataNode)
+ MoveNextInClass((ClassDataNode)dataNode!);
+ else if (dataNodeType == Globals.TypeOfCollectionDataNode)
+ MoveNextInCollection((CollectionDataNode)dataNode!);
+ else if (dataNodeType == Globals.TypeOfISerializableDataNode)
+ MoveNextInISerializable((ISerializableDataNode)dataNode!);
+ else if (dataNodeType == Globals.TypeOfXmlDataNode)
+ MoveNextInXml((XmlDataNode)dataNode!);
+ else if (dataNode?.Value != null)
+ MoveToDeserializedObject(dataNode!);
+ else
+ {
+ Fx.Assert("Encountered invalid data node when deserializing unknown data");
+ throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.InvalidStateInExtensionDataReader)));
+ }
+ break;
+ }
+ }
+
+ private void SetNextElement(IDataNode? node, string? name, string? ns, string? prefix)
+ {
+ _internalNodeType = ExtensionDataNodeType.Element;
+ _nextElement = GetNextElement();
+ _nextElement.localName = name;
+ _nextElement.ns = ns;
+ _nextElement.prefix = prefix;
+ if (node == null)
+ {
+ _nextElement.attributeCount = 0;
+ _nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
+ _internalNodeType = ExtensionDataNodeType.NullElement;
+ }
+ else if (!CheckIfNodeHandled(node))
+ {
+ AddDeserializedDataNode(node);
+ node.GetData(_nextElement);
+ if (node is XmlDataNode xdn)
+ MoveNextInXml(xdn);
+ }
+ }
+
+ private void AddDeserializedDataNode(IDataNode node)
+ {
+ if (node.Id != Globals.NewObjectId && (node.Value == null || !node.IsFinalValue))
+ {
+ if (_deserializedDataNodes == null)
+ _deserializedDataNodes = new Queue();
+ _deserializedDataNodes.Enqueue(node);
+ }
+ }
+
+ private bool CheckIfNodeHandled(IDataNode node)
+ {
+ bool handled = false;
+ if (node.Id != Globals.NewObjectId)
+ {
+ handled = (_cache[node] != null);
+ if (handled)
+ {
+ if (_nextElement == null)
+ _nextElement = GetNextElement();
+ _nextElement.attributeCount = 0;
+ _nextElement.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.RefLocalName, node.Id.ToString(NumberFormatInfo.InvariantInfo));
+ _nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
+ _internalNodeType = ExtensionDataNodeType.ReferencedElement;
+ }
+ else
+ {
+ _cache.Add(node, node);
+ }
+ }
+ return handled;
+ }
+
+ private void MoveNextInClass(ClassDataNode dataNode)
+ {
+ // Two frames above here in Read(), _element is asserted not null.
+ Fx.Assert(_element != null, "");
+ if (dataNode.Members != null && _element.childElementIndex < dataNode.Members.Count)
+ {
+ if (_element.childElementIndex == 0)
+ _context.IncrementItemCount(-dataNode.Members.Count);
+
+ ExtensionDataMember member = dataNode.Members[_element.childElementIndex++];
+ SetNextElement(member.Value, member.Name, member.Namespace, GetPrefix(member.Namespace));
+ }
+ else
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ _element.childElementIndex = 0;
+ }
+ }
+
+ private void MoveNextInCollection(CollectionDataNode dataNode)
+ {
+ // Two frames above here in Read(), _element is asserted not null.
+ Fx.Assert(_element != null, "");
+ if (dataNode.Items != null && _element.childElementIndex < dataNode.Items.Count)
+ {
+ if (_element.childElementIndex == 0)
+ _context.IncrementItemCount(-dataNode.Items.Count);
+
+ IDataNode? item = dataNode.Items[_element.childElementIndex++];
+ SetNextElement(item, dataNode.ItemName, dataNode.ItemNamespace, GetPrefix(dataNode.ItemNamespace));
+ }
+ else
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ _element.childElementIndex = 0;
+ }
+ }
+
+ private void MoveNextInISerializable(ISerializableDataNode dataNode)
+ {
+ // Two frames above here in Read(), _element is asserted not null.
+ Fx.Assert(_element != null, "");
+ if (dataNode.Members != null && _element.childElementIndex < dataNode.Members.Count)
+ {
+ if (_element.childElementIndex == 0)
+ _context.IncrementItemCount(-dataNode.Members.Count);
+
+ ISerializableDataMember member = dataNode.Members[_element.childElementIndex++];
+ SetNextElement(member.Value, member.Name, string.Empty, string.Empty);
+ }
+ else
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ _element.childElementIndex = 0;
+ }
+ }
+
+ private void MoveNextInXml(XmlDataNode dataNode)
{
- throw NotImplemented.ByDesign;
+ if (IsXmlDataNode)
+ {
+ _xmlNodeReader.Read();
+ if (_xmlNodeReader.Depth == 0)
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ _xmlNodeReader = null;
+ }
+ }
+ else
+ {
+ _internalNodeType = ExtensionDataNodeType.Xml;
+ if (_element == null)
+ _element = _nextElement;
+ else
+ PushElement();
+
+ Debug.Assert(dataNode.OwnerDocument != null); // OwnerDocument is always set on initialized dataNodes
+
+ XmlElement wrapperElement = XmlObjectSerializerReadContext.CreateWrapperXmlElement(dataNode.OwnerDocument,
+ dataNode.XmlAttributes, dataNode.XmlChildNodes, _element?.prefix, _element?.localName, _element?.ns);
+ if (_element != null)
+ {
+ for (int i = 0; i < _element.attributeCount; i++)
+ {
+ AttributeData a = _element.attributes![i];
+ XmlAttribute xmlAttr = dataNode.OwnerDocument.CreateAttribute(a.prefix, a.localName!, a.ns);
+ xmlAttr.Value = a.value;
+ wrapperElement.Attributes.Append(xmlAttr);
+ }
+ }
+ _xmlNodeReader = new XmlNodeReader(wrapperElement);
+ _xmlNodeReader.Read();
+ }
+ }
+
+ private void MoveToDeserializedObject(IDataNode dataNode)
+ {
+ Type type = dataNode.DataType;
+ bool isTypedNode = true;
+ if (type == Globals.TypeOfObject && dataNode.Value != null)
+ {
+ type = dataNode.Value.GetType();
+ if (type == Globals.TypeOfObject)
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ return;
+ }
+ isTypedNode = false;
+ }
+
+ if (!MoveToText(type, dataNode, isTypedNode))
+ {
+ if (dataNode.IsFinalValue)
+ {
+ _internalNodeType = ExtensionDataNodeType.EndElement;
+ }
+ else
+ {
+ throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.Format(SR.InvalidDataNode, DataContract.GetClrTypeFullName(type))));
+ }
+ }
+ }
+
+ private bool MoveToText(Type type, IDataNode dataNode, bool isTypedNode)
+ {
+ Fx.Assert(dataNode.Value != null, "");
+
+ bool handled = true;
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.Boolean:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (bool)dataNode.Value);
+ break;
+ case TypeCode.Char:
+ _value = XmlConvert.ToString((int)(isTypedNode ? ((DataNode)dataNode).GetValue() : (char)dataNode.Value));
+ break;
+ case TypeCode.Byte:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (byte)dataNode.Value);
+ break;
+ case TypeCode.Int16:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (short)dataNode.Value);
+ break;
+ case TypeCode.Int32:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (int)dataNode.Value);
+ break;
+ case TypeCode.Int64:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (long)dataNode.Value);
+ break;
+ case TypeCode.Single:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (float)dataNode.Value);
+ break;
+ case TypeCode.Double:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (double)dataNode.Value);
+ break;
+ case TypeCode.Decimal:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (decimal)dataNode.Value);
+ break;
+ case TypeCode.DateTime:
+ DateTime dateTime = isTypedNode ? ((DataNode)dataNode).GetValue() : (DateTime)dataNode.Value;
+ _value = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", DateTimeFormatInfo.InvariantInfo);
+ break;
+ case TypeCode.String:
+ _value = isTypedNode ? ((DataNode)dataNode).GetValue() : (string?)dataNode.Value;
+ break;
+ case TypeCode.SByte:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (sbyte)dataNode.Value);
+ break;
+ case TypeCode.UInt16:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (ushort)dataNode.Value);
+ break;
+ case TypeCode.UInt32:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (uint)dataNode.Value);
+ break;
+ case TypeCode.UInt64:
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (ulong)dataNode.Value);
+ break;
+ case TypeCode.Object:
+ default:
+ if (type == Globals.TypeOfByteArray)
+ {
+ byte[]? bytes = isTypedNode ? ((DataNode)dataNode).GetValue() : (byte[])dataNode.Value;
+ _value = (bytes == null) ? string.Empty : Convert.ToBase64String(bytes);
+ }
+ else if (type == Globals.TypeOfTimeSpan)
+ _value = XmlConvert.ToString(isTypedNode ? ((DataNode)dataNode).GetValue() : (TimeSpan)dataNode.Value);
+ else if (type == Globals.TypeOfGuid)
+ {
+ Guid guid = isTypedNode ? ((DataNode)dataNode).GetValue() : (Guid)dataNode.Value;
+ _value = guid.ToString();
+ }
+ else if (type == Globals.TypeOfUri)
+ {
+ Uri uri = isTypedNode ? ((DataNode)dataNode).GetValue() : (Uri)dataNode.Value;
+ _value = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
+ }
+ else
+ handled = false;
+ break;
+ }
+
+ if (handled)
+ _internalNodeType = ExtensionDataNodeType.Text;
+ return handled;
}
private void PushElement()
@@ -477,11 +783,11 @@ private void GrowElementsIfNeeded()
}
}
- private ElementData? GetNextElement()
+ private ElementData GetNextElement()
{
int nextDepth = _depth + 1;
return (_elements == null || _elements.Length <= nextDepth || _elements[nextDepth] == null)
- ? new ElementData() : _elements[nextDepth];
+ ? new ElementData() : _elements[nextDepth]!;
}
internal static string GetPrefix(string? ns)
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/GenericParameterDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/GenericParameterDataContract.cs
index 8f5bd20805c9d..1d5eca774631c 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/GenericParameterDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/GenericParameterDataContract.cs
@@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-namespace System.Runtime.Serialization
+namespace System.Runtime.Serialization.DataContracts
{
internal sealed class GenericParameterDataContract : DataContract
{
@@ -18,19 +18,9 @@ internal GenericParameterDataContract(Type type)
_helper = (base.Helper as GenericParameterDataContractCriticalHelper)!;
}
- internal int ParameterPosition
- {
- get
- { return _helper.ParameterPosition; }
- }
+ internal int ParameterPosition => _helper.ParameterPosition;
- public override bool IsBuiltInDataContract
- {
- get
- {
- return true;
- }
- }
+ public override bool IsBuiltInDataContract => true;
private sealed class GenericParameterDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
@@ -42,17 +32,15 @@ internal GenericParameterDataContractCriticalHelper(
Type type)
: base(type)
{
- SetDataContractName(DataContract.GetStableName(type));
+ SetDataContractName(DataContract.GetXmlName(type));
_parameterPosition = type.GenericParameterPosition;
}
- internal int ParameterPosition
- {
- get { return _parameterPosition; }
- }
+ internal int ParameterPosition => _parameterPosition;
}
- internal DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary boundContracts)
+ [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
+ internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary? boundContracts = null)
{
return paramContracts[ParameterPosition];
}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
index 48167f42d04f6..3fa9493884c75 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs
@@ -2,13 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
+using System.Runtime.Serialization.DataContracts;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Schema;
@@ -227,6 +227,10 @@ internal static partial class Globals
internal static Type TypeOfNullable =>
s_typeOfNullable ??= typeof(Nullable<>);
+ private static Type? s_typeOfReflectionPointer;
+ internal static Type TypeOfReflectionPointer =>
+ s_typeOfReflectionPointer ??= typeof(System.Reflection.Pointer);
+
private static Type? s_typeOfIDictionaryGeneric;
internal static Type TypeOfIDictionaryGeneric =>
s_typeOfIDictionaryGeneric ??= typeof(IDictionary<,>);
@@ -271,10 +275,6 @@ internal static partial class Globals
internal static Type TypeOfKeyValuePair =>
s_typeOfKeyValuePair ??= typeof(KeyValuePair<,>);
- private static Type? s_typeOfKeyValuePairAdapter;
- internal static Type TypeOfKeyValuePairAdapter =>
- s_typeOfKeyValuePairAdapter ??= typeof(KeyValuePairAdapter<,>);
-
private static Type? s_typeOfKeyValue;
internal static Type TypeOfKeyValue =>
s_typeOfKeyValue ??= typeof(KeyValue<,>);
@@ -314,21 +314,25 @@ internal static Type TypeOfHashtable
internal static Type TypeOfDBNull =>
s_typeOfDBNull ??= typeof(DBNull);
- private static Uri? s_dataContractXsdBaseNamespaceUri;
- internal static Uri DataContractXsdBaseNamespaceUri =>
- s_dataContractXsdBaseNamespaceUri ??= new Uri(DataContractXsdBaseNamespace);
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicFields)]
+ private static Type? s_typeOfSchemaDefinedType;
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicFields)]
+ internal static Type TypeOfSchemaDefinedType =>
+ s_typeOfSchemaDefinedType ??= typeof(SchemaDefinedType);
- private static readonly Type? s_typeOfScriptObject;
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicFields)]
+ private static Type? s_typeOfSchemaDefinedEnum;
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicFields)]
+ internal static Type TypeOfSchemaDefinedEnum =>
+ s_typeOfSchemaDefinedEnum ??= typeof(SchemaDefinedEnum);
- [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
- internal static ClassDataContract CreateScriptObjectClassDataContract()
- {
- Debug.Assert(s_typeOfScriptObject != null);
- return new ClassDataContract(s_typeOfScriptObject);
- }
+ private static MemberInfo? s_schemaMemberInfoPlaceholder;
+ internal static MemberInfo SchemaMemberInfoPlaceholder =>
+ s_schemaMemberInfoPlaceholder ??= TypeOfSchemaDefinedType.GetField(nameof(SchemaDefinedType._xmlName), BindingFlags.NonPublic | BindingFlags.Instance)!;
- internal static bool TypeOfScriptObject_IsAssignableFrom(Type type) =>
- s_typeOfScriptObject != null && s_typeOfScriptObject.IsAssignableFrom(type);
+ private static Uri? s_dataContractXsdBaseNamespaceUri;
+ internal static Uri DataContractXsdBaseNamespaceUri =>
+ s_dataContractXsdBaseNamespaceUri ??= new Uri(DataContractXsdBaseNamespace);
public const bool DefaultIsRequired = false;
public const bool DefaultEmitDefaultValue = true;
@@ -341,6 +345,10 @@ internal static bool TypeOfScriptObject_IsAssignableFrom(Type type) =>
public const string FullSRSInternalsVisiblePattern = @"^[\s]*System\.Runtime\.Serialization[\s]*,[\s]*PublicKey[\s]*=[\s]*(?i:00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb77e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c123b37ab)[\s]*$";
[GeneratedRegex(FullSRSInternalsVisiblePattern)]
public static partial Regex FullSRSInternalsVisibleRegex();
+ public const char SpaceChar = ' ';
+ public const char OpenBracketChar = '[';
+ public const char CloseBracketChar = ']';
+ public const char CommaChar = ',';
public const string Space = " ";
public const string XsiPrefix = "i";
public const string XsdPrefix = "x";
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
index 4ab7ae4006ca9..208edd8125982 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs
@@ -10,10 +10,12 @@
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
+using System.Runtime.Serialization.DataContracts;
using System.Security;
using System.Text;
using System.Xml;
-using DataContractDictionary = System.Collections.Generic.Dictionary;
+
+using DataContractDictionary = System.Collections.Generic.Dictionary;
namespace System.Runtime.Serialization.Json
{
@@ -32,7 +34,7 @@ public sealed class DataContractJsonSerializer : XmlObjectSerializer
private XmlDictionaryString? _rootName;
private bool _rootNameRequiresMapping;
private Type _rootType;
-
+ private ISerializationSurrogateProvider? _serializationSurrogateProvider;
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
public DataContractJsonSerializer(Type type)
@@ -92,6 +94,12 @@ internal DataContractJsonSerializer(Type type,
Initialize(type, rootName, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, emitTypeInformation, false, null, false);
}
+ internal ISerializationSurrogateProvider? SerializationSurrogateProvider
+ {
+ get { return _serializationSurrogateProvider; }
+ set { _serializationSurrogateProvider = value; }
+ }
+
public bool IgnoreExtensionDataObject
{
get { return _ignoreExtensionDataObject; }
@@ -193,6 +201,19 @@ private XmlDictionaryString RootName
}
}
+ // These Get/Set methods mirror the extensions that were added to DCS in the early days of Core, which allowed
+ // using a slimmed-down surrogate on both NetFx and Core via type-forwarding mechanisms. That's why these are
+ // a pair of methods instead of making the property itself public.
+ public ISerializationSurrogateProvider? GetSerializationSurrogateProvider()
+ {
+ return SerializationSurrogateProvider;
+ }
+
+ public void SetSerializationSurrogateProvider(ISerializationSurrogateProvider? provider)
+ {
+ SerializationSurrogateProvider = provider;
+ }
+
[RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)]
public override bool IsStartObject(XmlReader reader)
{
@@ -451,6 +472,11 @@ internal override void InternalWriteObjectContent(XmlWriterDelegator writer, obj
Type declaredType = contract.UnderlyingType;
Type graphType = (graph == null) ? declaredType : graph.GetType();
+ if (_serializationSurrogateProvider != null)
+ {
+ graph = DataContractSerializer.SurrogateToDataContractType(_serializationSurrogateProvider, graph, declaredType, ref graphType);
+ }
+
if (graph == null)
{
WriteJsonNull(writer);
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializerExtensions.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializerExtensions.cs
new file mode 100644
index 0000000000000..0c52dee3789a8
--- /dev/null
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializerExtensions.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.Serialization.Json
+{
+ public static class DataContractJsonSerializerExtensions
+ {
+ public static ISerializationSurrogateProvider? GetSerializationSurrogateProvider(this DataContractJsonSerializer serializer)
+ {
+ return serializer.SerializationSurrogateProvider;
+ }
+
+ public static void SetSerializationSurrogateProvider(this DataContractJsonSerializer serializer, ISerializationSurrogateProvider? provider)
+ {
+ serializer.SerializationSurrogateProvider = provider;
+ }
+ }
+}
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonByteArrayDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonByteArrayDataContract.cs
index 5518442c8649d..8a6ca1fb0f4c4 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonByteArrayDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonByteArrayDataContract.cs
@@ -3,10 +3,11 @@
using System;
using System.Collections.Generic;
-using System.Text;
using System.Diagnostics;
-using System.Xml;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization.DataContracts;
+using System.Text;
+using System.Xml;
namespace System.Runtime.Serialization.Json
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs
index 6ff59d9eaa7f2..509b99f968217 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs
@@ -1,12 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Threading;
-using System.Xml;
-using System.Diagnostics;
using System.Collections.Generic;
-using System.Runtime.CompilerServices;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization.DataContracts;
+using System.Threading;
+using System.Xml;
namespace System.Runtime.Serialization.Json
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs
index 9d0a40cc5d1c9..cbf92bf3e43e3 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs
@@ -5,6 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.Serialization.DataContracts;
using System.Threading;
using System.Xml;
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonDataContract.cs
index 4330703dc3ab8..88258b3b397cd 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonDataContract.cs
@@ -2,12 +2,15 @@
// 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.Reflection;
using System.Runtime;
using System.Runtime.Serialization;
-using System.Reflection;
+using System.Runtime.Serialization.DataContracts;
using System.Xml;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
+
+using DataContractDictionary = System.Collections.Generic.Dictionary;
namespace System.Runtime.Serialization.Json
{
@@ -32,7 +35,7 @@ protected JsonDataContract(JsonDataContractCriticalHelper helper)
protected DataContract TraditionalDataContract => _helper.TraditionalDataContract;
- private Dictionary? KnownDataContracts => _helper.KnownDataContracts;
+ private DataContractDictionary? KnownDataContracts => _helper.KnownDataContracts;
public static JsonReadWriteDelegates? GetGeneratedReadWriteDelegates(DataContract c)
{
@@ -144,7 +147,7 @@ internal class JsonDataContractCriticalHelper
private static readonly TypeHandleRef s_typeHandleRef = new TypeHandleRef();
private static readonly Dictionary s_typeToIDCache = new Dictionary(new TypeHandleRefEqualityComparer());
- private Dictionary? _knownDataContracts;
+ private DataContractDictionary? _knownDataContracts;
private readonly DataContract _traditionalDataContract;
private readonly string _typeName;
@@ -156,7 +159,7 @@ internal JsonDataContractCriticalHelper(DataContract traditionalDataContract)
_typeName = string.IsNullOrEmpty(traditionalDataContract.Namespace.Value) ? traditionalDataContract.Name.Value : string.Concat(traditionalDataContract.Name.Value, JsonGlobals.NameValueSeparatorString, XmlObjectSerializerWriteContextComplexJson.TruncateDefaultDataContractNamespace(traditionalDataContract.Namespace.Value));
}
- internal Dictionary? KnownDataContracts => _knownDataContracts;
+ internal DataContractDictionary? KnownDataContracts => _knownDataContracts;
internal DataContract TraditionalDataContract => _traditionalDataContract;
@@ -201,6 +204,9 @@ internal static int GetId(RuntimeTypeHandle typeHandle)
}
catch (Exception ex)
{
+ if (Fx.IsFatal(ex))
+ throw;
+
throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
}
}
@@ -283,15 +289,15 @@ private void AddCollectionItemContractsToKnownDataContracts()
while (collectionDataContract != null)
{
DataContract itemContract = collectionDataContract.ItemContract;
- _knownDataContracts ??= new Dictionary();
+ _knownDataContracts ??= new DataContractDictionary();
- _knownDataContracts.TryAdd(itemContract.StableName, itemContract);
+ _knownDataContracts.TryAdd(itemContract.XmlName, itemContract);
if (collectionDataContract.ItemType.IsGenericType
&& collectionDataContract.ItemType.GetGenericTypeDefinition() == typeof(KeyValue<,>))
{
DataContract itemDataContract = DataContract.GetDataContract(Globals.TypeOfKeyValuePair.MakeGenericType(collectionDataContract.ItemType.GenericTypeArguments));
- _knownDataContracts.TryAdd(itemDataContract.StableName, itemDataContract);
+ _knownDataContracts.TryAdd(itemDataContract.XmlName, itemDataContract);
}
if (!(itemContract is CollectionDataContract))
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEnumDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEnumDataContract.cs
index 76f774cde91f0..e20b49ca92b4e 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEnumDataContract.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEnumDataContract.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization.DataContracts;
namespace System.Runtime.Serialization.Json
{
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs
index 0df641f90eea0..b094e6fcde688 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs
@@ -7,6 +7,7 @@
using System.Xml;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization.DataContracts;
using System.Runtime.Serialization.Json;
namespace System.Runtime.Serialization
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs
index ceee570b7475e..9b7dd72c90c93 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs
@@ -8,6 +8,7 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime;
+using System.Runtime.Serialization.DataContracts;
using System.Security;
using System.Xml;
@@ -62,7 +63,7 @@ public JsonFormatClassReaderDelegate GenerateClassReader(ClassDataContract class
bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null);
try
{
- BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(classContract.StableName!.Name) + "FromJson", typeof(JsonFormatClassReaderDelegate), memberAccessFlag);
+ BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(classContract.XmlName!.Name) + "FromJson", typeof(JsonFormatClassReaderDelegate), memberAccessFlag);
}
catch (SecurityException securityException)
{
@@ -109,12 +110,6 @@ public JsonFormatClassReaderDelegate GenerateClassReader(ClassDataContract class
_ilg.Call(XmlFormatGeneratorStatics.GetMemoryStreamMethod);
_ilg.ConvertValue(Globals.TypeOfMemoryStream, _ilg.CurrentMethod.ReturnType);
}
- //Copy the KeyValuePairAdapter to a KeyValuePair.
- else if (classContract.IsKeyValuePairAdapter)
- {
- _ilg.Call(classContract.GetKeyValuePairMethodInfo);
- _ilg.ConvertValue(Globals.TypeOfKeyValuePair.MakeGenericType(classContract.KeyValuePairGenericArguments), _ilg.CurrentMethod.ReturnType);
- }
else
{
_ilg.ConvertValue(_objectLocal.LocalType, _ilg.CurrentMethod.ReturnType);
@@ -149,11 +144,11 @@ private CodeGenerator GenerateCollectionReaderHelper(CollectionDataContract coll
{
if (isGetOnlyCollection)
{
- BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "FromJson" + "IsGetOnly", typeof(JsonFormatGetOnlyCollectionReaderDelegate), memberAccessFlag);
+ BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.XmlName.Name) + "FromJson" + "IsGetOnly", typeof(JsonFormatGetOnlyCollectionReaderDelegate), memberAccessFlag);
}
else
{
- BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "FromJson", typeof(JsonFormatCollectionReaderDelegate), memberAccessFlag);
+ BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.XmlName.Name) + "FromJson", typeof(JsonFormatCollectionReaderDelegate), memberAccessFlag);
}
}
catch (SecurityException securityException)
@@ -174,7 +169,7 @@ private CodeGenerator GenerateCollectionReaderHelper(CollectionDataContract coll
private static void BeginMethod(CodeGenerator ilg, string methodName, Type delegateType, bool allowPrivateMemberAccess)
{
- MethodInfo signature = JsonFormatWriterGenerator.GetInvokeMethod(delegateType);
+ MethodInfo signature = CodeGenerator.GetInvokeMethod(delegateType);
ParameterInfo[] parameters = signature.GetParameters();
Type[] paramTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
@@ -228,8 +223,8 @@ private void CreateObject(ClassDataContract classContract)
private void InvokeOnDeserializing(ClassDataContract classContract)
{
- if (classContract.BaseContract != null)
- InvokeOnDeserializing(classContract.BaseContract);
+ if (classContract.BaseClassContract != null)
+ InvokeOnDeserializing(classContract.BaseClassContract);
if (classContract.OnDeserializing != null)
{
_ilg.LoadAddress(_objectLocal);
@@ -242,8 +237,8 @@ private void InvokeOnDeserializing(ClassDataContract classContract)
private void InvokeOnDeserialized(ClassDataContract classContract)
{
- if (classContract.BaseContract != null)
- InvokeOnDeserialized(classContract.BaseContract);
+ if (classContract.BaseClassContract != null)
+ InvokeOnDeserialized(classContract.BaseClassContract);
if (classContract.OnDeserialized != null)
{
_ilg.LoadAddress(_objectLocal);
@@ -291,7 +286,7 @@ private void ReadClass(ClassDataContract classContract)
MethodInfo? extensionDataSetMethod = currentContract.ExtensionDataSetMethod;
if (extensionDataSetMethod != null)
_ilg.Call(_objectLocal, extensionDataSetMethod, extensionDataLocal);
- currentContract = currentContract.BaseContract;
+ currentContract = currentContract.BaseClassContract;
}
}
else
@@ -352,8 +347,8 @@ private void ReadMembers(ClassDataContract classContract, LocalBuilder? extensio
private int ReadMembers(ClassDataContract classContract, BitFlagsGenerator expectedElements,
Label[] memberLabels, Label throwDuplicateMemberLabel, LocalBuilder memberIndexLocal)
{
- int memberCount = (classContract.BaseContract == null) ? 0 :
- ReadMembers(classContract.BaseContract, expectedElements, memberLabels, throwDuplicateMemberLabel, memberIndexLocal);
+ int memberCount = (classContract.BaseClassContract == null) ? 0 :
+ ReadMembers(classContract.BaseClassContract, expectedElements, memberLabels, throwDuplicateMemberLabel, memberIndexLocal);
for (int i = 0; i < classContract.Members!.Count; i++, memberCount++)
{
@@ -415,8 +410,8 @@ private void LoadArray(byte[] array, string name)
private int SetRequiredElements(ClassDataContract contract, byte[] requiredElements)
{
- int memberCount = (contract.BaseContract == null) ? 0 :
- SetRequiredElements(contract.BaseContract, requiredElements);
+ int memberCount = (contract.BaseClassContract == null) ? 0 :
+ SetRequiredElements(contract.BaseClassContract, requiredElements);
List members = contract.Members!;
for (int i = 0; i < members.Count; i++, memberCount++)
{
@@ -906,7 +901,7 @@ private bool TryReadPrimitiveArray(Type itemType)
return false;
string? readArrayMethod = null;
- switch (itemType.GetTypeCode())
+ switch (Type.GetTypeCode(itemType))
{
case TypeCode.Boolean:
readArrayMethod = "TryReadBooleanArray";
diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs
index afe02b062b6a7..a57df0b14d279 100644
--- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs
+++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs
@@ -7,6 +7,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Emit;
+using System.Runtime.Serialization.DataContracts;
using System.Security;
using System.Xml;
@@ -36,14 +37,6 @@ internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionD
return _helper.GenerateCollectionWriter(collectionContract);
}
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
- Justification = "The trimmer will never remove the Invoke method from delegates.")]
- internal static MethodInfo GetInvokeMethod(Type delegateType)
- {
- Debug.Assert(typeof(Delegate).IsAssignableFrom(delegateType));
- return delegateType.GetMethod("Invoke")!;
- }
-
private sealed class CriticalHelper
{
private CodeGenerator _ilg = null!; // initialized in GenerateXXXWriter
@@ -64,7 +57,7 @@ internal JsonFormatClassWriterDelegate GenerateClassWriter(ClassDataContract cla
bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null);
try
{
- BeginMethod(_ilg, "Write" + DataContract.SanitizeTypeName(classContract.StableName.Name) + "ToJson", typeof(JsonFormatClassWriterDelegate), memberAccessFlag);
+ BeginMethod(_ilg, "Write" + DataContract.SanitizeTypeName(classContract.XmlName.Name) + "ToJson", typeof(JsonFormatClassWriterDelegate), memberAccessFlag);
}
catch (SecurityException securityException)
{
@@ -90,7 +83,7 @@ internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionD
bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null);
try
{
- BeginMethod(_ilg, "Write" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "ToJson", typeof(JsonFormatCollectionWriterDelegate), memberAccessFlag);
+ BeginMethod(_ilg, "Write" + DataContract.SanitizeTypeName(collectionContract.XmlName.Name) + "ToJson", typeof(JsonFormatCollectionWriterDelegate), memberAccessFlag);
}
catch (SecurityException securityException)
{
@@ -114,7 +107,7 @@ internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionD
private static void BeginMethod(CodeGenerator ilg, string methodName, Type delegateType, bool allowPrivateMemberAccess)
{
- MethodInfo signature = GetInvokeMethod(delegateType);
+ MethodInfo signature = CodeGenerator.GetInvokeMethod(delegateType);
ParameterInfo[] parameters = signature.GetParameters();
Type[] paramTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
@@ -149,13 +142,6 @@ private void InitArgs(Type objType)
_ilg.ConvertValue(objectArg.ArgType, Globals.TypeOfMemoryStream);
_ilg.Call(XmlFormatGeneratorStatics.GetMemoryStreamAdapterMethod);
}
- //Copy the KeyValuePair