1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.Runtime.Serialization
7 using System.Collections;
8 using System.Diagnostics;
9 using System.Collections.Generic;
11 using System.Globalization;
12 using System.Reflection;
13 using System.Threading;
15 using System.Runtime.Serialization.Configuration;
16 using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
17 using System.Security;
18 using System.Security.Permissions;
20 [DataContract(Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
22 public struct KeyValue<K, V>
24 internal struct KeyValue<K, V>
30 internal KeyValue(K key, V value)
36 [DataMember(IsRequired = true)]
43 [DataMember(IsRequired = true)]
47 set { this.value = value; }
51 internal enum CollectionKind : byte
66 public sealed class CollectionDataContract : DataContract
68 internal sealed class CollectionDataContract : DataContract
71 [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the XML element name for collection items."
72 + "Statically cached and used from IL generated code.")]
74 XmlDictionaryString collectionItemName;
76 [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the XML namespace for collection items."
77 + "Statically cached and used from IL generated code.")]
79 XmlDictionaryString childElementNamespace;
81 [Fx.Tag.SecurityNote(Critical = "Internal DataContract representing the contract for collection items."
82 + "Statically cached and used from IL generated code.")]
84 DataContract itemContract;
86 [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization. "
87 + "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
89 CollectionDataContractCriticalHelper helper;
91 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
92 Safe = "Doesn't leak anything.")]
93 [SecuritySafeCritical]
94 internal CollectionDataContract(CollectionKind kind)
95 : base(new CollectionDataContractCriticalHelper(kind))
97 InitCollectionDataContract(this);
100 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
101 Safe = "Doesn't leak anything.")]
102 [SecuritySafeCritical]
103 internal CollectionDataContract(Type type)
104 : base(new CollectionDataContractCriticalHelper(type))
106 InitCollectionDataContract(this);
109 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
110 Safe = "Doesn't leak anything.")]
111 [SecuritySafeCritical]
112 internal CollectionDataContract(Type type, DataContract itemContract)
113 : base(new CollectionDataContractCriticalHelper(type, itemContract))
115 InitCollectionDataContract(this);
119 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
120 Safe = "Doesn't leak anything.")]
121 [SecuritySafeCritical]
122 CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string serializationExceptionMessage, string deserializationExceptionMessage)
123 : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage))
125 InitCollectionDataContract(GetSharedTypeContract(type));
128 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
129 Safe = "Doesn't leak anything.")]
130 [SecuritySafeCritical]
131 CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor)
132 : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, addMethod, constructor))
134 InitCollectionDataContract(GetSharedTypeContract(type));
137 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
138 Safe = "Doesn't leak anything.")]
139 [SecuritySafeCritical]
140 CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor, bool isConstructorCheckRequired)
141 : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, addMethod, constructor, isConstructorCheckRequired))
143 InitCollectionDataContract(GetSharedTypeContract(type));
146 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
147 Safe = "Doesn't leak anything.")]
148 [SecuritySafeCritical]
149 CollectionDataContract(Type type, string invalidCollectionInSharedContractMessage)
150 : base(new CollectionDataContractCriticalHelper(type, invalidCollectionInSharedContractMessage))
152 InitCollectionDataContract(GetSharedTypeContract(type));
155 [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical fields; called from all constructors.")]
157 void InitCollectionDataContract(DataContract sharedTypeContract)
159 this.helper = base.Helper as CollectionDataContractCriticalHelper;
160 this.collectionItemName = helper.CollectionItemName;
161 if (helper.Kind == CollectionKind.Dictionary || helper.Kind == CollectionKind.GenericDictionary)
163 this.itemContract = helper.ItemContract;
165 this.helper.SharedTypeContract = sharedTypeContract;
168 void InitSharedTypeContract()
172 static Type[] KnownInterfaces
174 [Fx.Tag.SecurityNote(Critical = "Fetches the critical knownInterfaces property.",
175 Safe = "knownInterfaces only needs to be protected for write.")]
176 [SecuritySafeCritical]
177 get { return CollectionDataContractCriticalHelper.KnownInterfaces; }
180 internal CollectionKind Kind
182 [Fx.Tag.SecurityNote(Critical = "Fetches the critical kind property.",
183 Safe = "kind only needs to be protected for write.")]
184 [SecuritySafeCritical]
185 get { return helper.Kind; }
188 internal Type ItemType
190 [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemType property.",
191 Safe = "itemType only needs to be protected for write.")]
192 [SecuritySafeCritical]
193 get { return helper.ItemType; }
196 public DataContract ItemContract
198 [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemContract property.",
199 Safe = "itemContract only needs to be protected for write.")]
200 [SecuritySafeCritical]
201 get { return itemContract ?? helper.ItemContract; }
203 [Fx.Tag.SecurityNote(Critical = "Sets the critical itemContract property.")]
207 itemContract = value;
208 helper.ItemContract = value;
212 internal DataContract SharedTypeContract
214 [Fx.Tag.SecurityNote(Critical = "Fetches the critical sharedTypeContract property.",
215 Safe = "sharedTypeContract only needs to be protected for write.")]
216 [SecuritySafeCritical]
217 get { return helper.SharedTypeContract; }
220 internal string ItemName
222 [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemName property.",
223 Safe = "itemName only needs to be protected for write.")]
224 [SecuritySafeCritical]
225 get { return helper.ItemName; }
227 [Fx.Tag.SecurityNote(Critical = "Sets the critical itemName property.")]
229 set { helper.ItemName = value; }
232 public XmlDictionaryString CollectionItemName
234 [Fx.Tag.SecurityNote(Critical = "Fetches the critical collectionItemName property.",
235 Safe = "collectionItemName only needs to be protected for write.")]
236 [SecuritySafeCritical]
237 get { return this.collectionItemName; }
240 internal string KeyName
242 [Fx.Tag.SecurityNote(Critical = "Fetches the critical keyName property.",
243 Safe = "keyName only needs to be protected for write.")]
244 [SecuritySafeCritical]
245 get { return helper.KeyName; }
247 [Fx.Tag.SecurityNote(Critical = "Sets the critical keyName property.")]
249 set { helper.KeyName = value; }
252 internal string ValueName
254 [Fx.Tag.SecurityNote(Critical = "Fetches the critical valueName property.",
255 Safe = "valueName only needs to be protected for write.")]
256 [SecuritySafeCritical]
257 get { return helper.ValueName; }
259 [Fx.Tag.SecurityNote(Critical = "Sets the critical valueName property.")]
261 set { helper.ValueName = value; }
264 internal bool IsDictionary
266 get { return KeyName != null; }
269 public XmlDictionaryString ChildElementNamespace
271 [Fx.Tag.SecurityNote(Critical = "Fetches the critical childElementNamespace property.",
272 Safe = "childElementNamespace only needs to be protected for write; initialized in getter if null.")]
273 [SecuritySafeCritical]
276 if (this.childElementNamespace == null)
280 if (this.childElementNamespace == null)
282 if (helper.ChildElementNamespace == null && !IsDictionary)
284 XmlDictionaryString tempChildElementNamespace = ClassDataContract.GetChildNamespaceToDeclare(this, ItemType, new XmlDictionary());
285 Thread.MemoryBarrier();
286 helper.ChildElementNamespace = tempChildElementNamespace;
288 this.childElementNamespace = helper.ChildElementNamespace;
292 return childElementNamespace;
296 internal bool IsItemTypeNullable
298 [Fx.Tag.SecurityNote(Critical = "Fetches the critical isItemTypeNullable property.",
299 Safe = "isItemTypeNullable only needs to be protected for write.")]
300 [SecuritySafeCritical]
301 get { return helper.IsItemTypeNullable; }
303 [Fx.Tag.SecurityNote(Critical = "Sets the critical isItemTypeNullable property.")]
305 set { helper.IsItemTypeNullable = value; }
308 internal bool IsConstructorCheckRequired
310 [Fx.Tag.SecurityNote(Critical = "Fetches the critical isConstructorCheckRequired property.",
311 Safe = "isConstructorCheckRequired only needs to be protected for write.")]
312 [SecuritySafeCritical]
313 get { return helper.IsConstructorCheckRequired; }
315 [Fx.Tag.SecurityNote(Critical = "Sets the critical isConstructorCheckRequired property.")]
317 set { helper.IsConstructorCheckRequired = value; }
320 internal MethodInfo GetEnumeratorMethod
322 [Fx.Tag.SecurityNote(Critical = "Fetches the critical getEnumeratorMethod property.",
323 Safe = "getEnumeratorMethod only needs to be protected for write.")]
324 [SecuritySafeCritical]
325 get { return helper.GetEnumeratorMethod; }
328 internal MethodInfo AddMethod
330 [Fx.Tag.SecurityNote(Critical = "Fetches the critical addMethod property.",
331 Safe = "addMethod only needs to be protected for write.")]
332 [SecuritySafeCritical]
333 get { return helper.AddMethod; }
336 internal ConstructorInfo Constructor
338 [Fx.Tag.SecurityNote(Critical = "Fetches the critical constructor property.",
339 Safe = "constructor only needs to be protected for write.")]
340 [SecuritySafeCritical]
341 get { return helper.Constructor; }
344 internal override DataContractDictionary KnownDataContracts
346 [Fx.Tag.SecurityNote(Critical = "Fetches the critical knownDataContracts property.",
347 Safe = "knownDataContracts only needs to be protected for write.")]
348 [SecuritySafeCritical]
349 get { return helper.KnownDataContracts; }
351 [Fx.Tag.SecurityNote(Critical = "Sets the critical knownDataContracts property.")]
353 set { helper.KnownDataContracts = value; }
356 internal string InvalidCollectionInSharedContractMessage
358 [Fx.Tag.SecurityNote(Critical = "Fetches the critical invalidCollectionInSharedContractMessage property.",
359 Safe = "invalidCollectionInSharedContractMessage only needs to be protected for write.")]
360 [SecuritySafeCritical]
361 get { return helper.InvalidCollectionInSharedContractMessage; }
364 internal string SerializationExceptionMessage
366 [Fx.Tag.SecurityNote(Critical = "Fetches the critical serializationExceptionMessage property.",
367 Safe = "serializationExceptionMessage only needs to be protected for write.")]
368 [SecuritySafeCritical]
369 get { return helper.SerializationExceptionMessage; }
372 internal string DeserializationExceptionMessage
374 [Fx.Tag.SecurityNote(Critical = "Fetches the critical deserializationExceptionMessage property.",
375 Safe = "deserializationExceptionMessage only needs to be protected for write.")]
376 [SecuritySafeCritical]
377 get { return helper.DeserializationExceptionMessage; }
380 internal bool IsReadOnlyContract
382 get { return this.DeserializationExceptionMessage != null; }
385 bool ItemNameSetExplicit
387 [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemNameSetExplicit property.",
388 Safe = "itemNameSetExplicit only needs to be protected for write.")]
389 [SecuritySafeCritical]
390 get { return helper.ItemNameSetExplicit; }
393 internal XmlFormatCollectionWriterDelegate XmlFormatWriterDelegate
395 [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatWriterDelegate property.",
396 Safe = "xmlFormatWriterDelegate only needs to be protected for write; initialized in getter if null.")]
397 [SecuritySafeCritical]
400 if (helper.XmlFormatWriterDelegate == null)
404 if (helper.XmlFormatWriterDelegate == null)
406 XmlFormatCollectionWriterDelegate tempDelegate = new XmlFormatWriterGenerator().GenerateCollectionWriter(this);
407 Thread.MemoryBarrier();
408 helper.XmlFormatWriterDelegate = tempDelegate;
412 return helper.XmlFormatWriterDelegate;
416 internal XmlFormatCollectionReaderDelegate XmlFormatReaderDelegate
418 [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatReaderDelegate property.",
419 Safe = "xmlFormatReaderDelegate only needs to be protected for write; initialized in getter if null.")]
420 [SecuritySafeCritical]
423 if (helper.XmlFormatReaderDelegate == null)
427 if (helper.XmlFormatReaderDelegate == null)
429 if (this.IsReadOnlyContract)
431 ThrowInvalidDataContractException(helper.DeserializationExceptionMessage, null /*type*/);
433 XmlFormatCollectionReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateCollectionReader(this);
434 Thread.MemoryBarrier();
435 helper.XmlFormatReaderDelegate = tempDelegate;
439 return helper.XmlFormatReaderDelegate;
443 internal XmlFormatGetOnlyCollectionReaderDelegate XmlFormatGetOnlyCollectionReaderDelegate
445 [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatGetOnlyCollectionReaderDelegate property.",
446 Safe = "xmlFormatGetOnlyCollectionReaderDelegate only needs to be protected for write; initialized in getter if null.")]
447 [SecuritySafeCritical]
450 if (helper.XmlFormatGetOnlyCollectionReaderDelegate == null)
454 if (helper.XmlFormatGetOnlyCollectionReaderDelegate == null)
456 if (this.UnderlyingType.IsInterface && (this.Kind == CollectionKind.Enumerable || this.Kind == CollectionKind.Collection || this.Kind == CollectionKind.GenericEnumerable))
458 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GetOnlyCollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(this.UnderlyingType))));
460 if (this.IsReadOnlyContract)
462 ThrowInvalidDataContractException(helper.DeserializationExceptionMessage, null /*type*/);
464 Fx.Assert(this.AddMethod != null || this.Kind == CollectionKind.Array, "Add method cannot be null if the collection is being used as a get-only property");
465 XmlFormatGetOnlyCollectionReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateGetOnlyCollectionReader(this);
466 Thread.MemoryBarrier();
467 helper.XmlFormatGetOnlyCollectionReaderDelegate = tempDelegate;
471 return helper.XmlFormatGetOnlyCollectionReaderDelegate;
475 [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing collections. Since the data is cached statically, we lock down access to it.")]
476 [SecurityCritical(SecurityCriticalScope.Everything)]
477 class CollectionDataContractCriticalHelper : DataContract.DataContractCriticalHelper
479 static Type[] _knownInterfaces;
482 bool isItemTypeNullable;
484 readonly MethodInfo getEnumeratorMethod, addMethod;
485 readonly ConstructorInfo constructor;
486 readonly string serializationExceptionMessage, deserializationExceptionMessage;
487 DataContract itemContract;
488 DataContract sharedTypeContract;
489 DataContractDictionary knownDataContracts;
490 bool isKnownTypeAttributeChecked;
492 bool itemNameSetExplicit;
493 XmlDictionaryString collectionItemName;
496 XmlDictionaryString childElementNamespace;
497 string invalidCollectionInSharedContractMessage;
498 XmlFormatCollectionReaderDelegate xmlFormatReaderDelegate;
499 XmlFormatGetOnlyCollectionReaderDelegate xmlFormatGetOnlyCollectionReaderDelegate;
500 XmlFormatCollectionWriterDelegate xmlFormatWriterDelegate;
501 bool isConstructorCheckRequired = false;
503 internal static Type[] KnownInterfaces
507 if (_knownInterfaces == null)
509 // Listed in priority order
510 _knownInterfaces = new Type[]
512 Globals.TypeOfIDictionaryGeneric,
513 Globals.TypeOfIDictionary,
514 Globals.TypeOfIListGeneric,
515 Globals.TypeOfICollectionGeneric,
517 Globals.TypeOfIEnumerableGeneric,
518 Globals.TypeOfICollection,
519 Globals.TypeOfIEnumerable
522 return _knownInterfaces;
526 void Init(CollectionKind kind, Type itemType, CollectionDataContractAttribute collectionContractAttribute)
529 if (itemType != null)
531 this.itemType = itemType;
532 this.isItemTypeNullable = DataContract.IsTypeNullable(itemType);
534 bool isDictionary = (kind == CollectionKind.Dictionary || kind == CollectionKind.GenericDictionary);
535 string itemName = null, keyName = null, valueName = null;
536 if (collectionContractAttribute != null)
538 if (collectionContractAttribute.IsItemNameSetExplicit)
540 if (collectionContractAttribute.ItemName == null || collectionContractAttribute.ItemName.Length == 0)
541 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractItemName, DataContract.GetClrTypeFullName(UnderlyingType))));
542 itemName = DataContract.EncodeLocalName(collectionContractAttribute.ItemName);
543 itemNameSetExplicit = true;
545 if (collectionContractAttribute.IsKeyNameSetExplicit)
547 if (collectionContractAttribute.KeyName == null || collectionContractAttribute.KeyName.Length == 0)
548 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractKeyName, DataContract.GetClrTypeFullName(UnderlyingType))));
550 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractKeyNoDictionary, DataContract.GetClrTypeFullName(UnderlyingType), collectionContractAttribute.KeyName)));
551 keyName = DataContract.EncodeLocalName(collectionContractAttribute.KeyName);
553 if (collectionContractAttribute.IsValueNameSetExplicit)
555 if (collectionContractAttribute.ValueName == null || collectionContractAttribute.ValueName.Length == 0)
556 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractValueName, DataContract.GetClrTypeFullName(UnderlyingType))));
558 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractValueNoDictionary, DataContract.GetClrTypeFullName(UnderlyingType), collectionContractAttribute.ValueName)));
559 valueName = DataContract.EncodeLocalName(collectionContractAttribute.ValueName);
563 XmlDictionary dictionary = isDictionary ? new XmlDictionary(5) : new XmlDictionary(3);
564 this.Name = dictionary.Add(this.StableName.Name);
565 this.Namespace = dictionary.Add(this.StableName.Namespace);
566 this.itemName = itemName ?? DataContract.GetStableName(DataContract.UnwrapNullableType(itemType)).Name;
567 this.collectionItemName = dictionary.Add(this.itemName);
570 this.keyName = keyName ?? Globals.KeyLocalName;
571 this.valueName = valueName ?? Globals.ValueLocalName;
574 if (collectionContractAttribute != null)
576 this.IsReference = collectionContractAttribute.IsReference;
580 internal CollectionDataContractCriticalHelper(CollectionKind kind)
583 Init(kind, null, null);
587 internal CollectionDataContractCriticalHelper(Type type)
590 if (type == Globals.TypeOfArray)
591 type = Globals.TypeOfObjectArray;
592 if (type.GetArrayRank() > 1)
593 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SupportForMultidimensionalArraysNotPresent)));
594 this.StableName = DataContract.GetStableName(type);
595 Init(CollectionKind.Array, type.GetElementType(), null);
599 internal CollectionDataContractCriticalHelper(Type type, DataContract itemContract)
602 if (type.GetArrayRank() > 1)
603 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SupportForMultidimensionalArraysNotPresent)));
604 this.StableName = CreateQualifiedName(Globals.ArrayPrefix + itemContract.StableName.Name, itemContract.StableName.Namespace);
605 this.itemContract = itemContract;
606 Init(CollectionKind.Array, type.GetElementType(), null);
609 // read-only collection
610 internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string serializationExceptionMessage, string deserializationExceptionMessage)
613 if (getEnumeratorMethod == null)
614 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveGetEnumeratorMethod, DataContract.GetClrTypeFullName(type))));
615 if (itemType == null)
616 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveItemType, DataContract.GetClrTypeFullName(type))));
618 CollectionDataContractAttribute collectionContractAttribute;
619 this.StableName = DataContract.GetCollectionStableName(type, itemType, out collectionContractAttribute);
621 Init(kind, itemType, collectionContractAttribute);
622 this.getEnumeratorMethod = getEnumeratorMethod;
623 this.serializationExceptionMessage = serializationExceptionMessage;
624 this.deserializationExceptionMessage = deserializationExceptionMessage;
628 internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor)
629 : this(type, kind, itemType, getEnumeratorMethod, (string)null, (string)null)
631 if (addMethod == null && !type.IsInterface)
632 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(type))));
633 this.addMethod = addMethod;
634 this.constructor = constructor;
638 internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor, bool isConstructorCheckRequired)
639 : this(type, kind, itemType, getEnumeratorMethod, addMethod, constructor)
641 this.isConstructorCheckRequired = isConstructorCheckRequired;
644 internal CollectionDataContractCriticalHelper(Type type, string invalidCollectionInSharedContractMessage)
647 Init(CollectionKind.Collection, null /*itemType*/, null);
648 this.invalidCollectionInSharedContractMessage = invalidCollectionInSharedContractMessage;
651 internal CollectionKind Kind
656 internal Type ItemType
658 get { return itemType; }
661 internal DataContract ItemContract
665 if (itemContract == null && UnderlyingType != null)
669 if (String.CompareOrdinal(KeyName, ValueName) == 0)
671 DataContract.ThrowInvalidDataContractException(
672 SR.GetString(SR.DupKeyValueName, DataContract.GetClrTypeFullName(UnderlyingType), KeyName),
675 itemContract = ClassDataContract.CreateClassDataContractForKeyValue(ItemType, Namespace, new string[] { KeyName, ValueName });
676 // Ensure that DataContract gets added to the static DataContract cache for dictionary items
677 DataContract.GetDataContract(ItemType);
681 itemContract = DataContract.GetDataContract(ItemType);
688 itemContract = value;
692 internal DataContract SharedTypeContract
694 get { return sharedTypeContract; }
695 set { sharedTypeContract = value; }
698 internal string ItemName
700 get { return itemName; }
701 set { itemName = value; }
704 internal bool IsConstructorCheckRequired
706 get { return isConstructorCheckRequired; }
707 set { isConstructorCheckRequired = value; }
710 public XmlDictionaryString CollectionItemName
712 get { return collectionItemName; }
715 internal string KeyName
717 get { return keyName; }
718 set { keyName = value; }
721 internal string ValueName
723 get { return valueName; }
724 set { valueName = value; }
727 internal bool IsDictionary
729 get { return KeyName != null; }
732 public string SerializationExceptionMessage
734 get { return serializationExceptionMessage; }
737 public string DeserializationExceptionMessage
739 get { return deserializationExceptionMessage; }
742 public XmlDictionaryString ChildElementNamespace
744 get { return childElementNamespace; }
745 set { childElementNamespace = value; }
748 internal bool IsItemTypeNullable
750 get { return isItemTypeNullable; }
751 set { isItemTypeNullable = value; }
754 internal MethodInfo GetEnumeratorMethod
756 get { return getEnumeratorMethod; }
759 internal MethodInfo AddMethod
761 get { return addMethod; }
764 internal ConstructorInfo Constructor
766 get { return constructor; }
769 internal override DataContractDictionary KnownDataContracts
773 if (!isKnownTypeAttributeChecked && UnderlyingType != null)
777 if (!isKnownTypeAttributeChecked)
779 knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
780 Thread.MemoryBarrier();
781 isKnownTypeAttributeChecked = true;
785 return knownDataContracts;
787 set { knownDataContracts = value; }
790 internal string InvalidCollectionInSharedContractMessage
792 get { return invalidCollectionInSharedContractMessage; }
795 internal bool ItemNameSetExplicit
797 get { return itemNameSetExplicit; }
800 internal XmlFormatCollectionWriterDelegate XmlFormatWriterDelegate
802 get { return xmlFormatWriterDelegate; }
803 set { xmlFormatWriterDelegate = value; }
806 internal XmlFormatCollectionReaderDelegate XmlFormatReaderDelegate
808 get { return xmlFormatReaderDelegate; }
809 set { xmlFormatReaderDelegate = value; }
812 internal XmlFormatGetOnlyCollectionReaderDelegate XmlFormatGetOnlyCollectionReaderDelegate
814 get { return xmlFormatGetOnlyCollectionReaderDelegate; }
815 set { xmlFormatGetOnlyCollectionReaderDelegate = value; }
819 DataContract GetSharedTypeContract(Type type)
821 if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false))
825 // ClassDataContract.IsNonAttributedTypeValidForSerialization does not need to be called here. It should
826 // never pass because it returns false for types that implement any of CollectionDataContract.KnownInterfaces
827 if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false))
829 return new ClassDataContract(type);
834 internal static bool IsCollectionInterface(Type type)
836 if (type.IsGenericType)
837 type = type.GetGenericTypeDefinition();
838 return ((IList<Type>)KnownInterfaces).Contains(type);
841 internal static bool IsCollection(Type type)
844 return IsCollection(type, out itemType);
847 internal static bool IsCollection(Type type, out Type itemType)
849 return IsCollectionHelper(type, out itemType, true /*constructorRequired*/);
852 internal static bool IsCollection(Type type, bool constructorRequired, bool skipIfReadOnlyContract)
855 return IsCollectionHelper(type, out itemType, constructorRequired, skipIfReadOnlyContract);
858 static bool IsCollectionHelper(Type type, out Type itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
860 if (type.IsArray && DataContract.GetBuiltInDataContract(type) == null)
862 itemType = type.GetElementType();
865 DataContract dataContract;
866 return IsCollectionOrTryCreate(type, false /*tryCreate*/, out dataContract, out itemType, constructorRequired, skipIfReadOnlyContract);
869 internal static bool TryCreate(Type type, out DataContract dataContract)
872 return IsCollectionOrTryCreate(type, true /*tryCreate*/, out dataContract, out itemType, true /*constructorRequired*/);
875 internal static bool TryCreateGetOnlyCollectionDataContract(Type type, out DataContract dataContract)
880 dataContract = new CollectionDataContract(type);
885 return IsCollectionOrTryCreate(type, true /*tryCreate*/, out dataContract, out itemType, false /*constructorRequired*/);
889 internal static MethodInfo GetTargetMethodWithName(string name, Type type, Type interfaceType)
891 InterfaceMapping mapping = type.GetInterfaceMap(interfaceType);
892 for (int i = 0; i < mapping.TargetMethods.Length; i++)
894 if (mapping.InterfaceMethods[i].Name == name)
895 return mapping.InterfaceMethods[i];
900 static bool IsArraySegment(Type t)
902 return t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(ArraySegment<>));
905 [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.Globalization, FxCop.Rule.DoNotPassLiteralsAsLocalizedParameters, Justification = "Private code.")]
906 static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataContract dataContract, out Type itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
909 itemType = Globals.TypeOfObject;
911 if (DataContract.GetBuiltInDataContract(type) != null)
913 return HandleIfInvalidCollection(type, tryCreate, false/*hasCollectionDataContract*/, false/*isBaseTypeCollection*/,
914 SR.CollectionTypeCannotBeBuiltIn, null, ref dataContract);
916 MethodInfo addMethod, getEnumeratorMethod;
917 bool hasCollectionDataContract = IsCollectionDataContract(type);
918 bool isReadOnlyContract = false;
919 string serializationExceptionMessage = null, deserializationExceptionMessage = null;
920 Type baseType = type.BaseType;
921 bool isBaseTypeCollection = (baseType != null && baseType != Globals.TypeOfObject
922 && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri) ? IsCollection(baseType) : false;
924 // Avoid creating an invalid collection contract for Serializable types since we can create a ClassDataContract instead
925 bool createContractWithException = isBaseTypeCollection && !type.IsSerializable;
927 if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
929 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
930 SR.CollectionTypeCannotHaveDataContract, null, ref dataContract);
933 if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type) || IsArraySegment(type))
938 if (!Globals.TypeOfIEnumerable.IsAssignableFrom(type))
940 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
941 SR.CollectionTypeIsNotIEnumerable, null, ref dataContract);
943 if (type.IsInterface)
945 Type interfaceTypeToCheck = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
946 Type[] knownInterfaces = KnownInterfaces;
947 for (int i = 0; i < knownInterfaces.Length; i++)
949 if (knownInterfaces[i] == interfaceTypeToCheck)
952 if (type.IsGenericType)
954 Type[] genericArgs = type.GetGenericArguments();
955 if (interfaceTypeToCheck == Globals.TypeOfIDictionaryGeneric)
957 itemType = Globals.TypeOfKeyValue.MakeGenericType(genericArgs);
958 addMethod = type.GetMethod(Globals.AddMethodName);
959 getEnumeratorMethod = Globals.TypeOfIEnumerableGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(genericArgs)).GetMethod(Globals.GetEnumeratorMethodName);
963 itemType = genericArgs[0];
964 if (interfaceTypeToCheck == Globals.TypeOfICollectionGeneric || interfaceTypeToCheck == Globals.TypeOfIListGeneric)
966 addMethod = Globals.TypeOfICollectionGeneric.MakeGenericType(itemType).GetMethod(Globals.AddMethodName);
968 getEnumeratorMethod = Globals.TypeOfIEnumerableGeneric.MakeGenericType(itemType).GetMethod(Globals.GetEnumeratorMethodName);
973 if (interfaceTypeToCheck == Globals.TypeOfIDictionary)
975 itemType = typeof(KeyValue<object, object>);
976 addMethod = type.GetMethod(Globals.AddMethodName);
980 itemType = Globals.TypeOfObject;
981 if (interfaceTypeToCheck == Globals.TypeOfIList)
983 addMethod = Globals.TypeOfIList.GetMethod(Globals.AddMethodName);
986 getEnumeratorMethod = Globals.TypeOfIEnumerable.GetMethod(Globals.GetEnumeratorMethodName);
989 dataContract = new CollectionDataContract(type, (CollectionKind)(i + 1), itemType, getEnumeratorMethod, addMethod, null/*defaultCtor*/);
994 ConstructorInfo defaultCtor = null;
995 if (!type.IsValueType)
997 defaultCtor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Globals.EmptyTypeArray, null);
998 if (defaultCtor == null && constructorRequired)
1000 // All collection types could be considered read-only collections except collection types that are marked [Serializable].
1001 // Collection types marked [Serializable] cannot be read-only collections for backward compatibility reasons.
1002 // DataContract types and POCO types cannot be collection types, so they don't need to be factored in
1003 if (type.IsSerializable)
1005 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
1006 SR.CollectionTypeDoesNotHaveDefaultCtor, null, ref dataContract);
1010 isReadOnlyContract = true;
1011 GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveDefaultCtor, null, out serializationExceptionMessage, out deserializationExceptionMessage);
1016 Type knownInterfaceType = null;
1017 CollectionKind kind = CollectionKind.None;
1018 bool multipleDefinitions = false;
1019 Type[] interfaceTypes = type.GetInterfaces();
1020 foreach (Type interfaceType in interfaceTypes)
1022 Type interfaceTypeToCheck = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType;
1023 Type[] knownInterfaces = KnownInterfaces;
1024 for (int i = 0; i < knownInterfaces.Length; i++)
1026 if (knownInterfaces[i] == interfaceTypeToCheck)
1028 CollectionKind currentKind = (CollectionKind)(i + 1);
1029 if (kind == CollectionKind.None || currentKind < kind)
1032 knownInterfaceType = interfaceType;
1033 multipleDefinitions = false;
1035 else if ((kind & currentKind) == currentKind)
1036 multipleDefinitions = true;
1042 if (kind == CollectionKind.None)
1044 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
1045 SR.CollectionTypeIsNotIEnumerable, null, ref dataContract);
1048 if (kind == CollectionKind.Enumerable || kind == CollectionKind.Collection || kind == CollectionKind.GenericEnumerable)
1050 if (multipleDefinitions)
1051 knownInterfaceType = Globals.TypeOfIEnumerable;
1052 itemType = knownInterfaceType.IsGenericType ? knownInterfaceType.GetGenericArguments()[0] : Globals.TypeOfObject;
1053 GetCollectionMethods(type, knownInterfaceType, new Type[] { itemType },
1054 false /*addMethodOnInterface*/,
1055 out getEnumeratorMethod, out addMethod);
1056 if (addMethod == null)
1058 // All collection types could be considered read-only collections except collection types that are marked [Serializable].
1059 // Collection types marked [Serializable] cannot be read-only collections for backward compatibility reasons.
1060 // DataContract types and POCO types cannot be collection types, so they don't need to be factored in.
1061 if (type.IsSerializable || skipIfReadOnlyContract)
1063 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException && !skipIfReadOnlyContract,
1064 SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), ref dataContract);
1068 isReadOnlyContract = true;
1069 GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), out serializationExceptionMessage, out deserializationExceptionMessage);
1075 dataContract = isReadOnlyContract ?
1076 new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
1077 new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
1082 if (multipleDefinitions)
1084 return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
1085 SR.CollectionTypeHasMultipleDefinitionsOfInterface, KnownInterfaces[(int)kind - 1].Name, ref dataContract);
1087 Type[] addMethodTypeArray = null;
1090 case CollectionKind.GenericDictionary:
1091 addMethodTypeArray = knownInterfaceType.GetGenericArguments();
1092 bool isOpenGeneric = knownInterfaceType.IsGenericTypeDefinition
1093 || (addMethodTypeArray[0].IsGenericParameter && addMethodTypeArray[1].IsGenericParameter);
1094 itemType = isOpenGeneric ? Globals.TypeOfKeyValue : Globals.TypeOfKeyValue.MakeGenericType(addMethodTypeArray);
1096 case CollectionKind.Dictionary:
1097 addMethodTypeArray = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
1098 itemType = Globals.TypeOfKeyValue.MakeGenericType(addMethodTypeArray);
1100 case CollectionKind.GenericList:
1101 case CollectionKind.GenericCollection:
1102 addMethodTypeArray = knownInterfaceType.GetGenericArguments();
1103 itemType = addMethodTypeArray[0];
1105 case CollectionKind.List:
1106 itemType = Globals.TypeOfObject;
1107 addMethodTypeArray = new Type[] { itemType };
1113 GetCollectionMethods(type, knownInterfaceType, addMethodTypeArray,
1114 true /*addMethodOnInterface*/,
1115 out getEnumeratorMethod, out addMethod);
1116 dataContract = isReadOnlyContract ?
1117 new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
1118 new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
1122 return !(isReadOnlyContract && skipIfReadOnlyContract);
1125 internal static bool IsCollectionDataContract(Type type)
1127 return type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false);
1130 static bool HandleIfInvalidCollection(Type type, bool tryCreate, bool hasCollectionDataContract, bool createContractWithException, string message, string param, ref DataContract dataContract)
1132 if (hasCollectionDataContract)
1135 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(GetInvalidCollectionMessage(message, SR.GetString(SR.InvalidCollectionDataContract, DataContract.GetClrTypeFullName(type)), param)));
1139 if (createContractWithException)
1142 dataContract = new CollectionDataContract(type, GetInvalidCollectionMessage(message, SR.GetString(SR.InvalidCollectionType, DataContract.GetClrTypeFullName(type)), param));
1149 static void GetReadOnlyCollectionExceptionMessages(Type type, bool hasCollectionDataContract, string message, string param, out string serializationExceptionMessage, out string deserializationExceptionMessage)
1151 serializationExceptionMessage = GetInvalidCollectionMessage(message, SR.GetString(hasCollectionDataContract ? SR.InvalidCollectionDataContract : SR.InvalidCollectionType, DataContract.GetClrTypeFullName(type)), param);
1152 deserializationExceptionMessage = GetInvalidCollectionMessage(message, SR.GetString(SR.ReadOnlyCollectionDeserialization, DataContract.GetClrTypeFullName(type)), param);
1155 static string GetInvalidCollectionMessage(string message, string nestedMessage, string param)
1157 return (param == null) ? SR.GetString(message, nestedMessage) : SR.GetString(message, nestedMessage, param);
1160 static void FindCollectionMethodsOnInterface(Type type, Type interfaceType, ref MethodInfo addMethod, ref MethodInfo getEnumeratorMethod)
1162 InterfaceMapping mapping = type.GetInterfaceMap(interfaceType);
1163 for (int i = 0; i < mapping.TargetMethods.Length; i++)
1165 if (mapping.InterfaceMethods[i].Name == Globals.AddMethodName)
1166 addMethod = mapping.InterfaceMethods[i];
1167 else if (mapping.InterfaceMethods[i].Name == Globals.GetEnumeratorMethodName)
1168 getEnumeratorMethod = mapping.InterfaceMethods[i];
1172 static void GetCollectionMethods(Type type, Type interfaceType, Type[] addMethodTypeArray, bool addMethodOnInterface, out MethodInfo getEnumeratorMethod, out MethodInfo addMethod)
1174 addMethod = getEnumeratorMethod = null;
1176 if (addMethodOnInterface)
1178 addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public, null, addMethodTypeArray, null);
1179 if (addMethod == null || addMethod.GetParameters()[0].ParameterType != addMethodTypeArray[0])
1181 FindCollectionMethodsOnInterface(type, interfaceType, ref addMethod, ref getEnumeratorMethod);
1182 if (addMethod == null)
1184 Type[] parentInterfaceTypes = interfaceType.GetInterfaces();
1185 foreach (Type parentInterfaceType in parentInterfaceTypes)
1187 if (IsKnownInterface(parentInterfaceType))
1189 FindCollectionMethodsOnInterface(type, parentInterfaceType, ref addMethod, ref getEnumeratorMethod);
1190 if (addMethod == null)
1201 // GetMethod returns Add() method with parameter closest matching T in assignability/inheritance chain
1202 addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, addMethodTypeArray, null);
1205 if (getEnumeratorMethod == null)
1207 getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
1208 if (getEnumeratorMethod == null || !Globals.TypeOfIEnumerator.IsAssignableFrom(getEnumeratorMethod.ReturnType))
1210 Type ienumerableInterface = interfaceType.GetInterface("System.Collections.Generic.IEnumerable*");
1211 if (ienumerableInterface == null)
1212 ienumerableInterface = Globals.TypeOfIEnumerable;
1213 getEnumeratorMethod = GetTargetMethodWithName(Globals.GetEnumeratorMethodName, type, ienumerableInterface);
1218 static bool IsKnownInterface(Type type)
1220 Type typeToCheck = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
1221 foreach (Type knownInterfaceType in KnownInterfaces)
1223 if (typeToCheck == knownInterfaceType)
1231 [Fx.Tag.SecurityNote(Critical = "Sets critical properties on CollectionDataContract .",
1232 Safe = "Called during schema import/code generation.")]
1233 [SecuritySafeCritical]
1234 internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
1236 DataContract boundContract;
1237 if (boundContracts.TryGetValue(this, out boundContract))
1238 return boundContract;
1240 CollectionDataContract boundCollectionContract = new CollectionDataContract(Kind);
1241 boundContracts.Add(this, boundCollectionContract);
1242 boundCollectionContract.ItemContract = this.ItemContract.BindGenericParameters(paramContracts, boundContracts);
1243 boundCollectionContract.IsItemTypeNullable = !boundCollectionContract.ItemContract.IsValueType;
1244 boundCollectionContract.ItemName = ItemNameSetExplicit ? this.ItemName : boundCollectionContract.ItemContract.StableName.Name;
1245 boundCollectionContract.KeyName = this.KeyName;
1246 boundCollectionContract.ValueName = this.ValueName;
1247 boundCollectionContract.StableName = CreateQualifiedName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(this.StableName.Name), new GenericNameProvider(DataContract.GetClrTypeFullName(this.UnderlyingType), paramContracts)),
1248 IsCollectionDataContract(UnderlyingType) ? this.StableName.Namespace : DataContract.GetCollectionNamespace(boundCollectionContract.ItemContract.StableName.Namespace));
1249 return boundCollectionContract;
1252 internal override DataContract GetValidContract(SerializationMode mode)
1254 if (mode == SerializationMode.SharedType)
1256 if (SharedTypeContract == null)
1257 DataContract.ThrowTypeNotSerializable(UnderlyingType);
1258 return SharedTypeContract;
1265 void ThrowIfInvalid()
1267 if (InvalidCollectionInSharedContractMessage != null)
1268 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(InvalidCollectionInSharedContractMessage));
1271 internal override DataContract GetValidContract()
1273 if (this.IsConstructorCheckRequired)
1280 [Fx.Tag.SecurityNote(Critical = "Sets the critical IsConstructorCheckRequired property on CollectionDataContract.",
1281 Safe = "Does not leak anything.")]
1282 [SecuritySafeCritical]
1283 void CheckConstructor()
1285 if (this.Constructor == null)
1287 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionTypeDoesNotHaveDefaultCtor, DataContract.GetClrTypeFullName(this.UnderlyingType))));
1291 this.IsConstructorCheckRequired = false;
1295 internal override bool IsValidContract(SerializationMode mode)
1297 if (mode == SerializationMode.SharedType)
1298 return (SharedTypeContract != null);
1299 return (InvalidCollectionInSharedContractMessage == null);
1302 [Fx.Tag.SecurityNote(Miscellaneous =
1303 "RequiresReview - Calculates whether this collection requires MemberAccessPermission for deserialization."
1304 + " Since this information is used to determine whether to give the generated code access"
1305 + " permissions to private members, any changes to the logic should be reviewed.")]
1306 internal bool RequiresMemberAccessForRead(SecurityException securityException)
1308 if (!IsTypeVisible(UnderlyingType))
1310 if (securityException != null)
1312 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1313 new SecurityException(SR.GetString(
1314 SR.PartialTrustCollectionContractTypeNotPublic,
1315 DataContract.GetClrTypeFullName(UnderlyingType)),
1316 securityException));
1320 if (ItemType != null && !IsTypeVisible(ItemType))
1322 if (securityException != null)
1324 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1325 new SecurityException(SR.GetString(
1326 SR.PartialTrustCollectionContractTypeNotPublic,
1327 DataContract.GetClrTypeFullName(ItemType)),
1328 securityException));
1332 if (ConstructorRequiresMemberAccess(Constructor))
1334 if (securityException != null)
1336 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1337 new SecurityException(SR.GetString(
1338 SR.PartialTrustCollectionContractNoPublicConstructor,
1339 DataContract.GetClrTypeFullName(UnderlyingType)),
1340 securityException));
1344 if (MethodRequiresMemberAccess(this.AddMethod))
1346 if (securityException != null)
1348 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1349 new SecurityException(SR.GetString(
1350 SR.PartialTrustCollectionContractAddMethodNotPublic,
1351 DataContract.GetClrTypeFullName(UnderlyingType),
1352 this.AddMethod.Name),
1353 securityException));
1361 [Fx.Tag.SecurityNote(Miscellaneous =
1362 "RequiresReview - Calculates whether this collection requires MemberAccessPermission for serialization."
1363 + " Since this information is used to determine whether to give the generated code access"
1364 + " permissions to private members, any changes to the logic should be reviewed.")]
1365 internal bool RequiresMemberAccessForWrite(SecurityException securityException)
1367 if (!IsTypeVisible(UnderlyingType))
1369 if (securityException != null)
1371 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1372 new SecurityException(SR.GetString(
1373 SR.PartialTrustCollectionContractTypeNotPublic,
1374 DataContract.GetClrTypeFullName(UnderlyingType)),
1375 securityException));
1379 if (ItemType != null && !IsTypeVisible(ItemType))
1381 if (securityException != null)
1383 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1384 new SecurityException(SR.GetString(
1385 SR.PartialTrustCollectionContractTypeNotPublic,
1386 DataContract.GetClrTypeFullName(ItemType)),
1387 securityException));
1395 internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
1397 if (IsEqualOrChecked(other, checkedContracts))
1400 if (base.Equals(other, checkedContracts))
1402 CollectionDataContract dataContract = other as CollectionDataContract;
1403 if (dataContract != null)
1405 bool thisItemTypeIsNullable = (ItemContract == null) ? false : !ItemContract.IsValueType;
1406 bool otherItemTypeIsNullable = (dataContract.ItemContract == null) ? false : !dataContract.ItemContract.IsValueType;
1407 return ItemName == dataContract.ItemName &&
1408 (IsItemTypeNullable || thisItemTypeIsNullable) == (dataContract.IsItemTypeNullable || otherItemTypeIsNullable) &&
1409 ItemContract.Equals(dataContract.ItemContract, checkedContracts);
1415 public override int GetHashCode()
1417 return base.GetHashCode();
1420 public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
1422 // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
1423 context.IsGetOnlyCollection = false;
1424 XmlFormatWriterDelegate(xmlWriter, obj, context, this);
1427 public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
1431 if (context.IsGetOnlyCollection)
1433 // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
1434 context.IsGetOnlyCollection = false;
1435 XmlFormatGetOnlyCollectionReaderDelegate(xmlReader, context, CollectionItemName, Namespace, this);
1439 o = XmlFormatReaderDelegate(xmlReader, context, CollectionItemName, Namespace, this);
1441 xmlReader.ReadEndElement();
1445 public class DictionaryEnumerator : IEnumerator<KeyValue<object, object>>
1447 IDictionaryEnumerator enumerator;
1449 public DictionaryEnumerator(IDictionaryEnumerator enumerator)
1451 this.enumerator = enumerator;
1454 public void Dispose()
1458 public bool MoveNext()
1460 return enumerator.MoveNext();
1463 public KeyValue<object, object> Current
1465 get { return new KeyValue<object, object>(enumerator.Key, enumerator.Value); }
1468 object System.Collections.IEnumerator.Current
1470 get { return Current; }
1479 public class GenericDictionaryEnumerator<K, V> : IEnumerator<KeyValue<K, V>>
1481 IEnumerator<KeyValuePair<K, V>> enumerator;
1483 public GenericDictionaryEnumerator(IEnumerator<KeyValuePair<K, V>> enumerator)
1485 this.enumerator = enumerator;
1488 public void Dispose()
1492 public bool MoveNext()
1494 return enumerator.MoveNext();
1497 public KeyValue<K, V> Current
1501 KeyValuePair<K, V> current = enumerator.Current;
1502 return new KeyValue<K, V>(current.Key, current.Value);
1506 object System.Collections.IEnumerator.Current
1508 get { return Current; }