1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.Runtime.Serialization
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Diagnostics.CodeAnalysis;
11 using System.Globalization;
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
15 using System.Runtime.Serialization.Configuration;
17 using System.Runtime.Serialization.Diagnostics.Application;
18 using System.Security;
21 using System.Xml.Schema;
22 using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
23 using System.Text.RegularExpressions;
26 public abstract class DataContract
28 internal abstract class DataContract
31 [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the type name. Statically cached and used from IL generated code.")]
33 XmlDictionaryString name;
35 [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the type name. Statically cached and used from IL generated code.")]
37 XmlDictionaryString ns;
39 [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization."
40 + " Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
42 DataContractCriticalHelper helper;
44 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
45 Safe = "Doesn't leak anything.")]
46 [SecuritySafeCritical]
47 protected DataContract(DataContractCriticalHelper helper)
50 this.name = helper.Name;
51 this.ns = helper.Namespace;
54 internal static DataContract GetDataContract(Type type)
56 return GetDataContract(type.TypeHandle, type, SerializationMode.SharedContract);
59 internal static DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)
61 int id = GetId(typeHandle);
62 return GetDataContract(id, typeHandle, mode);
65 internal static DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle, SerializationMode mode)
67 DataContract dataContract = GetDataContractSkipValidation(id, typeHandle, null);
68 dataContract = dataContract.GetValidContract(mode);
73 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract .",
74 Safe = "Read only access.")]
75 [SecuritySafeCritical]
76 internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHandle typeHandle, Type type)
78 return DataContractCriticalHelper.GetDataContractSkipValidation(id, typeHandle, type);
81 internal static DataContract GetGetOnlyCollectionDataContract(int id, RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)
83 DataContract dataContract = GetGetOnlyCollectionDataContractSkipValidation(id, typeHandle, type);
84 dataContract = dataContract.GetValidContract(mode);
85 if (dataContract is ClassDataContract)
87 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.ClassDataContractReturnedForGetOnlyCollection, DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
92 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract .",
93 Safe = "Read only access.")]
94 [SecuritySafeCritical]
95 internal static DataContract GetGetOnlyCollectionDataContractSkipValidation(int id, RuntimeTypeHandle typeHandle, Type type)
97 return DataContractCriticalHelper.GetGetOnlyCollectionDataContractSkipValidation(id, typeHandle, type);
100 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract .",
101 Safe = "Read only access; doesn't modify any static information.")]
102 [SecuritySafeCritical]
103 internal static DataContract GetDataContractForInitialization(int id)
105 return DataContractCriticalHelper.GetDataContractForInitialization(id);
108 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up id for DataContract .",
109 Safe = "Read only access; doesn't modify any static information.")]
110 [SecuritySafeCritical]
111 internal static int GetIdForInitialization(ClassDataContract classContract)
113 return DataContractCriticalHelper.GetIdForInitialization(classContract);
116 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up id assigned to a particular type.",
117 Safe = "Read only access.")]
118 [SecuritySafeCritical]
119 internal static int GetId(RuntimeTypeHandle typeHandle)
121 return DataContractCriticalHelper.GetId(typeHandle);
124 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract.",
125 Safe = "Read only access.")]
126 [SecuritySafeCritical]
127 public static DataContract GetBuiltInDataContract(Type type)
129 return DataContractCriticalHelper.GetBuiltInDataContract(type);
132 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract.",
133 Safe = "Read only access.")]
134 [SecuritySafeCritical]
135 public static DataContract GetBuiltInDataContract(string name, string ns)
137 return DataContractCriticalHelper.GetBuiltInDataContract(name, ns);
140 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up DataContract.",
141 Safe = "Read only access.")]
142 [SecuritySafeCritical]
143 public static DataContract GetBuiltInDataContract(string typeName)
145 return DataContractCriticalHelper.GetBuiltInDataContract(typeName);
148 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up string reference to use for a namespace string.",
149 Safe = "Read only access.")]
150 [SecuritySafeCritical]
151 internal static string GetNamespace(string key)
153 return DataContractCriticalHelper.GetNamespace(key);
156 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up XmlDictionaryString for a string.",
157 Safe = "Read only access.")]
158 [SecuritySafeCritical]
159 internal static XmlDictionaryString GetClrTypeString(string key)
161 return DataContractCriticalHelper.GetClrTypeString(key);
164 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to remove invalid DataContract if it has been added to cache.",
165 Safe = "Doesn't leak any information.")]
166 [SecuritySafeCritical]
167 internal static void ThrowInvalidDataContractException(string message, Type type)
169 DataContractCriticalHelper.ThrowInvalidDataContractException(message, type);
173 internal DataContractCriticalHelper Helper
175 protected DataContractCriticalHelper Helper
178 [Fx.Tag.SecurityNote(Critical = "holds instance of CriticalHelper which keeps state that is cached statically for serialization."
179 + " Static fields are marked SecurityCritical or readonly to prevent"
180 + " data from being modified or leaked to other components in appdomain.")]
182 get { return helper; }
185 internal Type UnderlyingType
187 [Fx.Tag.SecurityNote(Critical = "Fetches the critical UnderlyingType field.",
188 Safe = "Get-only properties only needs to be protected for write.")]
189 [SecuritySafeCritical]
190 get { return helper.UnderlyingType; }
193 internal Type OriginalUnderlyingType
195 [Fx.Tag.SecurityNote(Critical = "Fetches the critical OriginalUnderlyingType property.",
196 Safe = "OrginalUnderlyingType only needs to be protected for write.")]
197 [SecuritySafeCritical]
198 get { return helper.OriginalUnderlyingType; }
202 internal virtual bool IsBuiltInDataContract
204 [Fx.Tag.SecurityNote(Critical = "Fetches the critical isBuiltInDataContract property.",
205 Safe = "isBuiltInDataContract only needs to be protected for write.")]
206 [SecuritySafeCritical]
207 get { return helper.IsBuiltInDataContract; }
210 internal Type TypeForInitialization
212 [Fx.Tag.SecurityNote(Critical = "Fetches the critical typeForInitialization property.",
213 Safe = "typeForInitialization only needs to be protected for write.")]
214 [SecuritySafeCritical]
215 get { return helper.TypeForInitialization; }
218 public virtual void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
220 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
223 public virtual object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
225 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(this.GetType()), DataContract.GetClrTypeFullName(UnderlyingType))));
228 internal bool IsValueType
230 [Fx.Tag.SecurityNote(Critical = "Fetches the critical IsValueType property.",
231 Safe = "IsValueType only needs to be protected for write.")]
232 [SecuritySafeCritical]
233 get { return helper.IsValueType; }
234 [Fx.Tag.SecurityNote(Critical = "Sets the critical IsValueType property.")]
236 set { helper.IsValueType = value; }
239 internal bool IsReference
241 [Fx.Tag.SecurityNote(Critical = "Fetches the critical IsReference property.",
242 Safe = "IsReference only needs to be protected for write.")]
243 [SecuritySafeCritical]
244 get { return helper.IsReference; }
246 [Fx.Tag.SecurityNote(Critical = "Sets the critical IsReference property.")]
248 set { helper.IsReference = value; }
251 internal XmlQualifiedName StableName
253 [Fx.Tag.SecurityNote(Critical = "Fetches the critical StableName property.",
254 Safe = "StableName only needs to be protected for write.")]
255 [SecuritySafeCritical]
256 get { return helper.StableName; }
258 [Fx.Tag.SecurityNote(Critical = "Sets the critical StableName property.")]
260 set { helper.StableName = value; }
263 internal GenericInfo GenericInfo
265 [Fx.Tag.SecurityNote(Critical = "Fetches the critical GenericInfo property.",
266 Safe = "GenericInfo only needs to be protected for write.")]
267 [SecuritySafeCritical]
268 get { return helper.GenericInfo; }
269 [Fx.Tag.SecurityNote(Critical = "Sets the critical GenericInfo property.",
270 Safe = "Protected for write if contract has underlyingType .")]
272 set { helper.GenericInfo = value; }
275 internal virtual DataContractDictionary KnownDataContracts
277 [Fx.Tag.SecurityNote(Critical = "Fetches the critical KnownDataContracts property.",
278 Safe = "KnownDataContracts only needs to be protected for write.")]
279 [SecuritySafeCritical]
280 get { return helper.KnownDataContracts; }
282 [Fx.Tag.SecurityNote(Critical = "Sets the critical KnownDataContracts property.")]
284 set { helper.KnownDataContracts = value; }
287 internal virtual bool IsISerializable
289 [Fx.Tag.SecurityNote(Critical = "Fetches the critical IsISerializable property.",
290 Safe = "IsISerializable only needs to be protected for write.")]
291 [SecuritySafeCritical]
292 get { return helper.IsISerializable; }
294 [Fx.Tag.SecurityNote(Critical = "Sets the critical IsISerializable property.")]
296 set { helper.IsISerializable = value; }
299 internal XmlDictionaryString Name
301 [Fx.Tag.SecurityNote(Critical = "Fetches the critical Name property.",
302 Safe = "Name only needs to be protected for write.")]
303 [SecuritySafeCritical]
304 get { return this.name; }
307 public virtual XmlDictionaryString Namespace
309 [Fx.Tag.SecurityNote(Critical = "Fetches the critical Namespace property.",
310 Safe = "Namespace only needs to be protected for write.")]
311 [SecuritySafeCritical]
312 get { return this.ns; }
315 internal virtual bool HasRoot
321 internal virtual XmlDictionaryString TopLevelElementName
323 [Fx.Tag.SecurityNote(Critical = "Fetches the critical Name property.",
324 Safe = "Name only needs to be protected for write.")]
325 [SecuritySafeCritical]
326 get { return helper.TopLevelElementName; }
328 [Fx.Tag.SecurityNote(Critical = "Sets the critical Name property.")]
330 set { helper.TopLevelElementName = value; }
333 internal virtual XmlDictionaryString TopLevelElementNamespace
335 [Fx.Tag.SecurityNote(Critical = "Fetches the critical Namespace property.",
336 Safe = "Namespace only needs to be protected for write.")]
337 [SecuritySafeCritical]
338 get { return helper.TopLevelElementNamespace; }
340 [Fx.Tag.SecurityNote(Critical = "Sets the critical Namespace property.")]
342 set { helper.TopLevelElementNamespace = value; }
345 internal virtual bool CanContainReferences
350 internal virtual bool IsPrimitive
352 get { return false; }
355 internal virtual void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryString name, XmlDictionaryString ns)
357 if (object.ReferenceEquals(ns, DictionaryGlobals.SerializationNamespace) && !IsPrimitive)
358 writer.WriteStartElement(Globals.SerPrefix, name, ns);
360 writer.WriteStartElement(name, ns);
363 internal virtual DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
368 internal virtual DataContract GetValidContract(SerializationMode mode)
373 internal virtual DataContract GetValidContract()
378 internal virtual bool IsValidContract(SerializationMode mode)
383 internal MethodInfo ParseMethod
385 [Fx.Tag.SecurityNote(Critical = "Fetches the critical ParseMethod field.",
386 Safe = "Get-only properties only needs to be protected for write.")]
387 [SecuritySafeCritical]
388 get { return helper.ParseMethod; }
391 [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing types."
392 + " Since the data is cached statically, we lock down access to it.")]
393 #if !NO_SECURITY_ATTRIBUTES
394 [SecurityCritical(SecurityCriticalScope.Everything)]
397 public class DataContractCriticalHelper
399 protected class DataContractCriticalHelper
402 static Dictionary<TypeHandleRef, IntRef> typeToIDCache;
403 static DataContract[] dataContractCache;
404 static int dataContractID;
405 static Dictionary<Type, DataContract> typeToBuiltInContract;
406 static Dictionary<XmlQualifiedName, DataContract> nameToBuiltInContract;
407 static Dictionary<string, DataContract> typeNameToBuiltInContract;
408 static Dictionary<string, string> namespaces;
409 static Dictionary<string, XmlDictionaryString> clrTypeStrings;
410 static XmlDictionary clrTypeStringsDictionary;
411 static TypeHandleRef typeHandleRef = new TypeHandleRef();
413 static object cacheLock = new object();
414 static object createDataContractLock = new object();
415 static object initBuiltInContractsLock = new object();
416 static object namespacesLock = new object();
417 static object clrTypeStringsLock = new object();
419 readonly Type underlyingType;
420 Type originalUnderlyingType;
423 XmlQualifiedName stableName;
424 GenericInfo genericInfo;
425 XmlDictionaryString name;
426 XmlDictionaryString ns;
428 [Fx.Tag.SecurityNote(Critical = "In deserialization, we initialize an object instance passing this Type to GetUninitializedObject method.")]
429 Type typeForInitialization;
431 MethodInfo parseMethod;
434 static DataContractCriticalHelper()
436 typeToIDCache = new Dictionary<TypeHandleRef, IntRef>(new TypeHandleRefEqualityComparer());
437 dataContractCache = new DataContract[32];
441 internal static DataContract GetDataContractSkipValidation(int id, RuntimeTypeHandle typeHandle, Type type)
443 DataContract dataContract = dataContractCache[id];
444 if (dataContract == null)
446 dataContract = CreateDataContract(id, typeHandle, type);
450 return dataContract.GetValidContract();
455 internal static DataContract GetGetOnlyCollectionDataContractSkipValidation(int id, RuntimeTypeHandle typeHandle, Type type)
457 DataContract dataContract = dataContractCache[id];
458 if (dataContract == null)
460 dataContract = CreateGetOnlyCollectionDataContract(id, typeHandle, type);
461 dataContractCache[id] = dataContract;
466 internal static DataContract GetDataContractForInitialization(int id)
468 DataContract dataContract = dataContractCache[id];
469 if (dataContract == null)
471 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.DataContractCacheOverflow)));
476 internal static int GetIdForInitialization(ClassDataContract classContract)
478 int id = DataContract.GetId(classContract.TypeForInitialization.TypeHandle);
479 if (id < dataContractCache.Length && ContractMatches(classContract, dataContractCache[id]))
483 for (int i = 0; i < DataContractCriticalHelper.dataContractID; i++)
485 if (ContractMatches(classContract, dataContractCache[i]))
490 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.DataContractCacheOverflow)));
493 static bool ContractMatches(DataContract contract, DataContract cachedContract)
495 return (cachedContract != null && cachedContract.UnderlyingType == contract.UnderlyingType);
498 internal static int GetId(RuntimeTypeHandle typeHandle)
503 typeHandle = GetDataContractAdapterTypeHandle(typeHandle);
504 typeHandleRef.Value = typeHandle;
505 if (!typeToIDCache.TryGetValue(typeHandleRef, out id))
510 typeToIDCache.Add(new TypeHandleRef(typeHandle), id);
518 throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
525 // Assumed that this method is called under a lock
526 static IntRef GetNextId()
528 int value = dataContractID++;
529 if (value >= dataContractCache.Length)
531 int newSize = (value < Int32.MaxValue / 2) ? value * 2 : Int32.MaxValue;
532 if (newSize <= value)
534 Fx.Assert("DataContract cache overflow");
535 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.DataContractCacheOverflow)));
537 Array.Resize<DataContract>(ref dataContractCache, newSize);
539 return new IntRef(value);
542 // check whether a corresponding update is required in ClassDataContract.IsNonAttributedTypeValidForSerialization
543 static DataContract CreateDataContract(int id, RuntimeTypeHandle typeHandle, Type type)
545 lock (createDataContractLock)
547 DataContract dataContract = dataContractCache[id];
548 if (dataContract == null)
551 type = Type.GetTypeFromHandle(typeHandle);
552 type = UnwrapNullableType(type);
553 type = GetDataContractAdapterType(type);
554 dataContract = GetBuiltInDataContract(type);
555 if (dataContract == null)
558 dataContract = new CollectionDataContract(type);
559 else if (type.IsEnum)
560 dataContract = new EnumDataContract(type);
561 else if (type.IsGenericParameter)
562 dataContract = new GenericParameterDataContract(type);
563 else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
564 dataContract = new XmlDataContract(type);
567 //if (type.ContainsGenericParameters)
568 // ThrowInvalidDataContractException(SR.GetString(SR.TypeMustNotBeOpenGeneric, type), type);
570 type = Globals.TypeOfReflectionPointer;
572 if (!CollectionDataContract.TryCreate(type, out dataContract))
574 if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false) || ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
576 dataContract = new ClassDataContract(type);
580 ThrowInvalidDataContractException(SR.GetString(SR.TypeNotSerializable, type), type);
586 dataContractCache[id] = dataContract;
591 static DataContract CreateGetOnlyCollectionDataContract(int id, RuntimeTypeHandle typeHandle, Type type)
593 DataContract dataContract = null;
594 lock (createDataContractLock)
596 dataContract = dataContractCache[id];
597 if (dataContract == null)
600 type = Type.GetTypeFromHandle(typeHandle);
601 type = UnwrapNullableType(type);
602 type = GetDataContractAdapterType(type);
603 if (!CollectionDataContract.TryCreateGetOnlyCollectionDataContract(type, out dataContract))
605 ThrowInvalidDataContractException(SR.GetString(SR.TypeNotSerializable, type), type);
612 // Any change to this method should be reflected in GetDataContractOriginalType
613 internal static Type GetDataContractAdapterType(Type type)
615 // Replace the DataTimeOffset ISerializable type passed in with the internal DateTimeOffsetAdapter DataContract type.
616 // DateTimeOffsetAdapter is used for serialization/deserialization purposes to bypass the ISerializable implementation
617 // on DateTimeOffset; which does not work in partial trust and to ensure correct schema import/export scenarios.
618 if (type == Globals.TypeOfDateTimeOffset)
620 return Globals.TypeOfDateTimeOffsetAdapter;
625 // Maps adapted types back to the original type
626 // Any change to this method should be reflected in GetDataContractAdapterType
627 internal static Type GetDataContractOriginalType(Type type)
629 if (type == Globals.TypeOfDateTimeOffsetAdapter)
631 return Globals.TypeOfDateTimeOffset;
636 static RuntimeTypeHandle GetDataContractAdapterTypeHandle(RuntimeTypeHandle typeHandle)
638 if (Globals.TypeOfDateTimeOffset.TypeHandle.Equals(typeHandle))
640 return Globals.TypeOfDateTimeOffsetAdapter.TypeHandle;
645 [SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "typeToBuiltInContract", Justification = "No need to support type equivalence here.")]
646 public static DataContract GetBuiltInDataContract(Type type)
648 if (type.IsInterface && !CollectionDataContract.IsCollectionInterface(type))
649 type = Globals.TypeOfObject;
651 lock (initBuiltInContractsLock)
653 if (typeToBuiltInContract == null)
654 typeToBuiltInContract = new Dictionary<Type, DataContract>();
656 DataContract dataContract = null;
657 if (!typeToBuiltInContract.TryGetValue(type, out dataContract))
659 TryCreateBuiltInDataContract(type, out dataContract);
660 typeToBuiltInContract.Add(type, dataContract);
666 public static DataContract GetBuiltInDataContract(string name, string ns)
668 lock (initBuiltInContractsLock)
670 if (nameToBuiltInContract == null)
671 nameToBuiltInContract = new Dictionary<XmlQualifiedName, DataContract>();
673 DataContract dataContract = null;
674 XmlQualifiedName qname = new XmlQualifiedName(name, ns);
675 if (!nameToBuiltInContract.TryGetValue(qname, out dataContract))
677 if (TryCreateBuiltInDataContract(name, ns, out dataContract))
679 nameToBuiltInContract.Add(qname, dataContract);
686 public static DataContract GetBuiltInDataContract(string typeName)
688 if (!typeName.StartsWith("System.", StringComparison.Ordinal))
691 lock (initBuiltInContractsLock)
693 if (typeNameToBuiltInContract == null)
694 typeNameToBuiltInContract = new Dictionary<string, DataContract>();
696 DataContract dataContract = null;
697 if (!typeNameToBuiltInContract.TryGetValue(typeName, out dataContract))
700 string name = typeName.Substring(7);
703 else if (name == "Boolean")
704 type = typeof(Boolean);
705 else if (name == "SByte")
706 type = typeof(SByte);
707 else if (name == "Byte")
709 else if (name == "Int16")
710 type = typeof(Int16);
711 else if (name == "UInt16")
712 type = typeof(UInt16);
713 else if (name == "Int32")
714 type = typeof(Int32);
715 else if (name == "UInt32")
716 type = typeof(UInt32);
717 else if (name == "Int64")
718 type = typeof(Int64);
719 else if (name == "UInt64")
720 type = typeof(UInt64);
721 else if (name == "Single")
722 type = typeof(Single);
723 else if (name == "Double")
724 type = typeof(Double);
725 else if (name == "Decimal")
726 type = typeof(Decimal);
727 else if (name == "DateTime")
728 type = typeof(DateTime);
729 else if (name == "String")
730 type = typeof(String);
731 else if (name == "Byte[]")
732 type = typeof(byte[]);
733 else if (name == "Object")
734 type = typeof(Object);
735 else if (name == "TimeSpan")
736 type = typeof(TimeSpan);
737 else if (name == "Guid")
739 else if (name == "Uri")
741 else if (name == "Xml.XmlQualifiedName")
742 type = typeof(XmlQualifiedName);
743 else if (name == "Enum")
745 else if (name == "ValueType")
746 type = typeof(ValueType);
747 else if (name == "Array")
748 type = typeof(Array);
749 else if (name == "Xml.XmlElement")
750 type = typeof(XmlElement);
751 else if (name == "Xml.XmlNode[]")
752 type = typeof(XmlNode[]);
755 TryCreateBuiltInDataContract(type, out dataContract);
757 typeNameToBuiltInContract.Add(typeName, dataContract);
763 static public bool TryCreateBuiltInDataContract(Type type, out DataContract dataContract)
765 if (type.IsEnum) // Type.GetTypeCode will report Enums as TypeCode.IntXX
771 switch (Type.GetTypeCode(type))
773 case TypeCode.Boolean:
774 dataContract = new BooleanDataContract();
777 dataContract = new UnsignedByteDataContract();
780 dataContract = new CharDataContract();
782 case TypeCode.DateTime:
783 dataContract = new DateTimeDataContract();
785 case TypeCode.Decimal:
786 dataContract = new DecimalDataContract();
788 case TypeCode.Double:
789 dataContract = new DoubleDataContract();
792 dataContract = new ShortDataContract();
795 dataContract = new IntDataContract();
798 dataContract = new LongDataContract();
801 dataContract = new SignedByteDataContract();
803 case TypeCode.Single:
804 dataContract = new FloatDataContract();
806 case TypeCode.String:
807 dataContract = new StringDataContract();
809 case TypeCode.UInt16:
810 dataContract = new UnsignedShortDataContract();
812 case TypeCode.UInt32:
813 dataContract = new UnsignedIntDataContract();
815 case TypeCode.UInt64:
816 dataContract = new UnsignedLongDataContract();
819 if (type == typeof(byte[]))
820 dataContract = new ByteArrayDataContract();
821 else if (type == typeof(object))
822 dataContract = new ObjectDataContract();
823 else if (type == typeof(Uri))
824 dataContract = new UriDataContract();
825 else if (type == typeof(XmlQualifiedName))
826 dataContract = new QNameDataContract();
827 else if (type == typeof(TimeSpan))
828 dataContract = new TimeSpanDataContract();
829 else if (type == typeof(Guid))
830 dataContract = new GuidDataContract();
831 else if (type == typeof(Enum) || type == typeof(ValueType))
833 dataContract = new SpecialTypeDataContract(type, DictionaryGlobals.ObjectLocalName, DictionaryGlobals.SchemaNamespace);
835 else if (type == typeof(Array))
836 dataContract = new CollectionDataContract(type);
837 else if (type == typeof(XmlElement) || type == typeof(XmlNode[]))
838 dataContract = new XmlDataContract(type);
841 return dataContract != null;
844 static public bool TryCreateBuiltInDataContract(string name, string ns, out DataContract dataContract)
847 if (ns == DictionaryGlobals.SchemaNamespace.Value)
849 if (DictionaryGlobals.BooleanLocalName.Value == name)
850 dataContract = new BooleanDataContract();
851 else if (DictionaryGlobals.SignedByteLocalName.Value == name)
852 dataContract = new SignedByteDataContract();
853 else if (DictionaryGlobals.UnsignedByteLocalName.Value == name)
854 dataContract = new UnsignedByteDataContract();
855 else if (DictionaryGlobals.ShortLocalName.Value == name)
856 dataContract = new ShortDataContract();
857 else if (DictionaryGlobals.UnsignedShortLocalName.Value == name)
858 dataContract = new UnsignedShortDataContract();
859 else if (DictionaryGlobals.IntLocalName.Value == name)
860 dataContract = new IntDataContract();
861 else if (DictionaryGlobals.UnsignedIntLocalName.Value == name)
862 dataContract = new UnsignedIntDataContract();
863 else if (DictionaryGlobals.LongLocalName.Value == name)
864 dataContract = new LongDataContract();
865 else if (DictionaryGlobals.integerLocalName.Value == name)
866 dataContract = new IntegerDataContract();
867 else if (DictionaryGlobals.positiveIntegerLocalName.Value == name)
868 dataContract = new PositiveIntegerDataContract();
869 else if (DictionaryGlobals.negativeIntegerLocalName.Value == name)
870 dataContract = new NegativeIntegerDataContract();
871 else if (DictionaryGlobals.nonPositiveIntegerLocalName.Value == name)
872 dataContract = new NonPositiveIntegerDataContract();
873 else if (DictionaryGlobals.nonNegativeIntegerLocalName.Value == name)
874 dataContract = new NonNegativeIntegerDataContract();
875 else if (DictionaryGlobals.UnsignedLongLocalName.Value == name)
876 dataContract = new UnsignedLongDataContract();
877 else if (DictionaryGlobals.FloatLocalName.Value == name)
878 dataContract = new FloatDataContract();
879 else if (DictionaryGlobals.DoubleLocalName.Value == name)
880 dataContract = new DoubleDataContract();
881 else if (DictionaryGlobals.DecimalLocalName.Value == name)
882 dataContract = new DecimalDataContract();
883 else if (DictionaryGlobals.DateTimeLocalName.Value == name)
884 dataContract = new DateTimeDataContract();
885 else if (DictionaryGlobals.StringLocalName.Value == name)
886 dataContract = new StringDataContract();
887 else if (DictionaryGlobals.timeLocalName.Value == name)
888 dataContract = new TimeDataContract();
889 else if (DictionaryGlobals.dateLocalName.Value == name)
890 dataContract = new DateDataContract();
891 else if (DictionaryGlobals.hexBinaryLocalName.Value == name)
892 dataContract = new HexBinaryDataContract();
893 else if (DictionaryGlobals.gYearMonthLocalName.Value == name)
894 dataContract = new GYearMonthDataContract();
895 else if (DictionaryGlobals.gYearLocalName.Value == name)
896 dataContract = new GYearDataContract();
897 else if (DictionaryGlobals.gMonthDayLocalName.Value == name)
898 dataContract = new GMonthDayDataContract();
899 else if (DictionaryGlobals.gDayLocalName.Value == name)
900 dataContract = new GDayDataContract();
901 else if (DictionaryGlobals.gMonthLocalName.Value == name)
902 dataContract = new GMonthDataContract();
903 else if (DictionaryGlobals.normalizedStringLocalName.Value == name)
904 dataContract = new NormalizedStringDataContract();
905 else if (DictionaryGlobals.tokenLocalName.Value == name)
906 dataContract = new TokenDataContract();
907 else if (DictionaryGlobals.languageLocalName.Value == name)
908 dataContract = new LanguageDataContract();
909 else if (DictionaryGlobals.NameLocalName.Value == name)
910 dataContract = new NameDataContract();
911 else if (DictionaryGlobals.NCNameLocalName.Value == name)
912 dataContract = new NCNameDataContract();
913 else if (DictionaryGlobals.XSDIDLocalName.Value == name)
914 dataContract = new IDDataContract();
915 else if (DictionaryGlobals.IDREFLocalName.Value == name)
916 dataContract = new IDREFDataContract();
917 else if (DictionaryGlobals.IDREFSLocalName.Value == name)
918 dataContract = new IDREFSDataContract();
919 else if (DictionaryGlobals.ENTITYLocalName.Value == name)
920 dataContract = new ENTITYDataContract();
921 else if (DictionaryGlobals.ENTITIESLocalName.Value == name)
922 dataContract = new ENTITIESDataContract();
923 else if (DictionaryGlobals.NMTOKENLocalName.Value == name)
924 dataContract = new NMTOKENDataContract();
925 else if (DictionaryGlobals.NMTOKENSLocalName.Value == name)
926 dataContract = new NMTOKENDataContract();
927 else if (DictionaryGlobals.ByteArrayLocalName.Value == name)
928 dataContract = new ByteArrayDataContract();
929 else if (DictionaryGlobals.ObjectLocalName.Value == name)
930 dataContract = new ObjectDataContract();
931 else if (DictionaryGlobals.TimeSpanLocalName.Value == name)
932 dataContract = new XsDurationDataContract();
933 else if (DictionaryGlobals.UriLocalName.Value == name)
934 dataContract = new UriDataContract();
935 else if (DictionaryGlobals.QNameLocalName.Value == name)
936 dataContract = new QNameDataContract();
938 else if (ns == DictionaryGlobals.SerializationNamespace.Value)
940 if (DictionaryGlobals.TimeSpanLocalName.Value == name)
941 dataContract = new TimeSpanDataContract();
942 else if (DictionaryGlobals.GuidLocalName.Value == name)
943 dataContract = new GuidDataContract();
944 else if (DictionaryGlobals.CharLocalName.Value == name)
945 dataContract = new CharDataContract();
946 else if ("ArrayOfanyType" == name)
947 dataContract = new CollectionDataContract(typeof(Array));
949 else if (ns == DictionaryGlobals.AsmxTypesNamespace.Value)
951 if (DictionaryGlobals.CharLocalName.Value == name)
952 dataContract = new AsmxCharDataContract();
953 else if (DictionaryGlobals.GuidLocalName.Value == name)
954 dataContract = new AsmxGuidDataContract();
956 else if (ns == Globals.DataContractXmlNamespace)
958 if (name == "XmlElement")
959 dataContract = new XmlDataContract(typeof(XmlElement));
960 else if (name == "ArrayOfXmlNode")
961 dataContract = new XmlDataContract(typeof(XmlNode[]));
963 return dataContract != null;
966 internal static string GetNamespace(string key)
968 lock (namespacesLock)
970 if (namespaces == null)
971 namespaces = new Dictionary<string, string>();
973 if (namespaces.TryGetValue(key, out value))
977 namespaces.Add(key, key);
985 throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
991 internal static XmlDictionaryString GetClrTypeString(string key)
993 lock (clrTypeStringsLock)
995 if (clrTypeStrings == null)
997 clrTypeStringsDictionary = new XmlDictionary();
998 clrTypeStrings = new Dictionary<string, XmlDictionaryString>();
1001 clrTypeStrings.Add(Globals.TypeOfInt.Assembly.FullName, clrTypeStringsDictionary.Add(Globals.MscorlibAssemblyName));
1003 catch (Exception ex)
1009 throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
1012 XmlDictionaryString value;
1013 if (clrTypeStrings.TryGetValue(key, out value))
1015 value = clrTypeStringsDictionary.Add(key);
1018 clrTypeStrings.Add(key, value);
1020 catch (Exception ex)
1026 throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
1032 internal static void ThrowInvalidDataContractException(string message, Type type)
1038 typeHandleRef.Value = GetDataContractAdapterTypeHandle(type.TypeHandle);
1041 typeToIDCache.Remove(typeHandleRef);
1043 catch (Exception ex)
1049 throw DiagnosticUtility.ExceptionUtility.ThrowHelperFatal(ex.Message, ex);
1054 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(message));
1057 internal DataContractCriticalHelper()
1061 internal DataContractCriticalHelper(Type type)
1063 underlyingType = type;
1064 SetTypeForInitialization(type);
1065 isValueType = type.IsValueType;
1068 internal Type UnderlyingType
1070 get { return underlyingType; }
1073 internal Type OriginalUnderlyingType
1077 if (this.originalUnderlyingType == null)
1079 this.originalUnderlyingType = GetDataContractOriginalType(this.underlyingType);
1081 return this.originalUnderlyingType;
1085 internal virtual bool IsBuiltInDataContract
1093 internal Type TypeForInitialization
1095 get { return this.typeForInitialization; }
1098 [Fx.Tag.SecurityNote(Critical = "Sets the critical typeForInitialization property.",
1099 Safe = "Validates input data, sets field correctly.")]
1100 [SecuritySafeCritical]
1101 void SetTypeForInitialization(Type classType)
1103 if (classType.IsSerializable || classType.IsDefined(Globals.TypeOfDataContractAttribute, false))
1105 this.typeForInitialization = classType;
1109 internal bool IsReference
1111 get { return isReference; }
1114 isReference = value;
1118 internal bool IsValueType
1120 get { return isValueType; }
1121 set { isValueType = value; }
1124 internal XmlQualifiedName StableName
1126 get { return stableName; }
1127 set { stableName = value; }
1130 internal GenericInfo GenericInfo
1132 get { return genericInfo; }
1133 set { genericInfo = value; }
1136 internal virtual DataContractDictionary KnownDataContracts
1138 get { return null; }
1139 set { /* do nothing */ }
1142 internal virtual bool IsISerializable
1144 get { return false; }
1145 set { ThrowInvalidDataContractException(SR.GetString(SR.RequiresClassDataContractToSetIsISerializable)); }
1148 internal XmlDictionaryString Name
1150 get { return name; }
1151 set { name = value; }
1154 public XmlDictionaryString Namespace
1160 internal virtual bool HasRoot
1162 get { return true; }
1166 internal virtual XmlDictionaryString TopLevelElementName
1168 get { return name; }
1169 set { name = value; }
1172 internal virtual XmlDictionaryString TopLevelElementNamespace
1178 internal virtual bool CanContainReferences
1180 get { return true; }
1183 internal virtual bool IsPrimitive
1185 get { return false; }
1188 internal MethodInfo ParseMethod
1192 if (!parseMethodSet)
1194 MethodInfo method = UnderlyingType.GetMethod(Globals.ParseMethodName, BindingFlags.Public | BindingFlags.Static, null, new Type[] { Globals.TypeOfString }, null);
1196 if (method != null && method.ReturnType == UnderlyingType)
1198 parseMethod = method;
1201 parseMethodSet = true;
1203 return parseMethod; }
1206 internal virtual void WriteRootElement(XmlWriterDelegator writer, XmlDictionaryString name, XmlDictionaryString ns)
1208 if (object.ReferenceEquals(ns, DictionaryGlobals.SerializationNamespace) && !IsPrimitive)
1209 writer.WriteStartElement(Globals.SerPrefix, name, ns);
1211 writer.WriteStartElement(name, ns);
1214 internal void SetDataContractName(XmlQualifiedName stableName)
1216 XmlDictionary dictionary = new XmlDictionary(2);
1217 this.Name = dictionary.Add(stableName.Name);
1218 this.Namespace = dictionary.Add(stableName.Namespace);
1219 this.StableName = stableName;
1222 internal void SetDataContractName(XmlDictionaryString name, XmlDictionaryString ns)
1225 this.Namespace = ns;
1226 this.StableName = CreateQualifiedName(name.Value, ns.Value);
1229 internal void ThrowInvalidDataContractException(string message)
1231 ThrowInvalidDataContractException(message, UnderlyingType);
1235 static internal bool IsTypeSerializable(Type type)
1237 return IsTypeSerializable(type, new Dictionary<Type, object>());
1240 static bool IsTypeSerializable(Type type, Dictionary<Type, object> previousCollectionTypes)
1243 if (type.IsSerializable ||
1244 type.IsDefined(Globals.TypeOfDataContractAttribute, false) ||
1247 Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
1251 if (CollectionDataContract.IsCollection(type, out itemType))
1253 ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
1254 if (IsTypeSerializable(itemType, previousCollectionTypes))
1259 return (DataContract.GetBuiltInDataContract(type) != null || ClassDataContract.IsNonAttributedTypeValidForSerialization(type));
1262 [SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "previousCollectionTypes", Justification = "No need to support type equivalence here.")]
1263 static void ValidatePreviousCollectionTypes(Type collectionType, Type itemType, Dictionary<Type, object> previousCollectionTypes)
1265 previousCollectionTypes.Add(collectionType, collectionType);
1266 while (itemType.IsArray)
1268 itemType = itemType.GetElementType();
1271 // Do a breadth first traversal of the generic type tree to
1272 // produce the closure of all generic argument types and
1273 // check that none of these is in the previousCollectionTypes
1275 List<Type> itemTypeClosure = new List<Type>();
1276 Queue<Type> itemTypeQueue = new Queue<Type>();
1278 itemTypeQueue.Enqueue(itemType);
1279 itemTypeClosure.Add(itemType);
1281 while (itemTypeQueue.Count > 0)
1283 itemType = itemTypeQueue.Dequeue();
1284 if (previousCollectionTypes.ContainsKey(itemType))
1286 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.RecursiveCollectionType, DataContract.GetClrTypeFullName(itemType))));
1288 if (itemType.IsGenericType)
1290 foreach (Type argType in itemType.GetGenericArguments())
1292 if (!itemTypeClosure.Contains(argType))
1294 itemTypeQueue.Enqueue(argType);
1295 itemTypeClosure.Add(argType);
1302 internal static Type UnwrapRedundantNullableType(Type type)
1304 Type nullableType = type;
1305 while (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfNullable)
1307 nullableType = type;
1308 type = type.GetGenericArguments()[0];
1310 return nullableType;
1313 internal static Type UnwrapNullableType(Type type)
1315 while (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfNullable)
1316 type = type.GetGenericArguments()[0];
1320 static bool IsAlpha(char ch)
1322 return (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z');
1325 static bool IsDigit(char ch)
1327 return (ch >= '0' && ch <= '9');
1330 static bool IsAsciiLocalName(string localName)
1332 if (localName.Length == 0)
1334 if (!IsAlpha(localName[0]))
1336 for (int i = 1; i < localName.Length; i++)
1338 char ch = localName[i];
1339 if (!IsAlpha(ch) && !IsDigit(ch))
1345 static internal string EncodeLocalName(string localName)
1347 if (IsAsciiLocalName(localName))
1350 if (IsValidNCName(localName))
1353 return XmlConvert.EncodeLocalName(localName);
1356 internal static bool IsValidNCName(string name)
1360 XmlConvert.VerifyNCName(name);
1363 catch (XmlException)
1369 internal static XmlQualifiedName GetStableName(Type type)
1371 bool hasDataContract;
1372 return GetStableName(type, out hasDataContract);
1375 internal static XmlQualifiedName GetStableName(Type type, out bool hasDataContract)
1377 return GetStableName(type, new Dictionary<Type, object>(), out hasDataContract);
1380 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Callers may need to depend on hasDataContract for a security decision."
1381 + " hasDataContract must be calculated correctly."
1382 + " GetStableName is factored into sub-methods so as to isolate the DataContractAttribute calculation and reduce SecurityCritical surface area.",
1383 Safe = "Does not let caller influence hasDataContract calculation; no harm in leaking value.")]
1384 static XmlQualifiedName GetStableName(Type type, Dictionary<Type, object> previousCollectionTypes, out bool hasDataContract)
1386 type = UnwrapRedundantNullableType(type);
1387 XmlQualifiedName stableName;
1388 if (TryGetBuiltInXmlAndArrayTypeStableName(type, previousCollectionTypes, out stableName))
1390 hasDataContract = false;
1394 DataContractAttribute dataContractAttribute;
1395 if (TryGetDCAttribute(type, out dataContractAttribute))
1397 stableName = GetDCTypeStableName(type, dataContractAttribute);
1398 hasDataContract = true;
1402 stableName = GetNonDCTypeStableName(type, previousCollectionTypes);
1403 hasDataContract = false;
1410 static XmlQualifiedName GetDCTypeStableName(Type type, DataContractAttribute dataContractAttribute)
1412 string name = null, ns = null;
1413 if (dataContractAttribute.IsNameSetExplicitly)
1415 name = dataContractAttribute.Name;
1416 if (name == null || name.Length == 0)
1417 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidDataContractName, DataContract.GetClrTypeFullName(type))));
1418 if (type.IsGenericType && !type.IsGenericTypeDefinition)
1419 name = ExpandGenericParameters(name, type);
1420 name = DataContract.EncodeLocalName(name);
1423 name = GetDefaultStableLocalName(type);
1425 if (dataContractAttribute.IsNamespaceSetExplicitly)
1427 ns = dataContractAttribute.Namespace;
1429 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidDataContractNamespace, DataContract.GetClrTypeFullName(type))));
1430 CheckExplicitDataContractNamespaceUri(ns, type);
1433 ns = GetDefaultDataContractNamespace(type);
1435 return CreateQualifiedName(name, ns);
1438 static XmlQualifiedName GetNonDCTypeStableName(Type type, Dictionary<Type, object> previousCollectionTypes)
1440 string name = null, ns = null;
1443 CollectionDataContractAttribute collectionContractAttribute;
1444 if (CollectionDataContract.IsCollection(type, out itemType))
1446 ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
1447 return GetCollectionStableName(type, itemType, previousCollectionTypes, out collectionContractAttribute);
1449 name = GetDefaultStableLocalName(type);
1451 // ensures that ContractNamespaceAttribute is honored when used with non-attributed types
1452 if (ClassDataContract.IsNonAttributedTypeValidForSerialization(type))
1454 ns = GetDefaultDataContractNamespace(type);
1458 ns = GetDefaultStableNamespace(type);
1460 return CreateQualifiedName(name, ns);
1463 static bool TryGetBuiltInXmlAndArrayTypeStableName(Type type, Dictionary<Type, object> previousCollectionTypes, out XmlQualifiedName stableName)
1467 DataContract builtInContract = GetBuiltInDataContract(type);
1468 if (builtInContract != null)
1470 stableName = builtInContract.StableName;
1472 else if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
1475 XmlSchemaType xsdType;
1476 XmlQualifiedName xmlTypeStableName;
1477 SchemaExporter.GetXmlTypeInfo(type, out xmlTypeStableName, out xsdType, out hasRoot);
1478 stableName = xmlTypeStableName;
1480 else if (type.IsArray)
1482 Type itemType = type.GetElementType();
1483 ValidatePreviousCollectionTypes(type, itemType, previousCollectionTypes);
1484 CollectionDataContractAttribute collectionContractAttribute;
1485 stableName = GetCollectionStableName(type, itemType, previousCollectionTypes, out collectionContractAttribute);
1487 return stableName != null;
1490 [Fx.Tag.SecurityNote(Critical = "Marked SecurityCritical because callers may need to base security decisions on the presence (or absence) of the DC attribute.",
1491 Safe = "Does not let caller influence calculation and the result is not a protected value.")]
1492 [SecuritySafeCritical]
1493 internal static bool TryGetDCAttribute(Type type, out DataContractAttribute dataContractAttribute)
1495 dataContractAttribute = null;
1497 object[] dataContractAttributes = type.GetCustomAttributes(Globals.TypeOfDataContractAttribute, false);
1498 if (dataContractAttributes != null && dataContractAttributes.Length > 0)
1501 if (dataContractAttributes.Length > 1)
1502 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TooManyDataContracts, DataContract.GetClrTypeFullName(type))));
1504 dataContractAttribute = (DataContractAttribute)dataContractAttributes[0];
1507 return dataContractAttribute != null;
1510 internal static XmlQualifiedName GetCollectionStableName(Type type, Type itemType, out CollectionDataContractAttribute collectionContractAttribute)
1512 return GetCollectionStableName(type, itemType, new Dictionary<Type, object>(), out collectionContractAttribute);
1515 static XmlQualifiedName GetCollectionStableName(Type type, Type itemType, Dictionary<Type, object> previousCollectionTypes, out CollectionDataContractAttribute collectionContractAttribute)
1518 object[] collectionContractAttributes = type.GetCustomAttributes(Globals.TypeOfCollectionDataContractAttribute, false);
1519 if (collectionContractAttributes != null && collectionContractAttributes.Length > 0)
1522 if (collectionContractAttributes.Length > 1)
1523 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TooManyCollectionContracts, DataContract.GetClrTypeFullName(type))));
1525 collectionContractAttribute = (CollectionDataContractAttribute)collectionContractAttributes[0];
1526 if (collectionContractAttribute.IsNameSetExplicitly)
1528 name = collectionContractAttribute.Name;
1529 if (name == null || name.Length == 0)
1530 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractName, DataContract.GetClrTypeFullName(type))));
1531 if (type.IsGenericType && !type.IsGenericTypeDefinition)
1532 name = ExpandGenericParameters(name, type);
1533 name = DataContract.EncodeLocalName(name);
1536 name = GetDefaultStableLocalName(type);
1538 if (collectionContractAttribute.IsNamespaceSetExplicitly)
1540 ns = collectionContractAttribute.Namespace;
1542 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractNamespace, DataContract.GetClrTypeFullName(type))));
1543 CheckExplicitDataContractNamespaceUri(ns, type);
1546 ns = GetDefaultDataContractNamespace(type);
1550 collectionContractAttribute = null;
1551 string arrayOfPrefix = Globals.ArrayPrefix + GetArrayPrefix(ref itemType);
1552 bool hasDataContract;
1553 XmlQualifiedName elementStableName = GetStableName(itemType, previousCollectionTypes, out hasDataContract);
1554 name = arrayOfPrefix + elementStableName.Name;
1555 ns = GetCollectionNamespace(elementStableName.Namespace);
1557 return CreateQualifiedName(name, ns);
1560 private static string GetArrayPrefix(ref Type itemType)
1562 string arrayOfPrefix = string.Empty;
1563 while (itemType.IsArray)
1565 if (DataContract.GetBuiltInDataContract(itemType) != null)
1567 arrayOfPrefix += Globals.ArrayPrefix;
1568 itemType = itemType.GetElementType();
1570 return arrayOfPrefix;
1573 internal XmlQualifiedName GetArrayTypeName(bool isNullable)
1575 XmlQualifiedName itemName;
1576 if (this.IsValueType && isNullable)
1578 GenericInfo genericInfo = new GenericInfo(DataContract.GetStableName(Globals.TypeOfNullable), Globals.TypeOfNullable.FullName);
1579 genericInfo.Add(new GenericInfo(this.StableName, null));
1580 genericInfo.AddToLevel(0, 1);
1581 itemName = genericInfo.GetExpandedStableName();
1584 itemName = this.StableName;
1585 string ns = GetCollectionNamespace(itemName.Namespace);
1586 string name = Globals.ArrayPrefix + itemName.Name;
1587 return new XmlQualifiedName(name, ns);
1590 internal static string GetCollectionNamespace(string elementNs)
1592 return IsBuiltInNamespace(elementNs) ? Globals.CollectionsNamespace : elementNs;
1595 internal static XmlQualifiedName GetDefaultStableName(Type type)
1597 return CreateQualifiedName(GetDefaultStableLocalName(type), GetDefaultStableNamespace(type));
1600 static string GetDefaultStableLocalName(Type type)
1602 if (type.IsGenericParameter)
1603 return "{" + type.GenericParameterPosition + "}";
1605 string arrayPrefix = null;
1607 arrayPrefix = GetArrayPrefix(ref type);
1608 if (type.DeclaringType == null)
1609 typeName = type.Name;
1612 int nsLen = (type.Namespace == null) ? 0 : type.Namespace.Length;
1614 nsLen++; //include the . following namespace
1615 typeName = DataContract.GetClrTypeFullName(type).Substring(nsLen).Replace('+', '.');
1617 if (arrayPrefix != null)
1618 typeName = arrayPrefix + typeName;
1619 if (type.IsGenericType)
1621 StringBuilder localName = new StringBuilder();
1622 StringBuilder namespaces = new StringBuilder();
1623 bool parametersFromBuiltInNamespaces = true;
1624 int iParam = typeName.IndexOf('[');
1626 typeName = typeName.Substring(0, iParam);
1627 IList<int> nestedParamCounts = GetDataContractNameForGenericName(typeName, localName);
1628 bool isTypeOpenGeneric = type.IsGenericTypeDefinition;
1629 Type[] genParams = type.GetGenericArguments();
1630 for (int i = 0; i < genParams.Length; i++)
1632 Type genParam = genParams[i];
1633 if (isTypeOpenGeneric)
1634 localName.Append("{").Append(i).Append("}");
1637 XmlQualifiedName qname = DataContract.GetStableName(genParam);
1638 localName.Append(qname.Name);
1639 namespaces.Append(" ").Append(qname.Namespace);
1640 if (parametersFromBuiltInNamespaces)
1641 parametersFromBuiltInNamespaces = IsBuiltInNamespace(qname.Namespace);
1644 if (isTypeOpenGeneric)
1645 localName.Append("{#}");
1646 else if (nestedParamCounts.Count > 1 || !parametersFromBuiltInNamespaces)
1648 foreach (int count in nestedParamCounts)
1649 namespaces.Insert(0, count).Insert(0, " ");
1650 localName.Append(GetNamespacesDigest(namespaces.ToString()));
1652 typeName = localName.ToString();
1654 return DataContract.EncodeLocalName(typeName);
1657 static string GetDefaultDataContractNamespace(Type type)
1659 string clrNs = type.Namespace;
1661 clrNs = String.Empty;
1662 string ns = GetGlobalDataContractNamespace(clrNs, type.Module);
1664 ns = GetGlobalDataContractNamespace(clrNs, type.Assembly);
1667 ns = GetDefaultStableNamespace(type);
1669 CheckExplicitDataContractNamespaceUri(ns, type);
1673 internal static IList<int> GetDataContractNameForGenericName(string typeName, StringBuilder localName)
1675 List<int> nestedParamCounts = new List<int>();
1676 for (int startIndex = 0, endIndex;;)
1678 endIndex = typeName.IndexOf('`', startIndex);
1681 if (localName != null)
1682 localName.Append(typeName.Substring(startIndex));
1683 nestedParamCounts.Add(0);
1686 if (localName != null)
1687 localName.Append(typeName.Substring(startIndex, endIndex - startIndex));
1688 while ((startIndex = typeName.IndexOf('.', startIndex + 1, endIndex - startIndex - 1)) >= 0)
1689 nestedParamCounts.Add(0);
1690 startIndex = typeName.IndexOf('.', endIndex);
1693 nestedParamCounts.Add(Int32.Parse(typeName.Substring(endIndex + 1), CultureInfo.InvariantCulture));
1697 nestedParamCounts.Add(Int32.Parse(typeName.Substring(endIndex + 1, startIndex - endIndex - 1), CultureInfo.InvariantCulture));
1699 if (localName != null)
1700 localName.Append("Of");
1701 return nestedParamCounts;
1704 internal static bool IsBuiltInNamespace(string ns)
1706 return (ns == Globals.SchemaNamespace || ns == Globals.SerializationNamespace);
1709 internal static string GetDefaultStableNamespace(Type type)
1711 if (type.IsGenericParameter)
1713 return GetDefaultStableNamespace(type.Namespace);
1716 internal static XmlQualifiedName CreateQualifiedName(string localName, string ns)
1718 return new XmlQualifiedName(localName, GetNamespace(ns));
1721 internal static string GetDefaultStableNamespace(string clrNs)
1723 if (clrNs == null) clrNs = String.Empty;
1724 return new Uri(Globals.DataContractXsdBaseNamespaceUri, clrNs).AbsoluteUri;
1727 static void CheckExplicitDataContractNamespaceUri(string dataContractNs, Type type)
1729 if (dataContractNs.Length > 0)
1731 string trimmedNs = dataContractNs.Trim();
1732 // Code similar to XmlConvert.ToUri (string.Empty is a valid uri but not " ")
1733 if (trimmedNs.Length == 0 || trimmedNs.IndexOf("##", StringComparison.Ordinal) != -1)
1734 ThrowInvalidDataContractException(SR.GetString(SR.DataContractNamespaceIsNotValid, dataContractNs), type);
1735 dataContractNs = trimmedNs;
1738 if (Uri.TryCreate(dataContractNs, UriKind.RelativeOrAbsolute, out uri))
1740 if (uri.ToString() == Globals.SerializationNamespace)
1741 ThrowInvalidDataContractException(SR.GetString(SR.DataContractNamespaceReserved, Globals.SerializationNamespace), type);
1744 ThrowInvalidDataContractException(SR.GetString(SR.DataContractNamespaceIsNotValid, dataContractNs), type);
1747 internal static string GetClrTypeFullName(Type type)
1749 return !type.IsGenericTypeDefinition && type.ContainsGenericParameters ? String.Format(CultureInfo.InvariantCulture, "{0}.{1}", type.Namespace, type.Name) : type.FullName;
1752 internal static string GetClrAssemblyName(Type type, out bool hasTypeForwardedFrom)
1754 hasTypeForwardedFrom = false;
1755 object[] typeAttributes = type.GetCustomAttributes(typeof(TypeForwardedFromAttribute), false);
1756 if (typeAttributes != null && typeAttributes.Length > 0)
1758 TypeForwardedFromAttribute typeForwardedFromAttribute = (TypeForwardedFromAttribute)typeAttributes[0];
1759 hasTypeForwardedFrom = true;
1760 return typeForwardedFromAttribute.AssemblyFullName;
1764 return type.Assembly.FullName;
1768 internal static string GetClrTypeFullNameUsingTypeForwardedFromAttribute(Type type)
1772 return GetClrTypeFullNameForArray(type);
1776 return GetClrTypeFullNameForNonArrayTypes(type);
1780 static string GetClrTypeFullNameForArray(Type type)
1782 return String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}",
1783 GetClrTypeFullNameUsingTypeForwardedFromAttribute(type.GetElementType()), Globals.OpenBracket, Globals.CloseBracket);
1786 static string GetClrTypeFullNameForNonArrayTypes(Type type)
1788 if (!type.IsGenericType)
1790 return DataContract.GetClrTypeFullName(type);
1793 Type[] genericArguments = type.GetGenericArguments();
1794 StringBuilder builder = new StringBuilder(type.GetGenericTypeDefinition().FullName).Append(Globals.OpenBracket);
1796 foreach (Type genericArgument in genericArguments)
1798 bool hasTypeForwardedFrom;
1799 builder.Append(Globals.OpenBracket).Append(GetClrTypeFullNameUsingTypeForwardedFromAttribute(genericArgument)).Append(Globals.Comma);
1800 builder.Append(Globals.Space).Append(GetClrAssemblyName(genericArgument, out hasTypeForwardedFrom));
1801 builder.Append(Globals.CloseBracket).Append(Globals.Comma);
1804 //remove the last comma and close typename for generic with a close bracket
1805 return builder.Remove(builder.Length - 1, 1).Append(Globals.CloseBracket).ToString();
1808 internal static void GetClrNameAndNamespace(string fullTypeName, out string localName, out string ns)
1810 int nsEnd = fullTypeName.LastIndexOf('.');
1814 localName = fullTypeName.Replace('+', '.');
1818 ns = fullTypeName.Substring(0, nsEnd);
1819 localName = fullTypeName.Substring(nsEnd + 1).Replace('+', '.');
1821 int iParam = localName.IndexOf('[');
1823 localName = localName.Substring(0, iParam);
1826 internal static void GetDefaultStableName(string fullTypeName, out string localName, out string ns)
1828 CodeTypeReference typeReference = new CodeTypeReference(fullTypeName);
1829 GetDefaultStableName(typeReference, out localName, out ns);
1832 static void GetDefaultStableName(CodeTypeReference typeReference, out string localName, out string ns)
1834 string fullTypeName = typeReference.BaseType;
1835 DataContract dataContract = GetBuiltInDataContract(fullTypeName);
1836 if (dataContract != null)
1838 localName = dataContract.StableName.Name;
1839 ns = dataContract.StableName.Namespace;
1842 GetClrNameAndNamespace(fullTypeName, out localName, out ns);
1843 if (typeReference.TypeArguments.Count > 0)
1845 StringBuilder localNameBuilder = new StringBuilder();
1846 StringBuilder argNamespacesBuilder = new StringBuilder();
1847 bool parametersFromBuiltInNamespaces = true;
1848 IList<int> nestedParamCounts = GetDataContractNameForGenericName(localName, localNameBuilder);
1849 foreach (CodeTypeReference typeArg in typeReference.TypeArguments)
1851 string typeArgName, typeArgNs;
1852 GetDefaultStableName(typeArg, out typeArgName, out typeArgNs);
1853 localNameBuilder.Append(typeArgName);
1854 argNamespacesBuilder.Append(" ").Append(typeArgNs);
1855 if (parametersFromBuiltInNamespaces)
1856 parametersFromBuiltInNamespaces = IsBuiltInNamespace(typeArgNs);
1858 if (nestedParamCounts.Count > 1 || !parametersFromBuiltInNamespaces)
1860 foreach (int count in nestedParamCounts)
1861 argNamespacesBuilder.Insert(0, count).Insert(0, " ");
1862 localNameBuilder.Append(GetNamespacesDigest(argNamespacesBuilder.ToString()));
1864 localName = localNameBuilder.ToString();
1866 localName = DataContract.EncodeLocalName(localName);
1867 ns = GetDefaultStableNamespace(ns);
1870 internal static string GetDataContractNamespaceFromUri(string uriString)
1872 return uriString.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal) ? uriString.Substring(Globals.DataContractXsdBaseNamespace.Length) : uriString;
1875 static string GetGlobalDataContractNamespace(string clrNs, ICustomAttributeProvider customAttribuetProvider)
1877 object[] nsAttributes = customAttribuetProvider.GetCustomAttributes(typeof(ContractNamespaceAttribute), false);
1878 string dataContractNs = null;
1879 for (int i = 0; i < nsAttributes.Length; i++)
1881 ContractNamespaceAttribute nsAttribute = (ContractNamespaceAttribute)nsAttributes[i];
1882 string clrNsInAttribute = nsAttribute.ClrNamespace;
1883 if (clrNsInAttribute == null)
1884 clrNsInAttribute = String.Empty;
1885 if (clrNsInAttribute == clrNs)
1887 if (nsAttribute.ContractNamespace == null)
1888 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidGlobalDataContractNamespace, clrNs)));
1889 if (dataContractNs != null)
1890 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.DataContractNamespaceAlreadySet, dataContractNs, nsAttribute.ContractNamespace, clrNs)));
1891 dataContractNs = nsAttribute.ContractNamespace;
1894 return dataContractNs;
1897 private static string GetNamespacesDigest(string namespaces)
1899 byte[] namespaceBytes = Encoding.UTF8.GetBytes(namespaces);
1900 byte[] digestBytes = HashHelper.ComputeHash(namespaceBytes);
1901 char[] digestChars = new char[24];
1902 const int digestLen = 6;
1903 int digestCharsLen = Convert.ToBase64CharArray(digestBytes, 0, digestLen, digestChars, 0);
1904 StringBuilder digest = new StringBuilder();
1905 for (int i = 0; i < digestCharsLen; i++)
1907 char ch = digestChars[i];
1913 digest.Append("_S");
1916 digest.Append("_P");
1923 return digest.ToString();
1926 private static string ExpandGenericParameters(string format, Type type)
1928 GenericNameProvider genericNameProviderForType = new GenericNameProvider(type);
1929 return ExpandGenericParameters(format, genericNameProviderForType);
1932 internal static string ExpandGenericParameters(string format, IGenericNameProvider genericNameProvider)
1934 string digest = null;
1935 StringBuilder typeName = new StringBuilder();
1936 IList<int> nestedParameterCounts = genericNameProvider.GetNestedParameterCounts();
1937 for (int i = 0; i < format.Length; i++)
1939 char ch = format[i];
1944 for (; i < format.Length; i++)
1945 if (format[i] == '}')
1947 if (i == format.Length)
1948 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericNameBraceMismatch, format, genericNameProvider.GetGenericTypeName())));
1949 if (format[start] == '#' && i == (start + 1))
1951 if (nestedParameterCounts.Count > 1 || !genericNameProvider.ParametersFromBuiltInNamespaces)
1955 StringBuilder namespaces = new StringBuilder(genericNameProvider.GetNamespaces());
1956 foreach (int count in nestedParameterCounts)
1957 namespaces.Insert(0, count).Insert(0, " ");
1958 digest = GetNamespacesDigest(namespaces.ToString());
1960 typeName.Append(digest);
1966 if (!Int32.TryParse(format.Substring(start, i - start), out paramIndex) || paramIndex < 0 || paramIndex >= genericNameProvider.GetParameterCount())
1967 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericParameterNotValid, format.Substring(start, i - start), genericNameProvider.GetGenericTypeName(), genericNameProvider.GetParameterCount() - 1)));
1968 typeName.Append(genericNameProvider.GetParameterName(paramIndex));
1972 typeName.Append(ch);
1974 return typeName.ToString();
1977 static internal bool IsTypeNullable(Type type)
1979 return !type.IsValueType ||
1980 (type.IsGenericType &&
1981 type.GetGenericTypeDefinition() == Globals.TypeOfNullable);
1984 public static void ThrowTypeNotSerializable(Type type)
1986 ThrowInvalidDataContractException(SR.GetString(SR.TypeNotSerializable, type), type);
1989 #if !NO_CONFIGURATION
1990 [Fx.Tag.SecurityNote(Critical = "configSection value is fetched under an elevation; need to protected access to it.")]
1992 static DataContractSerializerSection configSection;
1993 static DataContractSerializerSection ConfigSection
1995 [Fx.Tag.SecurityNote(Critical = "Calls Security Critical method DataContractSerializerSection.UnsafeGetSection and stores result in"
1996 + " SecurityCritical field configSection.")]
2000 if (configSection == null)
2001 configSection = DataContractSerializerSection.UnsafeGetSection();
2002 return configSection;
2007 internal static DataContractDictionary ImportKnownTypeAttributes(Type type)
2009 DataContractDictionary knownDataContracts = null;
2010 Dictionary<Type, Type> typesChecked = new Dictionary<Type, Type>();
2011 ImportKnownTypeAttributes(type, typesChecked, ref knownDataContracts);
2012 return knownDataContracts;
2015 [SuppressMessage(FxCop.Category.Usage, "CA2301:EmbeddableTypesInContainersRule", MessageId = "typesChecked", Justification = "No need to support type equivalence here.")]
2016 static void ImportKnownTypeAttributes(Type type, Dictionary<Type, Type> typesChecked, ref DataContractDictionary knownDataContracts)
2018 if (TD.ImportKnownTypesStartIsEnabled())
2020 TD.ImportKnownTypesStart();
2023 while (type != null && DataContract.IsTypeSerializable(type))
2025 if (typesChecked.ContainsKey(type))
2028 typesChecked.Add(type, type);
2029 object[] knownTypeAttributes = type.GetCustomAttributes(Globals.TypeOfKnownTypeAttribute, false);
2030 if (knownTypeAttributes != null)
2032 KnownTypeAttribute kt;
2033 bool useMethod = false, useType = false;
2034 for (int i = 0; i < knownTypeAttributes.Length; ++i)
2036 kt = (KnownTypeAttribute)knownTypeAttributes[i];
2037 if (kt.Type != null)
2041 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeOneScheme, DataContract.GetClrTypeFullName(type)), type);
2044 CheckAndAdd(kt.Type, typesChecked, ref knownDataContracts);
2049 if (useMethod || useType)
2051 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeOneScheme, DataContract.GetClrTypeFullName(type)), type);
2054 string methodName = kt.MethodName;
2055 if (methodName == null)
2057 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeNoData, DataContract.GetClrTypeFullName(type)), type);
2060 if (methodName.Length == 0)
2061 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeEmptyString, DataContract.GetClrTypeFullName(type)), type);
2063 MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
2065 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeUnknownMethod, methodName, DataContract.GetClrTypeFullName(type)), type);
2067 if (!Globals.TypeOfTypeEnumerable.IsAssignableFrom(method.ReturnType))
2068 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeReturnType, DataContract.GetClrTypeFullName(type), methodName), type);
2070 object types = method.Invoke(null, Globals.EmptyObjectArray);
2073 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeMethodNull, DataContract.GetClrTypeFullName(type)), type);
2076 foreach (Type ty in (IEnumerable<Type>)types)
2079 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.KnownTypeAttributeValidMethodTypes, DataContract.GetClrTypeFullName(type)), type);
2081 CheckAndAdd(ty, typesChecked, ref knownDataContracts);
2089 LoadKnownTypesFromConfig(type, typesChecked, ref knownDataContracts);
2091 type = type.BaseType;
2094 if (TD.ImportKnownTypesStopIsEnabled())
2096 TD.ImportKnownTypesStop();
2100 [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical property ConfigSection.",
2101 Safe = "Completely processes ConfigSection and only makes available the processed result."
2102 + " The ConfigSection instance is not leaked.")]
2103 [SecuritySafeCritical]
2104 static void LoadKnownTypesFromConfig(Type type, Dictionary<Type, Type> typesChecked, ref DataContractDictionary knownDataContracts)
2106 #if !NO_CONFIGURATION
2107 // Pull known types from config
2108 if (ConfigSection != null)
2110 DeclaredTypeElementCollection elements = ConfigSection.DeclaredTypes;
2112 Type rootType = type;
2113 Type[] genArgs = null;
2115 CheckRootTypeInConfigIsGeneric(type, ref rootType, ref genArgs);
2117 DeclaredTypeElement elem = elements[rootType.AssemblyQualifiedName];
2120 if (IsElemTypeNullOrNotEqualToRootType(elem.Type, rootType))
2128 for (int i = 0; i < elements.Count; ++i)
2130 if (IsCollectionElementTypeEqualToRootType(elements[i].Type, rootType))
2140 for (int i = 0; i < elem.KnownTypes.Count; ++i)
2142 Type knownType = elem.KnownTypes[i].GetType(elem.Type, genArgs);
2143 if (knownType != null)
2145 CheckAndAdd(knownType, typesChecked, ref knownDataContracts);
2153 private static void CheckRootTypeInConfigIsGeneric(Type type, ref Type rootType, ref Type[] genArgs)
2155 if (rootType.IsGenericType)
2157 if (!rootType.ContainsGenericParameters)
2159 genArgs = rootType.GetGenericArguments();
2160 rootType = rootType.GetGenericTypeDefinition();
2164 DataContract.ThrowInvalidDataContractException(SR.GetString(SR.TypeMustBeConcrete, type), type);
2169 private static bool IsElemTypeNullOrNotEqualToRootType(string elemTypeName, Type rootType)
2171 Type t = Type.GetType(elemTypeName, false);
2172 if (t == null || !rootType.Equals(t))
2179 private static bool IsCollectionElementTypeEqualToRootType(string collectionElementTypeName, Type rootType)
2181 if (collectionElementTypeName.StartsWith(DataContract.GetClrTypeFullName(rootType), StringComparison.Ordinal))
2183 Type t = Type.GetType(collectionElementTypeName, false);
2186 if (t.IsGenericType && !IsOpenGenericType(t))
2188 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.KnownTypeConfigClosedGenericDeclared, collectionElementTypeName)));
2190 else if (rootType.Equals(t))
2199 [Fx.Tag.SecurityNote(Critical = "Fetches the critical dataContractAdapterType.",
2200 Safe = "The critical dataContractAdapterType is only used for local comparison and is not leaked beyond this method.")]
2201 [SecurityCritical, SecurityTreatAsSafe]
2202 internal static void CheckAndAdd(Type type, Dictionary<Type, Type> typesChecked, ref DataContractDictionary nameToDataContractTable)
2204 type = DataContract.UnwrapNullableType(type);
2205 DataContract dataContract = DataContract.GetDataContract(type);
2206 DataContract alreadyExistingContract;
2207 if (nameToDataContractTable == null)
2209 nameToDataContractTable = new DataContractDictionary();
2211 else if (nameToDataContractTable.TryGetValue(dataContract.StableName, out alreadyExistingContract))
2213 if (alreadyExistingContract.UnderlyingType != DataContractCriticalHelper.GetDataContractAdapterType(type))
2214 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.DupContractInKnownTypes, type, alreadyExistingContract.UnderlyingType, dataContract.StableName.Namespace, dataContract.StableName.Name)));
2217 nameToDataContractTable.Add(dataContract.StableName, dataContract);
2218 ImportKnownTypeAttributes(type, typesChecked, ref nameToDataContractTable);
2221 static bool IsOpenGenericType(Type t)
2223 Type[] args = t.GetGenericArguments();
2224 for (int i = 0; i < args.Length; ++i)
2225 if (!args[i].IsGenericParameter)
2231 public sealed override bool Equals(object other)
2233 if ((object)this == other)
2235 return Equals(other, new Dictionary<DataContractPairKey, object>());
2238 internal virtual bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
2240 DataContract dataContract = other as DataContract;
2241 if (dataContract != null)
2243 return (StableName.Name == dataContract.StableName.Name && StableName.Namespace == dataContract.StableName.Namespace && IsReference == dataContract.IsReference);
2248 internal bool IsEqualOrChecked(object other, Dictionary<DataContractPairKey, object> checkedContracts)
2250 if ((object)this == other)
2253 if (checkedContracts != null)
2255 DataContractPairKey contractPairKey = new DataContractPairKey(this, other);
2256 if (checkedContracts.ContainsKey(contractPairKey))
2258 checkedContracts.Add(contractPairKey, null);
2263 public override int GetHashCode()
2265 return base.GetHashCode();
2268 internal void ThrowInvalidDataContractException(string message)
2270 ThrowInvalidDataContractException(message, UnderlyingType);
2272 #if NO_DYNAMIC_CODEGEN
2273 static internal bool IsTypeVisible(Type t)
2278 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks type visibility to calculate if access to it requires MemberAccessPermission."
2279 + " Since this information is used to determine whether to give the generated code access"
2280 + " permissions to private members, any changes to the logic should be reviewed.")]
2281 static internal bool IsTypeVisible(Type t)
2283 // Generic parameters are always considered visible.
2284 if (t.IsGenericParameter)
2289 // The normal Type.IsVisible check requires all nested types to be IsNestedPublic.
2290 // This does not comply with our convention where they can also have InternalsVisibleTo
2291 // with our assembly. The following method performs a recursive walk back the declaring
2292 // type hierarchy to perform this enhanced IsVisible check.
2293 if (!IsTypeAndDeclaringTypeVisible(t))
2298 // All generic argument types must also be visible.
2299 // Nested types perform this test recursively for all their declaring types.
2300 foreach (Type genericType in t.GetGenericArguments())
2302 if (!IsTypeVisible(genericType))
2311 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks type visibility to calculate if access to it requires MemberAccessPermission."
2312 + " Since this information is used to determine whether to give the generated code access"
2313 + " permissions to private members, any changes to the logic should be reviewed.")]
2314 static internal bool IsTypeAndDeclaringTypeVisible(Type t)
2316 // Arrays, etc. must consider the underlying element type because the
2317 // non-element type does not reflect the same type nesting. For example,
2318 // MyClass[] would not show as a nested type, even when MyClass is nested.
2319 if (t.HasElementType)
2321 return IsTypeVisible(t.GetElementType());
2324 // Nested types are not visible unless their declaring type is visible.
2325 // Additionally, they must be either IsNestedPublic or in an assembly with InternalsVisibleTo this current assembly.
2326 // Non-nested types must be public or have this same InternalsVisibleTo relation.
2328 ? (t.IsNestedPublic || IsTypeVisibleInSerializationModule(t)) && IsTypeVisible(t.DeclaringType)
2329 : t.IsPublic || IsTypeVisibleInSerializationModule(t);
2332 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks constructor visibility to calculate if access to it requires MemberAccessPermission."
2333 + " note: does local check for visibility, assuming that the declaring Type visibility has been checked."
2334 + " Since this information is used to determine whether to give the generated code access"
2335 + " permissions to private members, any changes to the logic should be reviewed.")]
2336 static internal bool ConstructorRequiresMemberAccess(ConstructorInfo ctor)
2338 return ctor != null && !ctor.IsPublic && !IsMemberVisibleInSerializationModule(ctor);
2341 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks method visibility to calculate if access to it requires MemberAccessPermission."
2342 + " note: does local check for visibility, assuming that the declaring Type visibility has been checked."
2343 + " Since this information is used to determine whether to give the generated code access"
2344 + " permissions to private members, any changes to the logic should be reviewed.")]
2345 static internal bool MethodRequiresMemberAccess(MethodInfo method)
2347 return method != null && !method.IsPublic && !IsMemberVisibleInSerializationModule(method);
2350 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks field visibility to calculate if access to it requires MemberAccessPermission."
2351 + " note: does local check for visibility, assuming that the declaring Type visibility has been checked."
2352 + " Since this information is used to determine whether to give the generated code access"
2353 + " permissions to private members, any changes to the logic should be reviewed.")]
2354 static internal bool FieldRequiresMemberAccess(FieldInfo field)
2356 return field != null && !field.IsPublic && !IsMemberVisibleInSerializationModule(field);
2359 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks type visibility to calculate if access to it requires MemberAccessPermission."
2360 + " note: does local check for visibility, assuming that the declaring Type visibility has been checked."
2361 + " Since this information is used to determine whether to give the generated code access"
2362 + " permissions to private members, any changes to the logic should be reviewed.")]
2363 static bool IsTypeVisibleInSerializationModule(Type type)
2365 return (type.Module.Equals(typeof(CodeGenerator).Module) || IsAssemblyFriendOfSerialization(type.Assembly)) && !type.IsNestedPrivate;
2368 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks member visibility to calculate if access to it requires MemberAccessPermission."
2369 + " note: does local check for visibility, assuming that the declaring Type visibility has been checked."
2370 + " Since this information is used to determine whether to give the generated code access"
2371 + " permissions to private members, any changes to the logic should be reviewed.")]
2372 static bool IsMemberVisibleInSerializationModule(MemberInfo member)
2374 if (!IsTypeVisibleInSerializationModule(member.DeclaringType))
2377 if (member is MethodInfo)
2379 MethodInfo method = (MethodInfo)member;
2380 return (method.IsAssembly || method.IsFamilyOrAssembly);
2382 else if (member is FieldInfo)
2384 FieldInfo field = (FieldInfo)member;
2385 return (field.IsAssembly || field.IsFamilyOrAssembly) && IsTypeVisible(field.FieldType);
2387 else if (member is ConstructorInfo)
2389 ConstructorInfo constructor = (ConstructorInfo)member;
2390 return (constructor.IsAssembly || constructor.IsFamilyOrAssembly);
2396 [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - checks member visibility to calculate if access to it requires MemberAccessPermission."
2397 + " Since this information is used to determine whether to give the generated code access"
2398 + " permissions to private members, any changes to the logic should be reviewed.")]
2399 internal static bool IsAssemblyFriendOfSerialization(Assembly assembly)
2401 InternalsVisibleToAttribute[] internalsVisibleAttributes = (InternalsVisibleToAttribute[])assembly.GetCustomAttributes(typeof(InternalsVisibleToAttribute), false);
2402 foreach (InternalsVisibleToAttribute internalsVisibleAttribute in internalsVisibleAttributes)
2404 string internalsVisibleAttributeAssemblyName = internalsVisibleAttribute.AssemblyName;
2406 if (Regex.IsMatch(internalsVisibleAttributeAssemblyName, Globals.SimpleSRSInternalsVisiblePattern) ||
2407 Regex.IsMatch(internalsVisibleAttributeAssemblyName, Globals.FullSRSInternalsVisiblePattern))
2417 interface IGenericNameProvider
2419 int GetParameterCount();
2420 IList<int> GetNestedParameterCounts();
2421 string GetParameterName(int paramIndex);
2422 string GetNamespaces();
2423 string GetGenericTypeName();
2424 bool ParametersFromBuiltInNamespaces { get; }
2427 class GenericNameProvider : IGenericNameProvider
2429 string genericTypeName;
2430 object[] genericParams; //Type or DataContract
2431 IList<int> nestedParamCounts;
2432 internal GenericNameProvider(Type type)
2433 : this(DataContract.GetClrTypeFullName(type.GetGenericTypeDefinition()), type.GetGenericArguments())
2437 internal GenericNameProvider(string genericTypeName, object[] genericParams)
2439 this.genericTypeName = genericTypeName;
2440 this.genericParams = new object[genericParams.Length];
2441 genericParams.CopyTo(this.genericParams, 0);
2444 DataContract.GetClrNameAndNamespace(genericTypeName, out name, out ns);
2445 this.nestedParamCounts = DataContract.GetDataContractNameForGenericName(name, null);
2448 public int GetParameterCount()
2450 return genericParams.Length;
2453 public IList<int> GetNestedParameterCounts()
2455 return nestedParamCounts;
2458 public string GetParameterName(int paramIndex)
2460 return GetStableName(paramIndex).Name;
2463 public string GetNamespaces()
2465 StringBuilder namespaces = new StringBuilder();
2466 for (int j = 0; j < GetParameterCount(); j++)
2467 namespaces.Append(" ").Append(GetStableName(j).Namespace);
2468 return namespaces.ToString();
2471 public string GetGenericTypeName()
2473 return genericTypeName;
2476 public bool ParametersFromBuiltInNamespaces
2480 bool parametersFromBuiltInNamespaces = true;
2481 for (int j = 0; j < GetParameterCount(); j++)
2483 if (parametersFromBuiltInNamespaces)
2484 parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(GetStableName(j).Namespace);
2488 return parametersFromBuiltInNamespaces;
2492 XmlQualifiedName GetStableName(int i)
2494 object o = genericParams[i];
2495 XmlQualifiedName qname = o as XmlQualifiedName;
2498 Type paramType = o as Type;
2499 if (paramType != null)
2500 genericParams[i] = qname = DataContract.GetStableName(paramType);
2502 genericParams[i] = qname = ((DataContract)o).StableName;
2508 class GenericInfo : IGenericNameProvider
2510 string genericTypeName;
2511 XmlQualifiedName stableName;
2512 List<GenericInfo> paramGenericInfos;
2513 List<int> nestedParamCounts;
2515 internal GenericInfo(XmlQualifiedName stableName, string genericTypeName)
2517 this.stableName = stableName;
2518 this.genericTypeName = genericTypeName;
2519 this.nestedParamCounts = new List<int>();
2520 this.nestedParamCounts.Add(0);
2523 internal void Add(GenericInfo actualParamInfo)
2525 if (paramGenericInfos == null)
2526 paramGenericInfos = new List<GenericInfo>();
2527 paramGenericInfos.Add(actualParamInfo);
2530 internal void AddToLevel(int level, int count)
2532 if (level >= nestedParamCounts.Count)
2536 nestedParamCounts.Add((level == nestedParamCounts.Count) ? count : 0);
2537 } while (level >= nestedParamCounts.Count);
2540 nestedParamCounts[level] = nestedParamCounts[level] + count;
2543 internal XmlQualifiedName GetExpandedStableName()
2545 if (paramGenericInfos == null)
2547 return new XmlQualifiedName(DataContract.EncodeLocalName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(stableName.Name), this)), stableName.Namespace);
2550 internal string GetStableNamespace()
2552 return stableName.Namespace;
2555 internal XmlQualifiedName StableName
2557 get { return stableName; }
2560 internal IList<GenericInfo> Parameters
2562 get { return paramGenericInfos; }
2565 public int GetParameterCount()
2567 return paramGenericInfos.Count;
2570 public IList<int> GetNestedParameterCounts()
2572 return nestedParamCounts;
2575 public string GetParameterName(int paramIndex)
2577 return paramGenericInfos[paramIndex].GetExpandedStableName().Name;
2580 public string GetNamespaces()
2582 StringBuilder namespaces = new StringBuilder();
2583 for (int j = 0; j < paramGenericInfos.Count; j++)
2584 namespaces.Append(" ").Append(paramGenericInfos[j].GetStableNamespace());
2585 return namespaces.ToString();
2588 public string GetGenericTypeName()
2590 return genericTypeName;
2593 public bool ParametersFromBuiltInNamespaces
2597 bool parametersFromBuiltInNamespaces = true;
2598 for (int j = 0; j < paramGenericInfos.Count; j++)
2600 if (parametersFromBuiltInNamespaces)
2601 parametersFromBuiltInNamespaces = DataContract.IsBuiltInNamespace(paramGenericInfos[j].GetStableNamespace());
2605 return parametersFromBuiltInNamespaces;
2611 internal class DataContractPairKey
2616 public DataContractPairKey(object object1, object object2)
2618 this.object1 = object1;
2619 this.object2 = object2;
2622 public override bool Equals(object other)
2624 DataContractPairKey otherKey = other as DataContractPairKey;
2625 if (otherKey == null)
2627 return ((otherKey.object1 == object1 && otherKey.object2 == object2) || (otherKey.object1 == object2 && otherKey.object2 == object1));
2630 public override int GetHashCode()
2632 return object1.GetHashCode() ^ object2.GetHashCode();
2636 class TypeHandleRefEqualityComparer : IEqualityComparer<TypeHandleRef>
2638 public bool Equals(TypeHandleRef x, TypeHandleRef y)
2640 return x.Value.Equals(y.Value);
2643 public int GetHashCode(TypeHandleRef obj)
2645 return obj.Value.GetHashCode();
2651 RuntimeTypeHandle value;
2653 public TypeHandleRef()
2657 public TypeHandleRef(RuntimeTypeHandle value)
2662 public RuntimeTypeHandle Value
2679 public IntRef(int value)