|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace System.Runtime.Serialization
{
using System;
using System.Collections;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Reflection;
using System.Threading;
using Microsoft.Xml;
using DataContractDictionary = System.Collections.Generic.Dictionary<Microsoft.Xml.XmlQualifiedName, DataContract>;
using System.Security;
using System.Linq;
#if USE_REFEMIT || NET_NATIVE
public sealed class ClassDataContract : DataContract
#else
internal sealed class ClassDataContract : DataContract
#endif
{
/// <SecurityNote>
/// Review - XmlDictionaryString(s) representing the XML namespaces for class members.
/// statically cached and used from IL generated code. should ideally be Critical.
/// marked SecurityRequiresReview to be callable from transparent IL generated code.
/// not changed to property to avoid regressing performance; any changes to initalization should be reviewed.
/// </SecurityNote>
public XmlDictionaryString[] ContractNamespaces;
/// <SecurityNote>
/// Review - XmlDictionaryString(s) representing the XML element names for class members.
/// statically cached and used from IL generated code. should ideally be Critical.
/// marked SecurityRequiresReview to be callable from transparent IL generated code.
/// not changed to property to avoid regressing performance; any changes to initalization should be reviewed.
/// </SecurityNote>
public XmlDictionaryString[] MemberNames;
/// <SecurityNote>
/// Review - XmlDictionaryString(s) representing the XML namespaces for class members.
/// statically cached and used when calling IL generated code. should ideally be Critical.
/// marked SecurityRequiresReview to be callable from transparent code.
/// not changed to property to avoid regressing performance; any changes to initalization should be reviewed.
/// </SecurityNote>
public XmlDictionaryString[] MemberNamespaces;
[SecurityCritical]
/// <SecurityNote>
/// Critical - XmlDictionaryString representing the XML namespaces for members of class.
/// statically cached and used from IL generated code.
/// </SecurityNote>
private XmlDictionaryString[] _childElementNamespaces;
[SecurityCritical]
/// <SecurityNote>
/// Critical - holds instance of CriticalHelper which keeps state that is cached statically for serialization.
/// Static fields are marked SecurityCritical or readonly to prevent
/// data from being modified or leaked to other components in appdomain.
/// </SecurityNote>
private ClassDataContractCriticalHelper _helper;
private bool _isScriptObject;
#if NET_NATIVE || !disabled
public ClassDataContract() : base(new ClassDataContractCriticalHelper())
{
InitClassDataContract();
}
#endif
/// <SecurityNote>
/// Critical - initializes SecurityCritical field 'helper'
/// Safe - doesn't leak anything
/// </SecurityNote>
[SecuritySafeCritical]
internal ClassDataContract(Type type) : base(new ClassDataContractCriticalHelper(type))
{
InitClassDataContract();
}
[SecuritySafeCritical]
/// <SecurityNote>
/// Critical - initializes SecurityCritical field 'helper'
/// Safe - doesn't leak anything
/// </SecurityNote>
private ClassDataContract(Type type, XmlDictionaryString ns, string[] memberNames) : base(new ClassDataContractCriticalHelper(type, ns, memberNames))
{
InitClassDataContract();
}
[SecurityCritical]
/// <SecurityNote>
/// Critical - initializes SecurityCritical fields; called from all constructors
/// </SecurityNote>
private void InitClassDataContract()
{
_helper = base.Helper as ClassDataContractCriticalHelper;
this.ContractNamespaces = _helper.ContractNamespaces;
this.MemberNames = _helper.MemberNames;
this.MemberNamespaces = _helper.MemberNamespaces;
_isScriptObject = _helper.IsScriptObject;
}
internal ClassDataContract BaseContract
{
/// <SecurityNote>
/// Critical - fetches the critical baseContract property
/// Safe - baseContract only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.BaseContract; }
set
{
_helper.BaseContract = value;
}
}
internal List<DataMember> Members
{
/// <SecurityNote>
/// Critical - fetches the critical members property
/// Safe - members only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.Members; }
/// <SecurityNote>
/// Critical - Sets the critical members property.
/// Safe - Protected for write if contract has underlyingType.
/// </SecurityNote>
[SecurityCritical]
set { _helper.Members = value; }
}
public XmlDictionaryString[] ChildElementNamespaces
{
/// <SecurityNote>
/// Critical - fetches the critical childElementNamespaces property
/// Safe - childElementNamespaces only needs to be protected for write; initialized in getter if null
/// </SecurityNote>
[SecuritySafeCritical]
get
{
if (_childElementNamespaces == null)
{
lock (this)
{
if (_childElementNamespaces == null)
{
if (_helper.ChildElementNamespaces == null)
{
XmlDictionaryString[] tempChildElementamespaces = CreateChildElementNamespaces();
Interlocked.MemoryBarrier();
_helper.ChildElementNamespaces = tempChildElementamespaces;
}
_childElementNamespaces = _helper.ChildElementNamespaces;
}
}
}
return _childElementNamespaces;
}
#if NET_NATIVE
set
{
_childElementNamespaces = value;
}
#endif
}
internal MethodInfo OnSerializing
{
/// <SecurityNote>
/// Critical - fetches the critical onSerializing property
/// Safe - onSerializing only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.OnSerializing; }
}
internal MethodInfo OnSerialized
{
/// <SecurityNote>
/// Critical - fetches the critical onSerialized property
/// Safe - onSerialized only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.OnSerialized; }
}
internal MethodInfo OnDeserializing
{
/// <SecurityNote>
/// Critical - fetches the critical onDeserializing property
/// Safe - onDeserializing only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.OnDeserializing; }
}
internal MethodInfo OnDeserialized
{
/// <SecurityNote>
/// Critical - fetches the critical onDeserialized property
/// Safe - onDeserialized only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.OnDeserialized; }
}
#if !NET_NATIVE
public override DataContractDictionary KnownDataContracts
{
/// <SecurityNote>
/// Critical - fetches the critical knownDataContracts property
/// Safe - knownDataContracts only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.KnownDataContracts; }
}
#endif
internal bool IsNonAttributedType
{
/// <SecurityNote>
/// Critical - fetches the critical IsNonAttributedType property
/// Safe - IsNonAttributedType only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
get
{ return _helper.IsNonAttributedType; }
}
#if NET_NATIVE
public bool HasDataContract
{
[SecuritySafeCritical]
get
{ return _helper.HasDataContract; }
set { _helper.HasDataContract = value; }
}
public bool HasExtensionData
{
[SecuritySafeCritical]
get
{ return _helper.HasExtensionData; }
set { _helper.HasExtensionData = value; }
}
#endif
internal bool IsKeyValuePairAdapter
{
[SecuritySafeCritical]
get
{ return _helper.IsKeyValuePairAdapter; }
}
internal Type[] KeyValuePairGenericArguments
{
[SecuritySafeCritical]
get
{ return _helper.KeyValuePairGenericArguments; }
}
internal ConstructorInfo KeyValuePairAdapterConstructorInfo
{
[SecuritySafeCritical]
get
{ return _helper.KeyValuePairAdapterConstructorInfo; }
}
internal MethodInfo GetKeyValuePairMethodInfo
{
[SecuritySafeCritical]
get
{ return _helper.GetKeyValuePairMethodInfo; }
}
/// <SecurityNote>
/// Critical - fetches information about which constructor should be used to initialize non-attributed types that are valid for serialization
/// Safe - only needs to be protected for write
/// </SecurityNote>
[SecuritySafeCritical]
internal ConstructorInfo GetNonAttributedTypeConstructor()
{
return _helper.GetNonAttributedTypeConstructor();
}
#if !NET_NATIVE
internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate
{
/// <SecurityNote>
/// Critical - fetches the critical xmlFormatWriterDelegate property
/// Safe - xmlFormatWriterDelegate only needs to be protected for write; initialized in getter if null
/// </SecurityNote>
[SecuritySafeCritical]
get
{
if (_helper.XmlFormatWriterDelegate == null)
{
lock (this)
{
if (_helper.XmlFormatWriterDelegate == null)
{
XmlFormatClassWriterDelegate tempDelegate = new XmlFormatWriterGenerator().GenerateClassWriter(this);
Interlocked.MemoryBarrier();
_helper.XmlFormatWriterDelegate = tempDelegate;
}
}
}
return _helper.XmlFormatWriterDelegate;
}
}
#else
public XmlFormatClassWriterDelegate XmlFormatWriterDelegate { get; set; }
#endif
#if !NET_NATIVE
internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
{
/// <SecurityNote>
/// Critical - fetches the critical xmlFormatReaderDelegate property
/// Safe - xmlFormatReaderDelegate only needs to be protected for write; initialized in getter if null
/// </SecurityNote>
[SecuritySafeCritical]
get
{
if (_helper.XmlFormatReaderDelegate == null)
{
lock (this)
{
if (_helper.XmlFormatReaderDelegate == null)
{
XmlFormatClassReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateClassReader(this);
Interlocked.MemoryBarrier();
_helper.XmlFormatReaderDelegate = tempDelegate;
}
}
}
return _helper.XmlFormatReaderDelegate;
}
}
#else
public XmlFormatClassReaderDelegate XmlFormatReaderDelegate { get; set; }
#endif
internal static ClassDataContract CreateClassDataContractForKeyValue(Type type, XmlDictionaryString ns, string[] memberNames)
{
#if !NET_NATIVE
return new ClassDataContract(type, ns, memberNames);
#else
ClassDataContract cdc = (ClassDataContract)DataContract.GetDataContractFromGeneratedAssembly(type);
ClassDataContract cloned = cdc.Clone();
cloned.UpdateNamespaceAndMembers(type, ns, memberNames);
return cloned;
#endif
}
internal static void CheckAndAddMember(List<DataMember> members, DataMember memberContract, Dictionary<string, DataMember> memberNamesTable)
{
DataMember existingMemberContract;
if (memberNamesTable.TryGetValue(memberContract.Name, out existingMemberContract))
{
Type declaringType = memberContract.MemberInfo.DeclaringType;
DataContract.ThrowInvalidDataContractException(
string.Format((declaringType.GetTypeInfo().IsEnum ? SRSerialization.DupEnumMemberValue : SRSerialization.DupMemberName),
existingMemberContract.MemberInfo.Name,
memberContract.MemberInfo.Name,
DataContract.GetClrTypeFullName(declaringType),
memberContract.Name),
declaringType);
}
memberNamesTable.Add(memberContract.Name, memberContract);
members.Add(memberContract);
}
internal static XmlDictionaryString GetChildNamespaceToDeclare(DataContract dataContract, Type childType, XmlDictionary dictionary)
{
childType = DataContract.UnwrapNullableType(childType);
if (!childType.GetTypeInfo().IsEnum && !Globals.TypeOfIXmlSerializable.IsAssignableFrom(childType)
&& DataContract.GetBuiltInDataContract(childType) == null && childType != Globals.TypeOfDBNull)
{
string ns = DataContract.GetStableName(childType).Namespace;
if (ns.Length > 0 && ns != dataContract.Namespace.Value)
return dictionary.Add(ns);
}
return null;
}
private static bool IsArraySegment(Type t)
{
return t.GetTypeInfo().IsGenericType && (t.GetGenericTypeDefinition() == typeof(ArraySegment<>));
}
/// <SecurityNote>
/// RequiresReview - callers may need to depend on isNonAttributedType for a security decision
/// isNonAttributedType must be calculated correctly
/// IsNonAttributedTypeValidForSerialization is used as part of the isNonAttributedType calculation and
/// is therefore marked SRR
/// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value
/// </SecurityNote>
static internal bool IsNonAttributedTypeValidForSerialization(Type type)
{
if (type.IsArray)
return false;
if (type.GetTypeInfo().IsEnum)
return false;
if (type.IsGenericParameter)
return false;
if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
return false;
if (type.IsPointer)
return false;
if (type.GetTypeInfo().IsAttributeDefined(Globals.TypeOfCollectionDataContractAttribute))
return false;
Type[] interfaceTypes = type.GetInterfaces();
if (!IsArraySegment(type))
{
foreach (Type interfaceType in interfaceTypes)
{
if (CollectionDataContract.IsCollectionInterface(interfaceType))
return false;
}
}
if (type.GetTypeInfo().IsAttributeDefined(Globals.TypeOfDataContractAttribute))
return false;
if (type.GetTypeInfo().IsValueType)
{
return type.GetTypeInfo().IsVisible;
}
else
{
return (type.GetTypeInfo().IsVisible &&
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>()) != null);
}
}
private static string[] s_knownSerializableTypeNames = new string[] {
"System.Collections.Queue",
"System.Collections.Stack",
"System.Globalization.CultureInfo",
"System.Version",
"System.Collections.Generic.KeyValuePair`2",
"System.Collections.Generic.Queue`1",
"System.Collections.Generic.Stack`1",
"System.Collections.ObjectModel.ReadOnlyCollection`1",
"System.Collections.ObjectModel.ReadOnlyDictionary`2",
"System.Tuple`1",
"System.Tuple`2",
"System.Tuple`3",
"System.Tuple`4",
"System.Tuple`5",
"System.Tuple`6",
"System.Tuple`7",
"System.Tuple`8",
};
internal static bool IsKnownSerializableType(Type type)
{
// Applies to known types that DCS understands how to serialize/deserialize
//
// Ajdust for generic type
if (type.GetTypeInfo().IsGenericType && !type.GetTypeInfo().IsGenericTypeDefinition)
{
type = type.GetGenericTypeDefinition();
}
// Check for known types
if (Enumerable.Contains(s_knownSerializableTypeNames, type.FullName))
{
return true;
}
//Enable ClassDataContract to give support to Exceptions.
if (Globals.TypeOfException.IsAssignableFrom(type))
return true;
return false;
}
private XmlDictionaryString[] CreateChildElementNamespaces()
{
if (Members == null)
return null;
XmlDictionaryString[] baseChildElementNamespaces = null;
if (this.BaseContract != null)
baseChildElementNamespaces = this.BaseContract.ChildElementNamespaces;
int baseChildElementNamespaceCount = (baseChildElementNamespaces != null) ? baseChildElementNamespaces.Length : 0;
XmlDictionaryString[] childElementNamespaces = new XmlDictionaryString[Members.Count + baseChildElementNamespaceCount];
if (baseChildElementNamespaceCount > 0)
Array.Copy(baseChildElementNamespaces, 0, childElementNamespaces, 0, baseChildElementNamespaces.Length);
XmlDictionary dictionary = new XmlDictionary();
for (int i = 0; i < this.Members.Count; i++)
{
childElementNamespaces[i + baseChildElementNamespaceCount] = GetChildNamespaceToDeclare(this, this.Members[i].MemberType, dictionary);
}
return childElementNamespaces;
}
[SecuritySafeCritical]
/// <SecurityNote>
/// Critical - calls critical method on helper
/// Safe - doesn't leak anything
/// </SecurityNote>
private void EnsureMethodsImported()
{
_helper.EnsureMethodsImported();
}
public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
{
if (_isScriptObject)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(string.Format(SRSerialization.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
XmlFormatWriterDelegate(xmlWriter, obj, context, this);
}
public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
{
if (_isScriptObject)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(string.Format(SRSerialization.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
}
xmlReader.Read();
object o = XmlFormatReaderDelegate(xmlReader, context, MemberNames, MemberNamespaces);
xmlReader.ReadEndElement();
return o;
}
/// <SecurityNote>
/// Review - calculates whether this class requires MemberAccessPermission for deserialization.
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
internal bool RequiresMemberAccessForRead(SecurityException securityException)
{
EnsureMethodsImported();
if (!IsTypeVisible(UnderlyingType))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractTypeNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType)),
securityException));
}
return true;
}
if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForRead(securityException))
return true;
if (ConstructorRequiresMemberAccess(GetNonAttributedTypeConstructor()))
{
if (Globals.TypeOfScriptObject_IsAssignableFrom(UnderlyingType))
{
return true;
}
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustNonAttributedSerializableTypeNoPublicConstructor,
DataContract.GetClrTypeFullName(UnderlyingType)),
securityException));
}
return true;
}
if (MethodRequiresMemberAccess(this.OnDeserializing))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractOnDeserializingNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.OnDeserializing.Name),
securityException));
}
return true;
}
if (MethodRequiresMemberAccess(this.OnDeserialized))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractOnDeserializedNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.OnDeserialized.Name),
securityException));
}
return true;
}
if (this.Members != null)
{
for (int i = 0; i < this.Members.Count; i++)
{
if (this.Members[i].RequiresMemberAccessForSet())
{
if (securityException != null)
{
if (this.Members[i].MemberInfo is FieldInfo)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractFieldSetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.Members[i].MemberInfo.Name),
securityException));
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractPropertySetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.Members[i].MemberInfo.Name),
securityException));
}
}
return true;
}
}
}
return false;
}
/// <SecurityNote>
/// Review - calculates whether this class requires MemberAccessPermission for serialization.
/// since this information is used to determine whether to give the generated code access
/// permissions to private members, any changes to the logic should be reviewed.
/// </SecurityNote>
internal bool RequiresMemberAccessForWrite(SecurityException securityException)
{
EnsureMethodsImported();
if (!IsTypeVisible(UnderlyingType))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractTypeNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType)),
securityException));
}
return true;
}
if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForWrite(securityException))
return true;
if (MethodRequiresMemberAccess(this.OnSerializing))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractOnSerializingNotPublic,
DataContract.GetClrTypeFullName(this.UnderlyingType),
this.OnSerializing.Name),
securityException));
}
return true;
}
if (MethodRequiresMemberAccess(this.OnSerialized))
{
if (securityException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractOnSerializedNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.OnSerialized.Name),
securityException));
}
return true;
}
if (this.Members != null)
{
for (int i = 0; i < this.Members.Count; i++)
{
if (this.Members[i].RequiresMemberAccessForGet())
{
if (securityException != null)
{
if (this.Members[i].MemberInfo is FieldInfo)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractFieldGetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.Members[i].MemberInfo.Name),
securityException));
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new SecurityException(string.Format(
SRSerialization.PartialTrustDataContractPropertyGetNotPublic,
DataContract.GetClrTypeFullName(UnderlyingType),
this.Members[i].MemberInfo.Name),
securityException));
}
}
return true;
}
}
}
return false;
}
[SecurityCritical]
/// <SecurityNote>
/// Critical - holds all state used for (de)serializing classes.
/// since the data is cached statically, we lock down access to it.
/// </SecurityNote>
private class ClassDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
private ClassDataContract _baseContract;
private List<DataMember> _members;
private MethodInfo _onSerializing, _onSerialized;
private MethodInfo _onDeserializing, _onDeserialized;
#if !NET_NATIVE
private DataContractDictionary _knownDataContracts;
private bool _isKnownTypeAttributeChecked;
#endif
private bool _isMethodChecked;
/// <SecurityNote>
/// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and hasDataContract
/// </SecurityNote>
private bool _isNonAttributedType;
/// <SecurityNote>
/// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and isNonAttributedType
/// </SecurityNote>
private bool _hasDataContract;
#if NET_NATIVE
private bool _hasExtensionData;
#endif
private bool _isScriptObject;
private XmlDictionaryString[] _childElementNamespaces;
private XmlFormatClassReaderDelegate _xmlFormatReaderDelegate;
private XmlFormatClassWriterDelegate _xmlFormatWriterDelegate;
public XmlDictionaryString[] ContractNamespaces;
public XmlDictionaryString[] MemberNames;
public XmlDictionaryString[] MemberNamespaces;
internal ClassDataContractCriticalHelper() : base()
{
}
internal ClassDataContractCriticalHelper(Type type) : base(type)
{
XmlQualifiedName stableName = GetStableNameAndSetHasDataContract(type);
if (type == Globals.TypeOfDBNull)
{
this.StableName = stableName;
_members = new List<DataMember>();
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<XmlDictionaryString>();
EnsureMethodsImported();
return;
}
Type baseType = type.GetTypeInfo().BaseType;
SetIsNonAttributedType(type);
SetKeyValuePairAdapterFlags(type);
this.IsValueType = type.GetTypeInfo().IsValueType;
if (baseType != null && baseType != Globals.TypeOfObject && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri)
{
DataContract baseContract = DataContract.GetDataContract(baseType);
if (baseContract is CollectionDataContract)
this.BaseContract = ((CollectionDataContract)baseContract).SharedTypeContract as ClassDataContract;
else
this.BaseContract = baseContract as ClassDataContract;
if (this.BaseContract != null && this.BaseContract.IsNonAttributedType && !_isNonAttributedType)
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError
(new InvalidDataContractException(string.Format(SRSerialization.AttributedTypesCannotInheritFromNonAttributedSerializableTypes,
DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(baseType))));
}
}
else
this.BaseContract = null;
{
this.StableName = stableName;
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(2 + Members.Count);
Name = dictionary.Add(StableName.Name);
Namespace = dictionary.Add(StableName.Namespace);
int baseMemberCount = 0;
int baseContractCount = 0;
if (BaseContract == null)
{
MemberNames = new XmlDictionaryString[Members.Count];
MemberNamespaces = new XmlDictionaryString[Members.Count];
ContractNamespaces = new XmlDictionaryString[1];
}
else
{
baseMemberCount = BaseContract.MemberNames.Length;
MemberNames = new XmlDictionaryString[Members.Count + baseMemberCount];
Array.Copy(BaseContract.MemberNames, 0, MemberNames, 0, baseMemberCount);
MemberNamespaces = new XmlDictionaryString[Members.Count + baseMemberCount];
Array.Copy(BaseContract.MemberNamespaces, 0, MemberNamespaces, 0, baseMemberCount);
baseContractCount = BaseContract.ContractNamespaces.Length;
ContractNamespaces = new XmlDictionaryString[1 + baseContractCount];
Array.Copy(BaseContract.ContractNamespaces, 0, ContractNamespaces, 0, baseContractCount);
}
ContractNamespaces[baseContractCount] = Namespace;
for (int i = 0; i < Members.Count; i++)
{
MemberNames[i + baseMemberCount] = dictionary.Add(Members[i].Name);
MemberNamespaces[i + baseMemberCount] = Namespace;
}
}
EnsureMethodsImported();
_isScriptObject = this.IsNonAttributedType &&
Globals.TypeOfScriptObject_IsAssignableFrom(this.UnderlyingType);
}
internal ClassDataContractCriticalHelper(Type type, XmlDictionaryString ns, string[] memberNames) : base(type)
{
this.StableName = new XmlQualifiedName(GetStableNameAndSetHasDataContract(type).Name, ns.Value);
ImportDataMembers();
XmlDictionary dictionary = new XmlDictionary(1 + Members.Count);
Name = dictionary.Add(StableName.Name);
Namespace = ns;
ContractNamespaces = new XmlDictionaryString[] { Namespace };
MemberNames = new XmlDictionaryString[Members.Count];
MemberNamespaces = new XmlDictionaryString[Members.Count];
for (int i = 0; i < Members.Count; i++)
{
Members[i].Name = memberNames[i];
MemberNames[i] = dictionary.Add(Members[i].Name);
MemberNamespaces[i] = Namespace;
}
EnsureMethodsImported();
}
private void EnsureIsReferenceImported(Type type)
{
DataContractAttribute dataContractAttribute;
bool isReference = false;
bool hasDataContractAttribute = TryGetDCAttribute(type, out dataContractAttribute);
if (BaseContract != null)
{
if (hasDataContractAttribute && dataContractAttribute.IsReferenceSetExplicitly)
{
bool baseIsReference = this.BaseContract.IsReference;
if ((baseIsReference && !dataContractAttribute.IsReference) ||
(!baseIsReference && dataContractAttribute.IsReference))
{
DataContract.ThrowInvalidDataContractException(
string.Format(SRSerialization.InconsistentIsReference,
DataContract.GetClrTypeFullName(type),
dataContractAttribute.IsReference,
DataContract.GetClrTypeFullName(this.BaseContract.UnderlyingType),
this.BaseContract.IsReference),
type);
}
else
{
isReference = dataContractAttribute.IsReference;
}
}
else
{
isReference = this.BaseContract.IsReference;
}
}
else if (hasDataContractAttribute)
{
if (dataContractAttribute.IsReference)
isReference = dataContractAttribute.IsReference;
}
if (isReference && type.GetTypeInfo().IsValueType)
{
DataContract.ThrowInvalidDataContractException(
string.Format(SRSerialization.ValueTypeCannotHaveIsReference,
DataContract.GetClrTypeFullName(type),
true,
false),
type);
return;
}
this.IsReference = isReference;
}
private void ImportDataMembers()
{
Type type = this.UnderlyingType;
EnsureIsReferenceImported(type);
List<DataMember> tempMembers = new List<DataMember>();
Dictionary<string, DataMember> memberNamesTable = new Dictionary<string, DataMember>();
MemberInfo[] memberInfos;
bool isPodSerializable = !_isNonAttributedType || IsKnownSerializableType(type);
if (!isPodSerializable)
{
memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
}
else
{
memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
for (int i = 0; i < memberInfos.Length; i++)
{
MemberInfo member = memberInfos[i];
if (HasDataContract)
{
object[] memberAttributes = member.GetCustomAttributes(typeof(DataMemberAttribute), false).ToArray();
if (memberAttributes != null && memberAttributes.Length > 0)
{
if (memberAttributes.Length > 1)
ThrowInvalidDataContractException(string.Format(SRSerialization.TooManyDataMembers, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name));
DataMember memberContract = new DataMember(member);
if (member is PropertyInfo)
{
PropertyInfo property = (PropertyInfo)member;
MethodInfo getMethod = property.GetMethod;
if (getMethod != null && IsMethodOverriding(getMethod))
continue;
MethodInfo setMethod = property.SetMethod;
if (setMethod != null && IsMethodOverriding(setMethod))
continue;
if (getMethod == null)
ThrowInvalidDataContractException(string.Format(SRSerialization.NoGetMethodForProperty, property.DeclaringType, property.Name));
if (setMethod == null)
{
if (!SetIfGetOnlyCollection(memberContract))
{
ThrowInvalidDataContractException(string.Format(SRSerialization.NoSetMethodForProperty, property.DeclaringType, property.Name));
}
}
if (getMethod.GetParameters().Length > 0)
ThrowInvalidDataContractException(string.Format(SRSerialization.IndexedPropertyCannotBeSerialized, property.DeclaringType, property.Name));
}
else if (!(member is FieldInfo))
ThrowInvalidDataContractException(string.Format(SRSerialization.InvalidMember, DataContract.GetClrTypeFullName(type), member.Name));
DataMemberAttribute memberAttribute = (DataMemberAttribute)memberAttributes[0];
if (memberAttribute.IsNameSetExplicitly)
{
if (memberAttribute.Name == null || memberAttribute.Name.Length == 0)
ThrowInvalidDataContractException(string.Format(SRSerialization.InvalidDataMemberName, member.Name, DataContract.GetClrTypeFullName(type)));
memberContract.Name = memberAttribute.Name;
}
else
memberContract.Name = member.Name;
memberContract.Name = DataContract.EncodeLocalName(memberContract.Name);
memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
memberContract.IsRequired = memberAttribute.IsRequired;
if (memberAttribute.IsRequired && this.IsReference)
{
ThrowInvalidDataContractException(
string.Format(SRSerialization.IsRequiredDataMemberOnIsReferenceDataContractType,
DataContract.GetClrTypeFullName(member.DeclaringType),
member.Name, true), type);
}
memberContract.EmitDefaultValue = memberAttribute.EmitDefaultValue;
memberContract.Order = memberAttribute.Order;
CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
}
}
else if (!isPodSerializable)
{
FieldInfo field = member as FieldInfo;
PropertyInfo property = member as PropertyInfo;
if ((field == null && property == null) || (field != null && field.IsInitOnly))
continue;
object[] memberAttributes = member.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false).ToArray();
if (memberAttributes != null && memberAttributes.Length > 0)
{
if (memberAttributes.Length > 1)
ThrowInvalidDataContractException(string.Format(SRSerialization.TooManyIgnoreDataMemberAttributes, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name));
else
continue;
}
DataMember memberContract = new DataMember(member);
if (property != null)
{
MethodInfo getMethod = property.GetMethod;
if (getMethod == null || IsMethodOverriding(getMethod) || getMethod.GetParameters().Length > 0)
continue;
MethodInfo setMethod = property.SetMethod;
if (setMethod == null)
{
if (!SetIfGetOnlyCollection(memberContract))
continue;
}
else
{
if (!setMethod.IsPublic || IsMethodOverriding(setMethod))
continue;
}
}
memberContract.Name = DataContract.EncodeLocalName(member.Name);
memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
}
else
{
// [Serializible] and [NonSerialized] are deprecated on FxCore
// Try to mimic the behavior by allowing certain known types to go through
// POD types are fine also
FieldInfo field = member as FieldInfo;
if (CanSerializeMember(field))
{
DataMember memberContract = new DataMember(member);
memberContract.Name = DataContract.EncodeLocalName(member.Name);
object[] optionalFields = null;
if (optionalFields == null || optionalFields.Length == 0)
{
if (this.IsReference)
{
ThrowInvalidDataContractException(
string.Format(SRSerialization.NonOptionalFieldMemberOnIsReferenceSerializableType,
DataContract.GetClrTypeFullName(member.DeclaringType),
member.Name, true), type);
}
memberContract.IsRequired = true;
}
memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType);
CheckAndAddMember(tempMembers, memberContract, memberNamesTable);
}
}
}
if (tempMembers.Count > 1)
tempMembers.Sort(DataMemberComparer.Singleton);
SetIfMembersHaveConflict(tempMembers);
Interlocked.MemoryBarrier();
_members = tempMembers;
}
private static bool CanSerializeMember(FieldInfo field)
{
return field != null &&
field.FieldType != Globals.TypeOfObject; // Don't really know how to serialize plain System.Object instance;
}
private bool SetIfGetOnlyCollection(DataMember memberContract)
{
//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.GetTypeInfo().IsValueType)
{
memberContract.IsGetOnlyCollection = true;
return true;
}
return false;
}
private void SetIfMembersHaveConflict(List<DataMember> members)
{
if (BaseContract == null)
return;
int baseTypeIndex = 0;
List<Member> membersInHierarchy = new List<Member>();
foreach (DataMember member in members)
{
membersInHierarchy.Add(new Member(member, this.StableName.Namespace, baseTypeIndex));
}
ClassDataContract currContract = BaseContract;
while (currContract != null)
{
baseTypeIndex++;
foreach (DataMember member in currContract.Members)
{
membersInHierarchy.Add(new Member(member, currContract.StableName.Namespace, baseTypeIndex));
}
currContract = currContract.BaseContract;
}
IComparer<Member> comparer = DataMemberConflictComparer.Singleton;
membersInHierarchy.Sort(comparer);
for (int i = 0; i < membersInHierarchy.Count - 1; i++)
{
int startIndex = i;
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)
{
membersInHierarchy[endIndex].member.ConflictingMember = membersInHierarchy[endIndex + 1].member;
if (!hasConflictingType)
{
if (membersInHierarchy[endIndex + 1].member.HasConflictingNameAndType)
{
hasConflictingType = true;
}
else
{
hasConflictingType = (membersInHierarchy[endIndex].member.MemberType != membersInHierarchy[endIndex + 1].member.MemberType);
}
}
endIndex++;
}
if (hasConflictingType)
{
for (int j = startIndex; j <= endIndex; j++)
{
membersInHierarchy[j].member.HasConflictingNameAndType = true;
}
}
i = endIndex + 1;
}
}
/// <SecurityNote>
/// Critical - sets the critical hasDataContract field
/// Safe - uses a trusted critical API (DataContract.GetStableName) to calculate the value
/// does not accept the value from the caller
/// </SecurityNote>
//CSD16748
//[SecuritySafeCritical]
private XmlQualifiedName GetStableNameAndSetHasDataContract(Type type)
{
return DataContract.GetStableName(type, out _hasDataContract);
}
/// <SecurityNote>
/// 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
/// is dependent on the correct calculation of hasDataContract
/// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value
/// </SecurityNote>
private void SetIsNonAttributedType(Type type)
{
_isNonAttributedType = !_hasDataContract && IsNonAttributedTypeValidForSerialization(type);
}
private static bool IsMethodOverriding(MethodInfo method)
{
return method.IsVirtual && ((method.Attributes & MethodAttributes.NewSlot) == 0);
}
internal void EnsureMethodsImported()
{
if (!_isMethodChecked && UnderlyingType != null)
{
lock (this)
{
if (!_isMethodChecked)
{
Type type = this.UnderlyingType;
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
for (int i = 0; i < methods.Length; i++)
{
MethodInfo method = methods[i];
Type prevAttributeType = null;
ParameterInfo[] parameters = method.GetParameters();
//THese attributes are cut from mscorlib.
if (IsValidCallback(method, parameters, Globals.TypeOfOnSerializingAttribute, _onSerializing, ref prevAttributeType))
_onSerializing = method;
if (IsValidCallback(method, parameters, Globals.TypeOfOnSerializedAttribute, _onSerialized, ref prevAttributeType))
_onSerialized = method;
if (IsValidCallback(method, parameters, Globals.TypeOfOnDeserializingAttribute, _onDeserializing, ref prevAttributeType))
_onDeserializing = method;
if (IsValidCallback(method, parameters, Globals.TypeOfOnDeserializedAttribute, _onDeserialized, ref prevAttributeType))
_onDeserialized = method;
}
Interlocked.MemoryBarrier();
_isMethodChecked = true;
}
}
}
}
private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType)
{
if (method.IsDefined(attributeType, false))
{
if (currentCallback != null)
DataContract.ThrowInvalidDataContractException(string.Format(SRSerialization.DuplicateCallback, method, currentCallback, DataContract.GetClrTypeFullName(method.DeclaringType), attributeType), method.DeclaringType);
else if (prevAttributeType != null)
DataContract.ThrowInvalidDataContractException(string.Format(SRSerialization.DuplicateAttribute, prevAttributeType, attributeType, DataContract.GetClrTypeFullName(method.DeclaringType), method), method.DeclaringType);
else if (method.IsVirtual)
DataContract.ThrowInvalidDataContractException(string.Format(SRSerialization.CallbacksCannotBeVirtualMethods, method, DataContract.GetClrTypeFullName(method.DeclaringType), attributeType), method.DeclaringType);
else
{
if (method.ReturnType != Globals.TypeOfVoid)
DataContract.ThrowInvalidDataContractException(string.Format(SRSerialization.CallbackMustReturnVoid, DataContract.GetClrTypeFullName(method.DeclaringType), method), method.DeclaringType);
if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != Globals.TypeOfStreamingContext)
DataContract.ThrowInvalidDataContractException(string.Format(SRSerialization.CallbackParameterInvalid, DataContract.GetClrTypeFullName(method.DeclaringType), method, Globals.TypeOfStreamingContext), method.DeclaringType);
prevAttributeType = attributeType;
}
return true;
}
return false;
}
internal ClassDataContract BaseContract
{
get { return _baseContract; }
set
{
_baseContract = value;
if (_baseContract != null && IsValueType)
ThrowInvalidDataContractException(string.Format(SRSerialization.ValueTypeCannotHaveBaseType, StableName.Name, StableName.Namespace, _baseContract.StableName.Name, _baseContract.StableName.Namespace));
}
}
internal List<DataMember> Members
{
get { return _members; }
set { _members = value; }
}
internal MethodInfo OnSerializing
{
get
{
EnsureMethodsImported();
return _onSerializing;
}
}
internal MethodInfo OnSerialized
{
get
{
EnsureMethodsImported();
return _onSerialized;
}
}
internal MethodInfo OnDeserializing
{
get
{
EnsureMethodsImported();
return _onDeserializing;
}
}
internal MethodInfo OnDeserialized
{
get
{
EnsureMethodsImported();
return _onDeserialized;
}
}
#if !NET_NATIVE
internal override DataContractDictionary KnownDataContracts
{
[SecurityCritical]
get
{
if (!_isKnownTypeAttributeChecked && UnderlyingType != null)
{
lock (this)
{
if (!_isKnownTypeAttributeChecked)
{
_knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
Interlocked.MemoryBarrier();
_isKnownTypeAttributeChecked = true;
}
}
}
return _knownDataContracts;
}
[SecurityCritical]
set
{ _knownDataContracts = value; }
}
#endif
internal bool HasDataContract
{
get { return _hasDataContract; }
#if NET_NATIVE
set { _hasDataContract = value; }
#endif
}
#if NET_NATIVE
internal bool HasExtensionData
{
get { return _hasExtensionData; }
set { _hasExtensionData = value; }
}
#endif
internal bool IsNonAttributedType
{
get { return _isNonAttributedType; }
}
private void SetKeyValuePairAdapterFlags(Type type)
{
if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfKeyValuePairAdapter)
{
_isKeyValuePairAdapter = true;
_keyValuePairGenericArguments = type.GetGenericArguments();
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) });
_getKeyValuePairMethodInfo = type.GetMethod("GetKeyValuePair", Globals.ScanAllMembers);
}
}
private bool _isKeyValuePairAdapter;
private Type[] _keyValuePairGenericArguments;
private ConstructorInfo _keyValuePairCtorInfo;
private MethodInfo _getKeyValuePairMethodInfo;
internal bool IsKeyValuePairAdapter
{
get { return _isKeyValuePairAdapter; }
}
internal bool IsScriptObject
{
get { return _isScriptObject; }
}
internal Type[] KeyValuePairGenericArguments
{
get { return _keyValuePairGenericArguments; }
}
internal ConstructorInfo KeyValuePairAdapterConstructorInfo
{
get { return _keyValuePairCtorInfo; }
}
internal MethodInfo GetKeyValuePairMethodInfo
{
get { return _getKeyValuePairMethodInfo; }
}
internal ConstructorInfo GetNonAttributedTypeConstructor()
{
if (!this.IsNonAttributedType)
return null;
Type type = UnderlyingType;
if (type.GetTypeInfo().IsValueType)
return null;
ConstructorInfo ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>());
if (ctor == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(string.Format(SRSerialization.NonAttributedSerializableTypesMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type))));
return ctor;
}
internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate
{
get { return _xmlFormatWriterDelegate; }
set { _xmlFormatWriterDelegate = value; }
}
internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate
{
get { return _xmlFormatReaderDelegate; }
set { _xmlFormatReaderDelegate = value; }
}
public XmlDictionaryString[] ChildElementNamespaces
{
get { return _childElementNamespaces; }
set { _childElementNamespaces = value; }
}
internal struct Member
{
internal Member(DataMember member, string ns, int baseTypeIndex)
{
this.member = member;
this.ns = ns;
this.baseTypeIndex = baseTypeIndex;
}
internal DataMember member;
internal string ns;
internal int baseTypeIndex;
}
internal class DataMemberConflictComparer : IComparer<Member>
{
[SecuritySafeCritical]
public int Compare(Member x, Member y)
{
int nsCompare = String.CompareOrdinal(x.ns, y.ns);
if (nsCompare != 0)
return nsCompare;
int nameCompare = String.CompareOrdinal(x.member.Name, y.member.Name);
if (nameCompare != 0)
return nameCompare;
return x.baseTypeIndex - y.baseTypeIndex;
}
internal static DataMemberConflictComparer Singleton = new DataMemberConflictComparer();
}
#if NET_NATIVE
internal ClassDataContractCriticalHelper Clone()
{
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;
}
#endif
}
internal class DataMemberComparer : IComparer<DataMember>
{
public int Compare(DataMember x, DataMember y)
{
int orderCompare = x.Order - y.Order;
if (orderCompare != 0)
return orderCompare;
return String.CompareOrdinal(x.Name, y.Name);
}
internal static DataMemberComparer Singleton = new DataMemberComparer();
}
#if !NET_NATIVE
/// <summary>
/// Get object type for Xml/JsonFormmatReaderGenerator
/// </summary>
internal Type ObjectType
{
get
{
Type type = UnderlyingType;
if (type.GetTypeInfo().IsValueType && !IsNonAttributedType)
{
type = Globals.TypeOfValueType;
}
return type;
}
}
#endif
#if NET_NATIVE
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;
}
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;
}
}
#endif
}
}
|