| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.Runtime.Serialization
- {
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.IO;
- using System.Globalization;
- using System.Reflection;
- using System.Threading;
- using System.Xml;
- #if !NO_CONFIGURATION
- using System.Runtime.Serialization.Configuration;
- #endif
- using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
- using System.Security;
- using System.Security.Permissions;
- [DataContract(Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
- #if USE_REFEMIT
- public struct KeyValue<K, V>
- #else
- internal struct KeyValue<K, V>
- #endif
- {
- K key;
- V value;
- internal KeyValue(K key, V value)
- {
- this.key = key;
- this.value = value;
- }
- [DataMember(IsRequired = true)]
- public K Key
- {
- get { return key; }
- set { key = value; }
- }
- [DataMember(IsRequired = true)]
- public V Value
- {
- get { return value; }
- set { this.value = value; }
- }
- }
- internal enum CollectionKind : byte
- {
- None,
- GenericDictionary,
- Dictionary,
- GenericList,
- GenericCollection,
- List,
- GenericEnumerable,
- Collection,
- Enumerable,
- Array,
- }
- #if USE_REFEMIT
- public sealed class CollectionDataContract : DataContract
- #else
- internal sealed class CollectionDataContract : DataContract
- #endif
- {
- [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the XML element name for collection items."
- + "Statically cached and used from IL generated code.")]
- [SecurityCritical]
- XmlDictionaryString collectionItemName;
- [Fx.Tag.SecurityNote(Critical = "XmlDictionaryString representing the XML namespace for collection items."
- + "Statically cached and used from IL generated code.")]
- [SecurityCritical]
- XmlDictionaryString childElementNamespace;
- [Fx.Tag.SecurityNote(Critical = "Internal DataContract representing the contract for collection items."
- + "Statically cached and used from IL generated code.")]
- [SecurityCritical]
- DataContract itemContract;
- [Fx.Tag.SecurityNote(Critical = "Holds instance of CriticalHelper which keeps state that is cached statically for serialization. "
- + "Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
- [SecurityCritical]
- CollectionDataContractCriticalHelper helper;
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- internal CollectionDataContract(CollectionKind kind)
- : base(new CollectionDataContractCriticalHelper(kind))
- {
- InitCollectionDataContract(this);
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- internal CollectionDataContract(Type type)
- : base(new CollectionDataContractCriticalHelper(type))
- {
- InitCollectionDataContract(this);
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- internal CollectionDataContract(Type type, DataContract itemContract)
- : base(new CollectionDataContractCriticalHelper(type, itemContract))
- {
- InitCollectionDataContract(this);
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string serializationExceptionMessage, string deserializationExceptionMessage)
- : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage))
- {
- InitCollectionDataContract(GetSharedTypeContract(type));
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor)
- : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, addMethod, constructor))
- {
- InitCollectionDataContract(GetSharedTypeContract(type));
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- CollectionDataContract(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor, bool isConstructorCheckRequired)
- : base(new CollectionDataContractCriticalHelper(type, kind, itemType, getEnumeratorMethod, addMethod, constructor, isConstructorCheckRequired))
- {
- InitCollectionDataContract(GetSharedTypeContract(type));
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical field 'helper'.",
- Safe = "Doesn't leak anything.")]
- [SecuritySafeCritical]
- CollectionDataContract(Type type, string invalidCollectionInSharedContractMessage)
- : base(new CollectionDataContractCriticalHelper(type, invalidCollectionInSharedContractMessage))
- {
- InitCollectionDataContract(GetSharedTypeContract(type));
- }
- [Fx.Tag.SecurityNote(Critical = "Initializes SecurityCritical fields; called from all constructors.")]
- [SecurityCritical]
- void InitCollectionDataContract(DataContract sharedTypeContract)
- {
- this.helper = base.Helper as CollectionDataContractCriticalHelper;
- this.collectionItemName = helper.CollectionItemName;
- if (helper.Kind == CollectionKind.Dictionary || helper.Kind == CollectionKind.GenericDictionary)
- {
- this.itemContract = helper.ItemContract;
- }
- this.helper.SharedTypeContract = sharedTypeContract;
- }
- void InitSharedTypeContract()
- {
- }
- static Type[] KnownInterfaces
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical knownInterfaces property.",
- Safe = "knownInterfaces only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return CollectionDataContractCriticalHelper.KnownInterfaces; }
- }
- internal CollectionKind Kind
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical kind property.",
- Safe = "kind only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.Kind; }
- }
- internal Type ItemType
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemType property.",
- Safe = "itemType only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.ItemType; }
- }
- public DataContract ItemContract
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemContract property.",
- Safe = "itemContract only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return itemContract ?? helper.ItemContract; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical itemContract property.")]
- [SecurityCritical]
- set
- {
- itemContract = value;
- helper.ItemContract = value;
- }
- }
- internal DataContract SharedTypeContract
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical sharedTypeContract property.",
- Safe = "sharedTypeContract only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.SharedTypeContract; }
- }
- internal string ItemName
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemName property.",
- Safe = "itemName only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.ItemName; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical itemName property.")]
- [SecurityCritical]
- set { helper.ItemName = value; }
- }
- public XmlDictionaryString CollectionItemName
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical collectionItemName property.",
- Safe = "collectionItemName only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return this.collectionItemName; }
- }
- internal string KeyName
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical keyName property.",
- Safe = "keyName only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.KeyName; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical keyName property.")]
- [SecurityCritical]
- set { helper.KeyName = value; }
- }
- internal string ValueName
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical valueName property.",
- Safe = "valueName only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.ValueName; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical valueName property.")]
- [SecurityCritical]
- set { helper.ValueName = value; }
- }
- internal bool IsDictionary
- {
- get { return KeyName != null; }
- }
- public XmlDictionaryString ChildElementNamespace
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical childElementNamespace property.",
- Safe = "childElementNamespace only needs to be protected for write; initialized in getter if null.")]
- [SecuritySafeCritical]
- get
- {
- if (this.childElementNamespace == null)
- {
- lock (this)
- {
- if (this.childElementNamespace == null)
- {
- if (helper.ChildElementNamespace == null && !IsDictionary)
- {
- XmlDictionaryString tempChildElementNamespace = ClassDataContract.GetChildNamespaceToDeclare(this, ItemType, new XmlDictionary());
- Thread.MemoryBarrier();
- helper.ChildElementNamespace = tempChildElementNamespace;
- }
- this.childElementNamespace = helper.ChildElementNamespace;
- }
- }
- }
- return childElementNamespace;
- }
- }
- internal bool IsItemTypeNullable
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical isItemTypeNullable property.",
- Safe = "isItemTypeNullable only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.IsItemTypeNullable; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical isItemTypeNullable property.")]
- [SecurityCritical]
- set { helper.IsItemTypeNullable = value; }
- }
- internal bool IsConstructorCheckRequired
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical isConstructorCheckRequired property.",
- Safe = "isConstructorCheckRequired only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.IsConstructorCheckRequired; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical isConstructorCheckRequired property.")]
- [SecurityCritical]
- set { helper.IsConstructorCheckRequired = value; }
- }
- internal MethodInfo GetEnumeratorMethod
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical getEnumeratorMethod property.",
- Safe = "getEnumeratorMethod only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.GetEnumeratorMethod; }
- }
- internal MethodInfo AddMethod
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical addMethod property.",
- Safe = "addMethod only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.AddMethod; }
- }
- internal ConstructorInfo Constructor
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical constructor property.",
- Safe = "constructor only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.Constructor; }
- }
- internal override DataContractDictionary KnownDataContracts
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical knownDataContracts property.",
- Safe = "knownDataContracts only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.KnownDataContracts; }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical knownDataContracts property.")]
- [SecurityCritical]
- set { helper.KnownDataContracts = value; }
- }
- internal string InvalidCollectionInSharedContractMessage
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical invalidCollectionInSharedContractMessage property.",
- Safe = "invalidCollectionInSharedContractMessage only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.InvalidCollectionInSharedContractMessage; }
- }
- internal string SerializationExceptionMessage
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical serializationExceptionMessage property.",
- Safe = "serializationExceptionMessage only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.SerializationExceptionMessage; }
- }
- internal string DeserializationExceptionMessage
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical deserializationExceptionMessage property.",
- Safe = "deserializationExceptionMessage only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.DeserializationExceptionMessage; }
- }
- internal bool IsReadOnlyContract
- {
- get { return this.DeserializationExceptionMessage != null; }
- }
- bool ItemNameSetExplicit
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical itemNameSetExplicit property.",
- Safe = "itemNameSetExplicit only needs to be protected for write.")]
- [SecuritySafeCritical]
- get { return helper.ItemNameSetExplicit; }
- }
- internal XmlFormatCollectionWriterDelegate XmlFormatWriterDelegate
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatWriterDelegate property.",
- Safe = "xmlFormatWriterDelegate only needs to be protected for write; initialized in getter if null.")]
- [SecuritySafeCritical]
- get
- {
- if (helper.XmlFormatWriterDelegate == null)
- {
- lock (this)
- {
- if (helper.XmlFormatWriterDelegate == null)
- {
- XmlFormatCollectionWriterDelegate tempDelegate = new XmlFormatWriterGenerator().GenerateCollectionWriter(this);
- Thread.MemoryBarrier();
- helper.XmlFormatWriterDelegate = tempDelegate;
- }
- }
- }
- return helper.XmlFormatWriterDelegate;
- }
- }
- internal XmlFormatCollectionReaderDelegate XmlFormatReaderDelegate
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatReaderDelegate property.",
- Safe = "xmlFormatReaderDelegate only needs to be protected for write; initialized in getter if null.")]
- [SecuritySafeCritical]
- get
- {
- if (helper.XmlFormatReaderDelegate == null)
- {
- lock (this)
- {
- if (helper.XmlFormatReaderDelegate == null)
- {
- if (this.IsReadOnlyContract)
- {
- ThrowInvalidDataContractException(helper.DeserializationExceptionMessage, null /*type*/);
- }
- XmlFormatCollectionReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateCollectionReader(this);
- Thread.MemoryBarrier();
- helper.XmlFormatReaderDelegate = tempDelegate;
- }
- }
- }
- return helper.XmlFormatReaderDelegate;
- }
- }
- internal XmlFormatGetOnlyCollectionReaderDelegate XmlFormatGetOnlyCollectionReaderDelegate
- {
- [Fx.Tag.SecurityNote(Critical = "Fetches the critical xmlFormatGetOnlyCollectionReaderDelegate property.",
- Safe = "xmlFormatGetOnlyCollectionReaderDelegate only needs to be protected for write; initialized in getter if null.")]
- [SecuritySafeCritical]
- get
- {
- if (helper.XmlFormatGetOnlyCollectionReaderDelegate == null)
- {
- lock (this)
- {
- if (helper.XmlFormatGetOnlyCollectionReaderDelegate == null)
- {
- if (this.UnderlyingType.IsInterface && (this.Kind == CollectionKind.Enumerable || this.Kind == CollectionKind.Collection || this.Kind == CollectionKind.GenericEnumerable))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GetOnlyCollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(this.UnderlyingType))));
- }
- if (this.IsReadOnlyContract)
- {
- ThrowInvalidDataContractException(helper.DeserializationExceptionMessage, null /*type*/);
- }
- 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");
- XmlFormatGetOnlyCollectionReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateGetOnlyCollectionReader(this);
- Thread.MemoryBarrier();
- helper.XmlFormatGetOnlyCollectionReaderDelegate = tempDelegate;
- }
- }
- }
- return helper.XmlFormatGetOnlyCollectionReaderDelegate;
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Holds all state used for (de)serializing collections. Since the data is cached statically, we lock down access to it.")]
- #if !NO_SECURITY_ATTRIBUTES
- [SecurityCritical(SecurityCriticalScope.Everything)]
- #endif
- class CollectionDataContractCriticalHelper : DataContract.DataContractCriticalHelper
- {
- static Type[] _knownInterfaces;
- Type itemType;
- bool isItemTypeNullable;
- CollectionKind kind;
- readonly MethodInfo getEnumeratorMethod, addMethod;
- readonly ConstructorInfo constructor;
- readonly string serializationExceptionMessage, deserializationExceptionMessage;
- DataContract itemContract;
- DataContract sharedTypeContract;
- DataContractDictionary knownDataContracts;
- bool isKnownTypeAttributeChecked;
- string itemName;
- bool itemNameSetExplicit;
- XmlDictionaryString collectionItemName;
- string keyName;
- string valueName;
- XmlDictionaryString childElementNamespace;
- string invalidCollectionInSharedContractMessage;
- XmlFormatCollectionReaderDelegate xmlFormatReaderDelegate;
- XmlFormatGetOnlyCollectionReaderDelegate xmlFormatGetOnlyCollectionReaderDelegate;
- XmlFormatCollectionWriterDelegate xmlFormatWriterDelegate;
- bool isConstructorCheckRequired = false;
- internal static Type[] KnownInterfaces
- {
- get
- {
- if (_knownInterfaces == null)
- {
- // Listed in priority order
- _knownInterfaces = new Type[]
- {
- Globals.TypeOfIDictionaryGeneric,
- Globals.TypeOfIDictionary,
- Globals.TypeOfIListGeneric,
- Globals.TypeOfICollectionGeneric,
- Globals.TypeOfIList,
- Globals.TypeOfIEnumerableGeneric,
- Globals.TypeOfICollection,
- Globals.TypeOfIEnumerable
- };
- }
- return _knownInterfaces;
- }
- }
- void Init(CollectionKind kind, Type itemType, CollectionDataContractAttribute collectionContractAttribute)
- {
- this.kind = kind;
- if (itemType != null)
- {
- this.itemType = itemType;
- this.isItemTypeNullable = DataContract.IsTypeNullable(itemType);
- bool isDictionary = (kind == CollectionKind.Dictionary || kind == CollectionKind.GenericDictionary);
- string itemName = null, keyName = null, valueName = null;
- if (collectionContractAttribute != null)
- {
- if (collectionContractAttribute.IsItemNameSetExplicitly)
- {
- if (collectionContractAttribute.ItemName == null || collectionContractAttribute.ItemName.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractItemName, DataContract.GetClrTypeFullName(UnderlyingType))));
- itemName = DataContract.EncodeLocalName(collectionContractAttribute.ItemName);
- itemNameSetExplicit = true;
- }
- if (collectionContractAttribute.IsKeyNameSetExplicitly)
- {
- if (collectionContractAttribute.KeyName == null || collectionContractAttribute.KeyName.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractKeyName, DataContract.GetClrTypeFullName(UnderlyingType))));
- if (!isDictionary)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractKeyNoDictionary, DataContract.GetClrTypeFullName(UnderlyingType), collectionContractAttribute.KeyName)));
- keyName = DataContract.EncodeLocalName(collectionContractAttribute.KeyName);
- }
- if (collectionContractAttribute.IsValueNameSetExplicitly)
- {
- if (collectionContractAttribute.ValueName == null || collectionContractAttribute.ValueName.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractValueName, DataContract.GetClrTypeFullName(UnderlyingType))));
- if (!isDictionary)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidCollectionContractValueNoDictionary, DataContract.GetClrTypeFullName(UnderlyingType), collectionContractAttribute.ValueName)));
- valueName = DataContract.EncodeLocalName(collectionContractAttribute.ValueName);
- }
- }
- XmlDictionary dictionary = isDictionary ? new XmlDictionary(5) : new XmlDictionary(3);
- this.Name = dictionary.Add(this.StableName.Name);
- this.Namespace = dictionary.Add(this.StableName.Namespace);
- this.itemName = itemName ?? DataContract.GetStableName(DataContract.UnwrapNullableType(itemType)).Name;
- this.collectionItemName = dictionary.Add(this.itemName);
- if (isDictionary)
- {
- this.keyName = keyName ?? Globals.KeyLocalName;
- this.valueName = valueName ?? Globals.ValueLocalName;
- }
- }
- if (collectionContractAttribute != null)
- {
- this.IsReference = collectionContractAttribute.IsReference;
- }
- }
- internal CollectionDataContractCriticalHelper(CollectionKind kind)
- : base()
- {
- Init(kind, null, null);
- }
- // array
- internal CollectionDataContractCriticalHelper(Type type)
- : base(type)
- {
- if (type == Globals.TypeOfArray)
- type = Globals.TypeOfObjectArray;
- if (type.GetArrayRank() > 1)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SupportForMultidimensionalArraysNotPresent)));
- this.StableName = DataContract.GetStableName(type);
- Init(CollectionKind.Array, type.GetElementType(), null);
- }
- // array
- internal CollectionDataContractCriticalHelper(Type type, DataContract itemContract)
- : base(type)
- {
- if (type.GetArrayRank() > 1)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SupportForMultidimensionalArraysNotPresent)));
- this.StableName = CreateQualifiedName(Globals.ArrayPrefix + itemContract.StableName.Name, itemContract.StableName.Namespace);
- this.itemContract = itemContract;
- Init(CollectionKind.Array, type.GetElementType(), null);
- }
- // read-only collection
- internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, string serializationExceptionMessage, string deserializationExceptionMessage)
- : base(type)
- {
- if (getEnumeratorMethod == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveGetEnumeratorMethod, DataContract.GetClrTypeFullName(type))));
- if (itemType == null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveItemType, DataContract.GetClrTypeFullName(type))));
- CollectionDataContractAttribute collectionContractAttribute;
- this.StableName = DataContract.GetCollectionStableName(type, itemType, out collectionContractAttribute);
- Init(kind, itemType, collectionContractAttribute);
- this.getEnumeratorMethod = getEnumeratorMethod;
- this.serializationExceptionMessage = serializationExceptionMessage;
- this.deserializationExceptionMessage = deserializationExceptionMessage;
- }
- // collection
- internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor)
- : this(type, kind, itemType, getEnumeratorMethod, (string)null, (string)null)
- {
- if (addMethod == null && !type.IsInterface)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(type))));
- this.addMethod = addMethod;
- this.constructor = constructor;
- }
- // collection
- internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor, bool isConstructorCheckRequired)
- : this(type, kind, itemType, getEnumeratorMethod, addMethod, constructor)
- {
- this.isConstructorCheckRequired = isConstructorCheckRequired;
- }
- internal CollectionDataContractCriticalHelper(Type type, string invalidCollectionInSharedContractMessage)
- : base(type)
- {
- Init(CollectionKind.Collection, null /*itemType*/, null);
- this.invalidCollectionInSharedContractMessage = invalidCollectionInSharedContractMessage;
- }
- internal CollectionKind Kind
- {
- get { return kind; }
- }
- internal Type ItemType
- {
- get { return itemType; }
- }
- internal DataContract ItemContract
- {
- get
- {
- if (itemContract == null && UnderlyingType != null)
- {
- if (IsDictionary)
- {
- if (String.CompareOrdinal(KeyName, ValueName) == 0)
- {
- DataContract.ThrowInvalidDataContractException(
- SR.GetString(SR.DupKeyValueName, DataContract.GetClrTypeFullName(UnderlyingType), KeyName),
- UnderlyingType);
- }
- itemContract = ClassDataContract.CreateClassDataContractForKeyValue(ItemType, Namespace, new string[] { KeyName, ValueName });
- // Ensure that DataContract gets added to the static DataContract cache for dictionary items
- DataContract.GetDataContract(ItemType);
- }
- else
- {
- itemContract = DataContract.GetDataContract(ItemType);
- }
- }
- return itemContract;
- }
- set
- {
- itemContract = value;
- }
- }
- internal DataContract SharedTypeContract
- {
- get { return sharedTypeContract; }
- set { sharedTypeContract = value; }
- }
- internal string ItemName
- {
- get { return itemName; }
- set { itemName = value; }
- }
- internal bool IsConstructorCheckRequired
- {
- get { return isConstructorCheckRequired; }
- set { isConstructorCheckRequired = value; }
- }
- public XmlDictionaryString CollectionItemName
- {
- get { return collectionItemName; }
- }
- internal string KeyName
- {
- get { return keyName; }
- set { keyName = value; }
- }
- internal string ValueName
- {
- get { return valueName; }
- set { valueName = value; }
- }
- internal bool IsDictionary
- {
- get { return KeyName != null; }
- }
- public string SerializationExceptionMessage
- {
- get { return serializationExceptionMessage; }
- }
- public string DeserializationExceptionMessage
- {
- get { return deserializationExceptionMessage; }
- }
- public XmlDictionaryString ChildElementNamespace
- {
- get { return childElementNamespace; }
- set { childElementNamespace = value; }
- }
- internal bool IsItemTypeNullable
- {
- get { return isItemTypeNullable; }
- set { isItemTypeNullable = value; }
- }
- internal MethodInfo GetEnumeratorMethod
- {
- get { return getEnumeratorMethod; }
- }
- internal MethodInfo AddMethod
- {
- get { return addMethod; }
- }
- internal ConstructorInfo Constructor
- {
- get { return constructor; }
- }
- internal override DataContractDictionary KnownDataContracts
- {
- get
- {
- if (!isKnownTypeAttributeChecked && UnderlyingType != null)
- {
- lock (this)
- {
- if (!isKnownTypeAttributeChecked)
- {
- knownDataContracts = DataContract.ImportKnownTypeAttributes(this.UnderlyingType);
- Thread.MemoryBarrier();
- isKnownTypeAttributeChecked = true;
- }
- }
- }
- return knownDataContracts;
- }
- set { knownDataContracts = value; }
- }
- internal string InvalidCollectionInSharedContractMessage
- {
- get { return invalidCollectionInSharedContractMessage; }
- }
- internal bool ItemNameSetExplicit
- {
- get { return itemNameSetExplicit; }
- }
- internal XmlFormatCollectionWriterDelegate XmlFormatWriterDelegate
- {
- get { return xmlFormatWriterDelegate; }
- set { xmlFormatWriterDelegate = value; }
- }
- internal XmlFormatCollectionReaderDelegate XmlFormatReaderDelegate
- {
- get { return xmlFormatReaderDelegate; }
- set { xmlFormatReaderDelegate = value; }
- }
- internal XmlFormatGetOnlyCollectionReaderDelegate XmlFormatGetOnlyCollectionReaderDelegate
- {
- get { return xmlFormatGetOnlyCollectionReaderDelegate; }
- set { xmlFormatGetOnlyCollectionReaderDelegate = value; }
- }
- }
- DataContract GetSharedTypeContract(Type type)
- {
- if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false))
- {
- return this;
- }
- // ClassDataContract.IsNonAttributedTypeValidForSerialization does not need to be called here. It should
- // never pass because it returns false for types that implement any of CollectionDataContract.KnownInterfaces
- if (type.IsSerializable || type.IsDefined(Globals.TypeOfDataContractAttribute, false))
- {
- return new ClassDataContract(type);
- }
- return null;
- }
- internal static bool IsCollectionInterface(Type type)
- {
- if (type.IsGenericType)
- type = type.GetGenericTypeDefinition();
- return ((IList<Type>)KnownInterfaces).Contains(type);
- }
- internal static bool IsCollection(Type type)
- {
- Type itemType;
- return IsCollection(type, out itemType);
- }
- internal static bool IsCollection(Type type, out Type itemType)
- {
- return IsCollectionHelper(type, out itemType, true /*constructorRequired*/);
- }
- internal static bool IsCollection(Type type, bool constructorRequired, bool skipIfReadOnlyContract)
- {
- Type itemType;
- return IsCollectionHelper(type, out itemType, constructorRequired, skipIfReadOnlyContract);
- }
- static bool IsCollectionHelper(Type type, out Type itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
- {
- if (type.IsArray && DataContract.GetBuiltInDataContract(type) == null)
- {
- itemType = type.GetElementType();
- return true;
- }
- DataContract dataContract;
- return IsCollectionOrTryCreate(type, false /*tryCreate*/, out dataContract, out itemType, constructorRequired, skipIfReadOnlyContract);
- }
- internal static bool TryCreate(Type type, out DataContract dataContract)
- {
- Type itemType;
- return IsCollectionOrTryCreate(type, true /*tryCreate*/, out dataContract, out itemType, true /*constructorRequired*/);
- }
- internal static bool TryCreateGetOnlyCollectionDataContract(Type type, out DataContract dataContract)
- {
- Type itemType;
- if (type.IsArray)
- {
- dataContract = new CollectionDataContract(type);
- return true;
- }
- else
- {
- return IsCollectionOrTryCreate(type, true /*tryCreate*/, out dataContract, out itemType, false /*constructorRequired*/);
- }
- }
- internal static MethodInfo GetTargetMethodWithName(string name, Type type, Type interfaceType)
- {
- InterfaceMapping mapping = type.GetInterfaceMap(interfaceType);
- for (int i = 0; i < mapping.TargetMethods.Length; i++)
- {
- if (mapping.InterfaceMethods[i].Name == name)
- return mapping.InterfaceMethods[i];
- }
- return null;
- }
- static bool IsArraySegment(Type t)
- {
- return t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(ArraySegment<>));
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.Globalization, FxCop.Rule.DoNotPassLiteralsAsLocalizedParameters, Justification = "Private code.")]
- static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataContract dataContract, out Type itemType, bool constructorRequired, bool skipIfReadOnlyContract = false)
- {
- dataContract = null;
- itemType = Globals.TypeOfObject;
- if (DataContract.GetBuiltInDataContract(type) != null)
- {
- return HandleIfInvalidCollection(type, tryCreate, false/*hasCollectionDataContract*/, false/*isBaseTypeCollection*/,
- SR.CollectionTypeCannotBeBuiltIn, null, ref dataContract);
- }
- MethodInfo addMethod, getEnumeratorMethod;
- bool hasCollectionDataContract = IsCollectionDataContract(type);
- bool isReadOnlyContract = false;
- string serializationExceptionMessage = null, deserializationExceptionMessage = null;
- Type baseType = type.BaseType;
- bool isBaseTypeCollection = (baseType != null && baseType != Globals.TypeOfObject
- && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri) ? IsCollection(baseType) : false;
- // Avoid creating an invalid collection contract for Serializable types since we can create a ClassDataContract instead
- bool createContractWithException = isBaseTypeCollection && !type.IsSerializable;
- if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
- SR.CollectionTypeCannotHaveDataContract, null, ref dataContract);
- }
- if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type) || IsArraySegment(type))
- {
- return false;
- }
- if (!Globals.TypeOfIEnumerable.IsAssignableFrom(type))
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
- SR.CollectionTypeIsNotIEnumerable, null, ref dataContract);
- }
- if (type.IsInterface)
- {
- Type interfaceTypeToCheck = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
- Type[] knownInterfaces = KnownInterfaces;
- for (int i = 0; i < knownInterfaces.Length; i++)
- {
- if (knownInterfaces[i] == interfaceTypeToCheck)
- {
- addMethod = null;
- if (type.IsGenericType)
- {
- Type[] genericArgs = type.GetGenericArguments();
- if (interfaceTypeToCheck == Globals.TypeOfIDictionaryGeneric)
- {
- itemType = Globals.TypeOfKeyValue.MakeGenericType(genericArgs);
- addMethod = type.GetMethod(Globals.AddMethodName);
- getEnumeratorMethod = Globals.TypeOfIEnumerableGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(genericArgs)).GetMethod(Globals.GetEnumeratorMethodName);
- }
- else
- {
- itemType = genericArgs[0];
- if (interfaceTypeToCheck == Globals.TypeOfICollectionGeneric || interfaceTypeToCheck == Globals.TypeOfIListGeneric)
- {
- addMethod = Globals.TypeOfICollectionGeneric.MakeGenericType(itemType).GetMethod(Globals.AddMethodName);
- }
- getEnumeratorMethod = Globals.TypeOfIEnumerableGeneric.MakeGenericType(itemType).GetMethod(Globals.GetEnumeratorMethodName);
- }
- }
- else
- {
- if (interfaceTypeToCheck == Globals.TypeOfIDictionary)
- {
- itemType = typeof(KeyValue<object, object>);
- addMethod = type.GetMethod(Globals.AddMethodName);
- }
- else
- {
- itemType = Globals.TypeOfObject;
- if (interfaceTypeToCheck == Globals.TypeOfIList)
- {
- addMethod = Globals.TypeOfIList.GetMethod(Globals.AddMethodName);
- }
- }
- getEnumeratorMethod = Globals.TypeOfIEnumerable.GetMethod(Globals.GetEnumeratorMethodName);
- }
- if (tryCreate)
- dataContract = new CollectionDataContract(type, (CollectionKind)(i + 1), itemType, getEnumeratorMethod, addMethod, null/*defaultCtor*/);
- return true;
- }
- }
- }
- ConstructorInfo defaultCtor = null;
- if (!type.IsValueType)
- {
- defaultCtor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Globals.EmptyTypeArray, null);
- if (defaultCtor == null && constructorRequired)
- {
- // All collection types could be considered read-only collections except collection types that are marked [Serializable].
- // Collection types marked [Serializable] cannot be read-only collections for backward compatibility reasons.
- // DataContract types and POCO types cannot be collection types, so they don't need to be factored in
- if (type.IsSerializable)
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
- SR.CollectionTypeDoesNotHaveDefaultCtor, null, ref dataContract);
- }
- else
- {
- isReadOnlyContract = true;
- GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveDefaultCtor, null, out serializationExceptionMessage, out deserializationExceptionMessage);
- }
- }
- }
- Type knownInterfaceType = null;
- CollectionKind kind = CollectionKind.None;
- bool multipleDefinitions = false;
- Type[] interfaceTypes = type.GetInterfaces();
- foreach (Type interfaceType in interfaceTypes)
- {
- Type interfaceTypeToCheck = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType;
- Type[] knownInterfaces = KnownInterfaces;
- for (int i = 0; i < knownInterfaces.Length; i++)
- {
- if (knownInterfaces[i] == interfaceTypeToCheck)
- {
- CollectionKind currentKind = (CollectionKind)(i + 1);
- if (kind == CollectionKind.None || currentKind < kind)
- {
- kind = currentKind;
- knownInterfaceType = interfaceType;
- multipleDefinitions = false;
- }
- else if ((kind & currentKind) == currentKind)
- multipleDefinitions = true;
- break;
- }
- }
- }
- if (kind == CollectionKind.None)
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
- SR.CollectionTypeIsNotIEnumerable, null, ref dataContract);
- }
- if (kind == CollectionKind.Enumerable || kind == CollectionKind.Collection || kind == CollectionKind.GenericEnumerable)
- {
- if (multipleDefinitions)
- knownInterfaceType = Globals.TypeOfIEnumerable;
- itemType = knownInterfaceType.IsGenericType ? knownInterfaceType.GetGenericArguments()[0] : Globals.TypeOfObject;
- GetCollectionMethods(type, knownInterfaceType, new Type[] { itemType },
- false /*addMethodOnInterface*/,
- out getEnumeratorMethod, out addMethod);
- if (addMethod == null)
- {
- // All collection types could be considered read-only collections except collection types that are marked [Serializable].
- // Collection types marked [Serializable] cannot be read-only collections for backward compatibility reasons.
- // DataContract types and POCO types cannot be collection types, so they don't need to be factored in.
- if (type.IsSerializable || skipIfReadOnlyContract)
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException && !skipIfReadOnlyContract,
- SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), ref dataContract);
- }
- else
- {
- isReadOnlyContract = true;
- GetReadOnlyCollectionExceptionMessages(type, hasCollectionDataContract, SR.CollectionTypeDoesNotHaveAddMethod, DataContract.GetClrTypeFullName(itemType), out serializationExceptionMessage, out deserializationExceptionMessage);
- }
- }
- if (tryCreate)
- {
- dataContract = isReadOnlyContract ?
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
- }
- }
- else
- {
- if (multipleDefinitions)
- {
- return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, createContractWithException,
- SR.CollectionTypeHasMultipleDefinitionsOfInterface, KnownInterfaces[(int)kind - 1].Name, ref dataContract);
- }
- Type[] addMethodTypeArray = null;
- switch (kind)
- {
- case CollectionKind.GenericDictionary:
- addMethodTypeArray = knownInterfaceType.GetGenericArguments();
- bool isOpenGeneric = knownInterfaceType.IsGenericTypeDefinition
- || (addMethodTypeArray[0].IsGenericParameter && addMethodTypeArray[1].IsGenericParameter);
- itemType = isOpenGeneric ? Globals.TypeOfKeyValue : Globals.TypeOfKeyValue.MakeGenericType(addMethodTypeArray);
- break;
- case CollectionKind.Dictionary:
- addMethodTypeArray = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject };
- itemType = Globals.TypeOfKeyValue.MakeGenericType(addMethodTypeArray);
- break;
- case CollectionKind.GenericList:
- case CollectionKind.GenericCollection:
- addMethodTypeArray = knownInterfaceType.GetGenericArguments();
- itemType = addMethodTypeArray[0];
- break;
- case CollectionKind.List:
- itemType = Globals.TypeOfObject;
- addMethodTypeArray = new Type[] { itemType };
- break;
- }
- if (tryCreate)
- {
- GetCollectionMethods(type, knownInterfaceType, addMethodTypeArray,
- true /*addMethodOnInterface*/,
- out getEnumeratorMethod, out addMethod);
- dataContract = isReadOnlyContract ?
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, serializationExceptionMessage, deserializationExceptionMessage) :
- new CollectionDataContract(type, kind, itemType, getEnumeratorMethod, addMethod, defaultCtor, !constructorRequired);
- }
- }
- return !(isReadOnlyContract && skipIfReadOnlyContract);
- }
- internal static bool IsCollectionDataContract(Type type)
- {
- return type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false);
- }
- static bool HandleIfInvalidCollection(Type type, bool tryCreate, bool hasCollectionDataContract, bool createContractWithException, string message, string param, ref DataContract dataContract)
- {
- if (hasCollectionDataContract)
- {
- if (tryCreate)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(GetInvalidCollectionMessage(message, SR.GetString(SR.InvalidCollectionDataContract, DataContract.GetClrTypeFullName(type)), param)));
- return true;
- }
- if (createContractWithException)
- {
- if (tryCreate)
- dataContract = new CollectionDataContract(type, GetInvalidCollectionMessage(message, SR.GetString(SR.InvalidCollectionType, DataContract.GetClrTypeFullName(type)), param));
- return true;
- }
- return false;
- }
- static void GetReadOnlyCollectionExceptionMessages(Type type, bool hasCollectionDataContract, string message, string param, out string serializationExceptionMessage, out string deserializationExceptionMessage)
- {
- serializationExceptionMessage = GetInvalidCollectionMessage(message, SR.GetString(hasCollectionDataContract ? SR.InvalidCollectionDataContract : SR.InvalidCollectionType, DataContract.GetClrTypeFullName(type)), param);
- deserializationExceptionMessage = GetInvalidCollectionMessage(message, SR.GetString(SR.ReadOnlyCollectionDeserialization, DataContract.GetClrTypeFullName(type)), param);
- }
- static string GetInvalidCollectionMessage(string message, string nestedMessage, string param)
- {
- return (param == null) ? SR.GetString(message, nestedMessage) : SR.GetString(message, nestedMessage, param);
- }
- static void FindCollectionMethodsOnInterface(Type type, Type interfaceType, ref MethodInfo addMethod, ref MethodInfo getEnumeratorMethod)
- {
- InterfaceMapping mapping = type.GetInterfaceMap(interfaceType);
- for (int i = 0; i < mapping.TargetMethods.Length; i++)
- {
- if (mapping.InterfaceMethods[i].Name == Globals.AddMethodName)
- addMethod = mapping.InterfaceMethods[i];
- else if (mapping.InterfaceMethods[i].Name == Globals.GetEnumeratorMethodName)
- getEnumeratorMethod = mapping.InterfaceMethods[i];
- }
- }
- static void GetCollectionMethods(Type type, Type interfaceType, Type[] addMethodTypeArray, bool addMethodOnInterface, out MethodInfo getEnumeratorMethod, out MethodInfo addMethod)
- {
- addMethod = getEnumeratorMethod = null;
- if (addMethodOnInterface)
- {
- addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public, null, addMethodTypeArray, null);
- if (addMethod == null || addMethod.GetParameters()[0].ParameterType != addMethodTypeArray[0])
- {
- FindCollectionMethodsOnInterface(type, interfaceType, ref addMethod, ref getEnumeratorMethod);
- if (addMethod == null)
- {
- Type[] parentInterfaceTypes = interfaceType.GetInterfaces();
- foreach (Type parentInterfaceType in parentInterfaceTypes)
- {
- if (IsKnownInterface(parentInterfaceType))
- {
- FindCollectionMethodsOnInterface(type, parentInterfaceType, ref addMethod, ref getEnumeratorMethod);
- if (addMethod == null)
- {
- break;
- }
- }
- }
- }
- }
- }
- else
- {
- // GetMethod returns Add() method with parameter closest matching T in assignability/inheritance chain
- addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, addMethodTypeArray, null);
- }
- if (getEnumeratorMethod == null)
- {
- getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null);
- if (getEnumeratorMethod == null || !Globals.TypeOfIEnumerator.IsAssignableFrom(getEnumeratorMethod.ReturnType))
- {
- Type ienumerableInterface = interfaceType.GetInterface("System.Collections.Generic.IEnumerable*");
- if (ienumerableInterface == null)
- ienumerableInterface = Globals.TypeOfIEnumerable;
- getEnumeratorMethod = GetTargetMethodWithName(Globals.GetEnumeratorMethodName, type, ienumerableInterface);
- }
- }
- }
- static bool IsKnownInterface(Type type)
- {
- Type typeToCheck = type.IsGenericType ? type.GetGenericTypeDefinition() : type;
- foreach (Type knownInterfaceType in KnownInterfaces)
- {
- if (typeToCheck == knownInterfaceType)
- {
- return true;
- }
- }
- return false;
- }
- [Fx.Tag.SecurityNote(Critical = "Sets critical properties on CollectionDataContract .",
- Safe = "Called during schema import/code generation.")]
- [SecuritySafeCritical]
- internal override DataContract BindGenericParameters(DataContract[] paramContracts, Dictionary<DataContract, DataContract> boundContracts)
- {
- DataContract boundContract;
- if (boundContracts.TryGetValue(this, out boundContract))
- return boundContract;
- CollectionDataContract boundCollectionContract = new CollectionDataContract(Kind);
- boundContracts.Add(this, boundCollectionContract);
- boundCollectionContract.ItemContract = this.ItemContract.BindGenericParameters(paramContracts, boundContracts);
- boundCollectionContract.IsItemTypeNullable = !boundCollectionContract.ItemContract.IsValueType;
- boundCollectionContract.ItemName = ItemNameSetExplicit ? this.ItemName : boundCollectionContract.ItemContract.StableName.Name;
- boundCollectionContract.KeyName = this.KeyName;
- boundCollectionContract.ValueName = this.ValueName;
- boundCollectionContract.StableName = CreateQualifiedName(DataContract.ExpandGenericParameters(XmlConvert.DecodeName(this.StableName.Name), new GenericNameProvider(DataContract.GetClrTypeFullName(this.UnderlyingType), paramContracts)),
- IsCollectionDataContract(UnderlyingType) ? this.StableName.Namespace : DataContract.GetCollectionNamespace(boundCollectionContract.ItemContract.StableName.Namespace));
- return boundCollectionContract;
- }
- internal override DataContract GetValidContract(SerializationMode mode)
- {
- if (mode == SerializationMode.SharedType)
- {
- if (SharedTypeContract == null)
- DataContract.ThrowTypeNotSerializable(UnderlyingType);
- return SharedTypeContract;
- }
- ThrowIfInvalid();
- return this;
- }
- void ThrowIfInvalid()
- {
- if (InvalidCollectionInSharedContractMessage != null)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(InvalidCollectionInSharedContractMessage));
- }
- internal override DataContract GetValidContract()
- {
- if (this.IsConstructorCheckRequired)
- {
- CheckConstructor();
- }
- return this;
- }
- [Fx.Tag.SecurityNote(Critical = "Sets the critical IsConstructorCheckRequired property on CollectionDataContract.",
- Safe = "Does not leak anything.")]
- [SecuritySafeCritical]
- void CheckConstructor()
- {
- if (this.Constructor == null)
- {
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionTypeDoesNotHaveDefaultCtor, DataContract.GetClrTypeFullName(this.UnderlyingType))));
- }
- else
- {
- this.IsConstructorCheckRequired = false;
- }
- }
- internal override bool IsValidContract(SerializationMode mode)
- {
- if (mode == SerializationMode.SharedType)
- return (SharedTypeContract != null);
- return (InvalidCollectionInSharedContractMessage == null);
- }
- #if !NO_DYNAMIC_CODEGEN
- [Fx.Tag.SecurityNote(Miscellaneous =
- "RequiresReview - Calculates whether this collection requires MemberAccessPermission for deserialization."
- + " Since this information is used to determine whether to give the generated code access"
- + " permissions to private members, any changes to the logic should be reviewed.")]
- internal bool RequiresMemberAccessForRead(SecurityException securityException)
- {
- if (!IsTypeVisible(UnderlyingType))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractTypeNotPublic,
- DataContract.GetClrTypeFullName(UnderlyingType)),
- securityException));
- }
- return true;
- }
- if (ItemType != null && !IsTypeVisible(ItemType))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractTypeNotPublic,
- DataContract.GetClrTypeFullName(ItemType)),
- securityException));
- }
- return true;
- }
- if (ConstructorRequiresMemberAccess(Constructor))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractNoPublicConstructor,
- DataContract.GetClrTypeFullName(UnderlyingType)),
- securityException));
- }
- return true;
- }
- if (MethodRequiresMemberAccess(this.AddMethod))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractAddMethodNotPublic,
- DataContract.GetClrTypeFullName(UnderlyingType),
- this.AddMethod.Name),
- securityException));
- }
- return true;
- }
- return false;
- }
- [Fx.Tag.SecurityNote(Miscellaneous =
- "RequiresReview - Calculates whether this collection requires MemberAccessPermission for serialization."
- + " Since this information is used to determine whether to give the generated code access"
- + " permissions to private members, any changes to the logic should be reviewed.")]
- internal bool RequiresMemberAccessForWrite(SecurityException securityException)
- {
- if (!IsTypeVisible(UnderlyingType))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractTypeNotPublic,
- DataContract.GetClrTypeFullName(UnderlyingType)),
- securityException));
- }
- return true;
- }
- if (ItemType != null && !IsTypeVisible(ItemType))
- {
- if (securityException != null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SecurityException(SR.GetString(
- SR.PartialTrustCollectionContractTypeNotPublic,
- DataContract.GetClrTypeFullName(ItemType)),
- securityException));
- }
- return true;
- }
- return false;
- }
- #endif
- internal override bool Equals(object other, Dictionary<DataContractPairKey, object> checkedContracts)
- {
- if (IsEqualOrChecked(other, checkedContracts))
- return true;
- if (base.Equals(other, checkedContracts))
- {
- CollectionDataContract dataContract = other as CollectionDataContract;
- if (dataContract != null)
- {
- bool thisItemTypeIsNullable = (ItemContract == null) ? false : !ItemContract.IsValueType;
- bool otherItemTypeIsNullable = (dataContract.ItemContract == null) ? false : !dataContract.ItemContract.IsValueType;
- return ItemName == dataContract.ItemName &&
- (IsItemTypeNullable || thisItemTypeIsNullable) == (dataContract.IsItemTypeNullable || otherItemTypeIsNullable) &&
- ItemContract.Equals(dataContract.ItemContract, checkedContracts);
- }
- }
- return false;
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context)
- {
- // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
- context.IsGetOnlyCollection = false;
- XmlFormatWriterDelegate(xmlWriter, obj, context, this);
- }
- public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
- {
- xmlReader.Read();
- object o = null;
- if (context.IsGetOnlyCollection)
- {
- // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset.
- context.IsGetOnlyCollection = false;
- XmlFormatGetOnlyCollectionReaderDelegate(xmlReader, context, CollectionItemName, Namespace, this);
- }
- else
- {
- o = XmlFormatReaderDelegate(xmlReader, context, CollectionItemName, Namespace, this);
- }
- xmlReader.ReadEndElement();
- return o;
- }
- public class DictionaryEnumerator : IEnumerator<KeyValue<object, object>>
- {
- IDictionaryEnumerator enumerator;
- public DictionaryEnumerator(IDictionaryEnumerator enumerator)
- {
- this.enumerator = enumerator;
- }
- public void Dispose()
- {
- }
- public bool MoveNext()
- {
- return enumerator.MoveNext();
- }
- public KeyValue<object, object> Current
- {
- get { return new KeyValue<object, object>(enumerator.Key, enumerator.Value); }
- }
- object System.Collections.IEnumerator.Current
- {
- get { return Current; }
- }
- public void Reset()
- {
- enumerator.Reset();
- }
- }
- public class GenericDictionaryEnumerator<K, V> : IEnumerator<KeyValue<K, V>>
- {
- IEnumerator<KeyValuePair<K, V>> enumerator;
- public GenericDictionaryEnumerator(IEnumerator<KeyValuePair<K, V>> enumerator)
- {
- this.enumerator = enumerator;
- }
- public void Dispose()
- {
- }
- public bool MoveNext()
- {
- return enumerator.MoveNext();
- }
- public KeyValue<K, V> Current
- {
- get
- {
- KeyValuePair<K, V> current = enumerator.Current;
- return new KeyValue<K, V>(current.Key, current.Value);
- }
- }
- object System.Collections.IEnumerator.Current
- {
- get { return Current; }
- }
- public void Reset()
- {
- enumerator.Reset();
- }
- }
- }
- }
|