Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / CollectionDataContract.cs / 1305376 / CollectionDataContract.cs
//------------------------------------------------------------------------------
// 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;
using System.Runtime.Serialization.Configuration;
using DataContractDictionary=System.Collections.Generic.Dictionary;
using System.Security;
using System.Security.Permissions;
[DataContract(Namespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")]
#if USE_REFEMIT
public struct KeyValue
#else
internal struct KeyValue
#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, 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; }
}
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)
{
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.OriginalUnderlyingType.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.OriginalUnderlyingType))));
}
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.")]
[SecurityCritical(SecurityCriticalScope.Everything)]
class CollectionDataContractCriticalHelper : DataContract.DataContractCriticalHelper
{
static Type[] _knownInterfaces;
Type itemType;
bool isItemTypeNullable;
CollectionKind kind;
readonly MethodInfo getEnumeratorMethod, addMethod;
readonly ConstructorInfo constructor;
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.IsItemNameSetExplicit)
{
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.IsKeyNameSetExplicit)
{
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.IsValueNameSetExplicit)
{
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);
}
// collection
internal CollectionDataContractCriticalHelper(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor) : base(type)
{
if (getEnumeratorMethod == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveGetEnumeratorMethod, DataContract.GetClrTypeFullName(type))));
if (addMethod == null && !type.IsInterface)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CollectionMustHaveAddMethod, 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.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 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)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)
{
Type itemType;
return IsCollectionHelper(type, out itemType, constructorRequired);
}
static bool IsCollectionHelper(Type type, out Type itemType, bool constructorRequired)
{
if (type.IsArray && DataContract.GetBuiltInDataContract(type) == null)
{
itemType = type.GetElementType();
return true;
}
DataContract dataContract;
return IsCollectionOrTryCreate(type, false /*tryCreate*/, out dataContract, out itemType, constructorRequired);
}
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 CreateGetOnlyCollectionDataContract(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 IsCollectionOrTryCreate(Type type, bool tryCreate, out DataContract dataContract, out Type itemType, bool constructorRequired)
{
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);
Type baseType = type.BaseType;
bool isBaseTypeCollection = (baseType != null && baseType != Globals.TypeOfObject
&& baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri) ? IsCollection(baseType) : false;
if (type.IsDefined(Globals.TypeOfDataContractAttribute, false))
{
return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, isBaseTypeCollection,
SR.CollectionTypeCannotHaveDataContract, null, ref dataContract);
}
if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type))
{
return false;
}
if (!Globals.TypeOfIEnumerable.IsAssignableFrom(type))
{
return HandleIfInvalidCollection(type, tryCreate, hasCollectionDataContract, isBaseTypeCollection,
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