Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / ClassDataContract.cs / 4 / ClassDataContract.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.Permissions; using System.Security; #if USE_REFEMIT public sealed class ClassDataContract : DataContract #else internal sealed class ClassDataContract : DataContract #endif { /// /// Review - XmlDictionaryString(s) representing the XML namespaces for class members. /// statically cached and used from IL generated code. should ideally be Critical. /// marked SecurityRequiresReview to be callable from transparent IL generated code. /// not changed to property to avoid regressing performance; any changes to initalization should be reviewed. /// [SecurityRequiresReview] public XmlDictionaryString[] ContractNamespaces; ////// Review - XmlDictionaryString(s) representing the XML element names for class members. /// statically cached and used from IL generated code. should ideally be Critical. /// marked SecurityRequiresReview to be callable from transparent IL generated code. /// not changed to property to avoid regressing performance; any changes to initalization should be reviewed. /// [SecurityRequiresReview] public XmlDictionaryString[] MemberNames; ////// Review - XmlDictionaryString(s) representing the XML namespaces for class members. /// statically cached and used when calling IL generated code. should ideally be Critical. /// marked SecurityRequiresReview to be callable from transparent code. /// not changed to property to avoid regressing performance; any changes to initalization should be reviewed. /// [SecurityRequiresReview] public XmlDictionaryString[] MemberNamespaces; ////// Critical - XmlDictionaryString representing the XML namespaces for members of class. /// statically cached and used from IL generated code. /// [SecurityCritical] XmlDictionaryString[] childElementNamespaces; ////// 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] ClassDataContractCriticalHelper helper; ////// Critical - initializes SecurityCritical field 'helper' /// Safe - doesn't leak anything /// [SecurityCritical, SecurityTreatAsSafe] internal ClassDataContract() : base(new ClassDataContractCriticalHelper()) { InitClassDataContract(); } ////// Critical - initializes SecurityCritical field 'helper' /// Safe - doesn't leak anything /// [SecurityCritical, SecurityTreatAsSafe] internal ClassDataContract(Type type) : base(new ClassDataContractCriticalHelper(type)) { InitClassDataContract(); } ////// Critical - initializes SecurityCritical field 'helper' /// Safe - doesn't leak anything /// [SecurityCritical, SecurityTreatAsSafe] ClassDataContract(Type type, XmlDictionaryString ns, string[] memberNames) : base(new ClassDataContractCriticalHelper(type, ns, memberNames)) { InitClassDataContract(); } ////// Critical - initializes SecurityCritical fields; called from all constructors /// [SecurityCritical] void InitClassDataContract() { this.helper = base.Helper as ClassDataContractCriticalHelper; this.ContractNamespaces = helper.ContractNamespaces; this.MemberNames = helper.MemberNames; this.MemberNamespaces = helper.MemberNamespaces; } internal ClassDataContract BaseContract { ////// Critical - fetches the critical baseContract property /// Safe - baseContract only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.BaseContract; } ////// Critical - sets the critical baseContract property /// [SecurityCritical] set { helper.BaseContract = value; } } internal ListMembers { /// /// Critical - fetches the critical members property /// Safe - members only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.Members; } ////// Critical - sets the critical members property /// Safe - protected for write if contract has underlyingType /// [SecurityCritical] set { helper.Members = value; } } public XmlDictionaryString[] ChildElementNamespaces { ////// Critical - fetches the critical childElementNamespaces property /// Safe - childElementNamespaces only needs to be protected for write; initialized in getter if null /// [SecurityCritical, SecurityTreatAsSafe] get { if (this.childElementNamespaces == null) { lock (this) { if (this.childElementNamespaces == null) { if (helper.ChildElementNamespaces == null) { XmlDictionaryString[] tempChildElementamespaces = CreateChildElementNamespaces(); Thread.MemoryBarrier(); helper.ChildElementNamespaces = tempChildElementamespaces; } this.childElementNamespaces = helper.ChildElementNamespaces; } } } return this.childElementNamespaces; } } internal MethodInfo OnSerializing { ////// Critical - fetches the critical onSerializing property /// Safe - onSerializing only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.OnSerializing; } } internal MethodInfo OnSerialized { ////// Critical - fetches the critical onSerialized property /// Safe - onSerialized only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.OnSerialized; } } internal MethodInfo OnDeserializing { ////// Critical - fetches the critical onDeserializing property /// Safe - onDeserializing only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.OnDeserializing; } } internal MethodInfo OnDeserialized { ////// Critical - fetches the critical onDeserialized property /// Safe - onDeserialized only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.OnDeserialized; } } internal MethodInfo ExtensionDataSetMethod { ////// Critical - fetches the critical extensionDataSetMethod property /// Safe - extensionDataSetMethod only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.ExtensionDataSetMethod; } } internal override DataContractDictionary KnownDataContracts { ////// Critical - fetches the critical knownDataContracts property /// Safe - knownDataContracts only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.KnownDataContracts; } ////// Critical - sets the critical knownDataContracts property /// Safe - protected for write if contract has underlyingType /// [SecurityCritical] set { helper.KnownDataContracts = value; } } internal override bool IsISerializable { ////// Critical - fetches the critical isISerializable property /// Safe - isISerializable only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.IsISerializable; } ////// Critical - sets the critical isISerializable property /// Safe - protected for write if contract has underlyingType /// [SecurityCritical] set { helper.IsISerializable = value; } } internal bool IsNonAttributedType { ////// Critical - fetches the critical IsNonAttributedType property /// Safe - IsNonAttributedType only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.IsNonAttributedType; } } internal bool HasDataContract { ////// Critical - fetches the critical hasDataContract property /// Safe - hasDataContract only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.HasDataContract; } } internal bool HasExtensionData { ////// Critical - fetches the critical hasExtensionData property /// Safe - hasExtensionData only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] get { return helper.HasExtensionData; } } ////// Critical - fetches information about which constructor should be used to initialize ISerializable types /// Safe - only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] internal ConstructorInfo GetISerializableConstructor() { return helper.GetISerializableConstructor(); } ////// Critical - fetches information about which constructor should be used to initialize non-attributed types that are valid for serialization /// Safe - only needs to be protected for write /// [SecurityCritical, SecurityTreatAsSafe] internal ConstructorInfo GetNonAttributedTypeConstructor() { return helper.GetNonAttributedTypeConstructor(); } internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate { ////// Critical - fetches the critical xmlFormatWriterDelegate property /// Safe - xmlFormatWriterDelegate only needs to be protected for write; initialized in getter if null /// [SecurityCritical, SecurityTreatAsSafe] get { if (helper.XmlFormatWriterDelegate == null) { lock (this) { if (helper.XmlFormatWriterDelegate == null) { XmlFormatClassWriterDelegate tempDelegate = new XmlFormatWriterGenerator().GenerateClassWriter(this); Thread.MemoryBarrier(); helper.XmlFormatWriterDelegate = tempDelegate; } } } return helper.XmlFormatWriterDelegate; } } internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate { ////// Critical - fetches the critical xmlFormatReaderDelegate property /// Safe - xmlFormatReaderDelegate only needs to be protected for write; initialized in getter if null /// [SecurityCritical, SecurityTreatAsSafe] get { if (helper.XmlFormatReaderDelegate == null) { lock (this) { if (helper.XmlFormatReaderDelegate == null) { XmlFormatClassReaderDelegate tempDelegate = new XmlFormatReaderGenerator().GenerateClassReader(this); Thread.MemoryBarrier(); helper.XmlFormatReaderDelegate = tempDelegate; } } } return helper.XmlFormatReaderDelegate; } } internal static ClassDataContract CreateClassDataContractForKeyValue(Type type, XmlDictionaryString ns, string[] memberNames) { return new ClassDataContract(type, ns, memberNames); } internal static void CheckAndAddMember(Listmembers, DataMember memberContract, Dictionary memberNamesTable) { DataMember existingMemberContract; if (memberNamesTable.TryGetValue(memberContract.Name, out existingMemberContract)) { Type declaringType = memberContract.MemberInfo.DeclaringType; DataContract.ThrowInvalidDataContractException( SR.GetString((declaringType.IsEnum ? SR.DupEnumMemberValue : SR.DupMemberName), existingMemberContract.MemberInfo.Name, memberContract.MemberInfo.Name, DataContract.GetClrTypeFullName(declaringType), memberContract.Name), declaringType); } memberNamesTable.Add(memberContract.Name, memberContract); members.Add(memberContract); } internal static XmlDictionaryString GetChildNamespaceToDeclare(DataContract dataContract, Type childType, XmlDictionary dictionary) { childType = DataContract.UnwrapNullableType(childType); if (!childType.IsEnum && !Globals.TypeOfIXmlSerializable.IsAssignableFrom(childType) && DataContract.GetBuiltInDataContract(childType) == null && childType != Globals.TypeOfDBNull) { string ns = DataContract.GetStableName(childType).Namespace; if (ns.Length > 0 && ns != dataContract.Namespace.Value) return dictionary.Add(ns); } return null; } /// /// RequiresReview - callers may need to depend on isNonAttributedType for a security decision /// isNonAttributedType must be calculated correctly /// IsNonAttributedTypeValidForSerialization is used as part of the isNonAttributedType calculation and /// is therefore marked SRR /// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value /// [SecurityRequiresReview] // check whether a corresponding update is required in DataContractCriticalHelper.CreateDataContract static internal bool IsNonAttributedTypeValidForSerialization(Type type) { if (type.IsArray) return false; if (type.IsEnum) return false; if (type.IsGenericParameter) return false; if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type)) return false; if (type.IsPointer) return false; if (type.IsDefined(Globals.TypeOfCollectionDataContractAttribute, false)) return false; Type[] interfaceTypes = type.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (CollectionDataContract.IsCollectionInterface(interfaceType)) return false; } if (type.IsSerializable) return false; if (Globals.TypeOfISerializable.IsAssignableFrom(type)) return false; if (type.IsDefined(Globals.TypeOfDataContractAttribute, false)) return false; if (type == Globals.TypeOfExtensionDataObject) return false; if (type.IsValueType) { return type.IsVisible; } else { return (type.IsVisible && type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null) != null); } } XmlDictionaryString[] CreateChildElementNamespaces() { if (Members == null) return null; XmlDictionaryString[] baseChildElementNamespaces = null; if (this.BaseContract != null) baseChildElementNamespaces = this.BaseContract.ChildElementNamespaces; int baseChildElementNamespaceCount = (baseChildElementNamespaces != null) ? baseChildElementNamespaces.Length : 0; XmlDictionaryString[] childElementNamespaces = new XmlDictionaryString[Members.Count + baseChildElementNamespaceCount]; if (baseChildElementNamespaceCount > 0) Array.Copy(baseChildElementNamespaces, 0, childElementNamespaces, 0, baseChildElementNamespaces.Length); XmlDictionary dictionary = new XmlDictionary(); for (int i = 0; i < this.Members.Count; i++) { childElementNamespaces[i + baseChildElementNamespaceCount] = GetChildNamespaceToDeclare(this, this.Members[i].MemberType, dictionary); } return childElementNamespaces; } ////// Critical - calls critical method on helper /// Safe - doesn't leak anything /// [SecurityCritical, SecurityTreatAsSafe] void EnsureMethodsImported() { helper.EnsureMethodsImported(); } public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context) { XmlFormatWriterDelegate(xmlWriter, obj, context, this); } public override object ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context) { xmlReader.Read(); object o = XmlFormatReaderDelegate(xmlReader, context, MemberNames, MemberNamespaces); xmlReader.ReadEndElement(); return o; } ////// Review - calculates whether this class requires MemberAccessPermission for deserialization. /// since this information is used to determine whether to give the generated code access /// permissions to private members, any changes to the logic should be reviewed. /// [SecurityRequiresReview] internal bool RequiresMemberAccessForRead(SecurityException securityException) { EnsureMethodsImported(); if (!IsTypeVisible(UnderlyingType)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractTypeNotPublic, DataContract.GetClrTypeFullName(UnderlyingType)), securityException)); } return true; } if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForRead(securityException)) return true; if (ConstructorRequiresMemberAccess(GetISerializableConstructor())) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustISerializableNoPublicConstructor, DataContract.GetClrTypeFullName(UnderlyingType)), securityException)); } return true; } if (ConstructorRequiresMemberAccess(GetNonAttributedTypeConstructor())) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustNonAttributedSerializableTypeNoPublicConstructor, DataContract.GetClrTypeFullName(UnderlyingType)), securityException)); } return true; } if (MethodRequiresMemberAccess(this.OnDeserializing)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractOnDeserializingNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.OnDeserializing.Name), securityException)); } return true; } if (MethodRequiresMemberAccess(this.OnDeserialized)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractOnDeserializedNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.OnDeserialized.Name), securityException)); } return true; } if (this.Members != null) { for (int i = 0; i < this.Members.Count; i++) { if (this.Members[i].RequiresMemberAccessForSet()) { if (securityException != null) { if (this.Members[i].MemberInfo is FieldInfo) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractFieldSetNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.Members[i].MemberInfo.Name), securityException)); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractPropertySetNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.Members[i].MemberInfo.Name), securityException)); } } return true; } } } return false; } ////// Review - calculates whether this class requires MemberAccessPermission for serialization. /// since this information is used to determine whether to give the generated code access /// permissions to private members, any changes to the logic should be reviewed. /// [SecurityRequiresReview] internal bool RequiresMemberAccessForWrite(SecurityException securityException) { EnsureMethodsImported(); if (!IsTypeVisible(UnderlyingType)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractTypeNotPublic, DataContract.GetClrTypeFullName(UnderlyingType)), securityException)); } return true; } if (this.BaseContract != null && this.BaseContract.RequiresMemberAccessForWrite(securityException)) return true; if (MethodRequiresMemberAccess(this.OnSerializing)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractOnSerializingNotPublic, DataContract.GetClrTypeFullName(this.UnderlyingType), this.OnSerializing.Name), securityException)); } return true; } if (MethodRequiresMemberAccess(this.OnSerialized)) { if (securityException != null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractOnSerializedNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.OnSerialized.Name), securityException)); } return true; } if (this.Members != null) { for (int i = 0; i < this.Members.Count; i++) { if (this.Members[i].RequiresMemberAccessForGet()) { if (securityException != null) { if (this.Members[i].MemberInfo is FieldInfo) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractFieldGetNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.Members[i].MemberInfo.Name), securityException)); } else { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityException(SR.GetString( SR.PartialTrustDataContractPropertyGetNotPublic, DataContract.GetClrTypeFullName(UnderlyingType), this.Members[i].MemberInfo.Name), securityException)); } } return true; } } } return false; } ////// Critical - holds all state used for (de)serializing classes. /// since the data is cached statically, we lock down access to it. /// [SecurityCritical(SecurityCriticalScope.Everything)] class ClassDataContractCriticalHelper : DataContract.DataContractCriticalHelper { ClassDataContract baseContract; Listmembers; MethodInfo onSerializing, onSerialized; MethodInfo onDeserializing, onDeserialized; MethodInfo extensionDataSetMethod; DataContractDictionary knownDataContracts; bool isISerializable; bool isKnownTypeAttributeChecked; bool isMethodChecked; bool hasExtensionData; /// /// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and hasDataContract /// bool isNonAttributedType; ////// in serialization/deserialization we base the decision whether to Demand SerializationFormatter permission on this value and isNonAttributedType /// bool hasDataContract; XmlDictionaryString[] childElementNamespaces; XmlFormatClassReaderDelegate xmlFormatReaderDelegate; XmlFormatClassWriterDelegate xmlFormatWriterDelegate; public XmlDictionaryString[] ContractNamespaces; public XmlDictionaryString[] MemberNames; public XmlDictionaryString[] MemberNamespaces; internal ClassDataContractCriticalHelper() : base() { } internal ClassDataContractCriticalHelper(Type type) : base(type) { XmlQualifiedName stableName = GetStableNameAndSetHasDataContract(type); if (type == Globals.TypeOfDBNull) { this.StableName = stableName; this.members = new List(); XmlDictionary dictionary = new XmlDictionary(2); this.Name = dictionary.Add(StableName.Name); this.Namespace = dictionary.Add(StableName.Namespace); this.ContractNamespaces = this.MemberNames = this.MemberNamespaces = new XmlDictionaryString[] { }; EnsureMethodsImported(); return; } Type baseType = type.BaseType; this.isISerializable = (Globals.TypeOfISerializable.IsAssignableFrom(type)); SetIsNonAttributedType(type); if (this.isISerializable) { if (HasDataContract) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.ISerializableCannotHaveDataContract, DataContract.GetClrTypeFullName(type)))); if (baseType != null && !(baseType.IsSerializable && Globals.TypeOfISerializable.IsAssignableFrom(baseType))) baseType = null; } this.IsValueType = type.IsValueType; if (baseType != null && baseType != Globals.TypeOfObject && baseType != Globals.TypeOfValueType && baseType != Globals.TypeOfUri) { DataContract baseContract = DataContract.GetDataContract(baseType); if (baseContract is CollectionDataContract) this.BaseContract = ((CollectionDataContract)baseContract).SharedTypeContract as ClassDataContract; else this.BaseContract = baseContract as ClassDataContract; if (this.BaseContract != null && this.BaseContract.IsNonAttributedType && !this.isNonAttributedType) { throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidDataContractException(SR.GetString(SR.AttributedTypesCannotInheritFromNonAttributedSerializableTypes, DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(baseType)))); } } else this.BaseContract = null; hasExtensionData = (Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(type)); if (hasExtensionData && !HasDataContract && !IsNonAttributedType) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.OnlyDataContractTypesCanHaveExtensionData, DataContract.GetClrTypeFullName(type)))); if (this.isISerializable) SetDataContractName(stableName); else { this.StableName = stableName; ImportDataMembers(); XmlDictionary dictionary = new XmlDictionary(2 + Members.Count); Name = dictionary.Add(StableName.Name); Namespace = dictionary.Add(StableName.Namespace); int baseMemberCount = 0; int baseContractCount = 0; if (BaseContract == null) { MemberNames = new XmlDictionaryString[Members.Count]; MemberNamespaces = new XmlDictionaryString[Members.Count]; ContractNamespaces = new XmlDictionaryString[1]; } else { baseMemberCount = BaseContract.MemberNames.Length; MemberNames = new XmlDictionaryString[Members.Count + baseMemberCount]; Array.Copy(BaseContract.MemberNames, MemberNames, baseMemberCount); MemberNamespaces = new XmlDictionaryString[Members.Count + baseMemberCount]; Array.Copy(BaseContract.MemberNamespaces, MemberNamespaces, baseMemberCount); baseContractCount = BaseContract.ContractNamespaces.Length; ContractNamespaces = new XmlDictionaryString[1 + baseContractCount]; Array.Copy(BaseContract.ContractNamespaces, ContractNamespaces, baseContractCount); } ContractNamespaces[baseContractCount] = Namespace; for (int i = 0; i < Members.Count; i++) { MemberNames[i + baseMemberCount] = dictionary.Add(Members[i].Name); MemberNamespaces[i + baseMemberCount] = Namespace; } } EnsureMethodsImported(); } internal ClassDataContractCriticalHelper(Type type, XmlDictionaryString ns, string[] memberNames) : base(type) { this.StableName = new XmlQualifiedName(GetStableNameAndSetHasDataContract(type).Name, ns.Value); ImportDataMembers(); XmlDictionary dictionary = new XmlDictionary(1 + Members.Count); Name = dictionary.Add(StableName.Name); Namespace = ns; ContractNamespaces = new XmlDictionaryString[] { Namespace }; MemberNames = new XmlDictionaryString[Members.Count]; MemberNamespaces = new XmlDictionaryString[Members.Count]; for (int i = 0; i < Members.Count; i++) { Members[i].Name = memberNames[i]; MemberNames[i] = dictionary.Add(Members[i].Name); MemberNamespaces[i] = Namespace; } EnsureMethodsImported(); } void EnsureIsReferenceImported(Type type) { DataContractAttribute dataContractAttribute; bool isReference = false; bool hasDataContractAttribute = TryGetDCAttribute(type, out dataContractAttribute); if (BaseContract != null) { if (hasDataContractAttribute && dataContractAttribute.IsReferenceSetExplicit) { bool baseIsReference = this.BaseContract.IsReference; if ((baseIsReference && !dataContractAttribute.IsReference) || (!baseIsReference && dataContractAttribute.IsReference)) { DataContract.ThrowInvalidDataContractException( SR.GetString(SR.InconsistentIsReference, DataContract.GetClrTypeFullName(type), dataContractAttribute.IsReference, DataContract.GetClrTypeFullName(this.BaseContract.UnderlyingType), this.BaseContract.IsReference), type); } else { isReference = dataContractAttribute.IsReference; } } else { isReference = this.BaseContract.IsReference; } } else if (hasDataContractAttribute) { if (dataContractAttribute.IsReference) isReference = dataContractAttribute.IsReference; } if (isReference && type.IsValueType) { DataContract.ThrowInvalidDataContractException( SR.GetString(SR.ValueTypeCannotHaveIsReference, DataContract.GetClrTypeFullName(type), true, false), type); return; } this.IsReference = isReference; } void ImportDataMembers() { Type type = this.UnderlyingType; EnsureIsReferenceImported(type); List tempMembers = new List (); Dictionary memberNamesTable = new Dictionary (); MemberInfo[] memberInfos; if (this.isNonAttributedType) { memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); } else { memberInfos = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } for (int i = 0; i < memberInfos.Length; i++) { MemberInfo member = memberInfos[i]; if (HasDataContract) { object[] memberAttributes = member.GetCustomAttributes(typeof(DataMemberAttribute), false); if (memberAttributes != null && memberAttributes.Length > 0) { if (memberAttributes.Length > 1) ThrowInvalidDataContractException(SR.GetString(SR.TooManyDataMembers, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name)); DataMember memberContract = new DataMember(member); if (member.MemberType == MemberTypes.Property) { PropertyInfo property = (PropertyInfo)member; MethodInfo getMethod = property.GetGetMethod(true); if (getMethod != null && IsMethodOverriding(getMethod)) continue; MethodInfo setMethod = property.GetSetMethod(true); if (setMethod != null && IsMethodOverriding(setMethod)) continue; if (getMethod == null) ThrowInvalidDataContractException(SR.GetString(SR.NoGetMethodForProperty, property.DeclaringType, property.Name)); if (setMethod == null) { if (!SetIfGetOnlyCollection(memberContract)) { ThrowInvalidDataContractException(SR.GetString(SR.NoSetMethodForProperty, property.DeclaringType, property.Name)); } } if (getMethod.GetParameters().Length > 0) ThrowInvalidDataContractException(SR.GetString(SR.IndexedPropertyCannotBeSerialized, property.DeclaringType, property.Name)); } else if (member.MemberType != MemberTypes.Field) ThrowInvalidDataContractException(SR.GetString(SR.InvalidMember, DataContract.GetClrTypeFullName(type), member.Name)); DataMemberAttribute memberAttribute = (DataMemberAttribute)memberAttributes[0]; if (memberAttribute.IsNameSetExplicit) { if (memberAttribute.Name == null || memberAttribute.Name.Length == 0) ThrowInvalidDataContractException(SR.GetString(SR.InvalidDataMemberName, member.Name, DataContract.GetClrTypeFullName(type))); memberContract.Name = memberAttribute.Name; } else memberContract.Name = member.Name; memberContract.Name = DataContract.EncodeLocalName(memberContract.Name); memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType); memberContract.IsRequired = memberAttribute.IsRequired; if (memberAttribute.IsRequired && this.IsReference) { ThrowInvalidDataContractException( SR.GetString(SR.IsRequiredDataMemberOnIsReferenceDataContractType, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name, true), type); } memberContract.EmitDefaultValue = memberAttribute.EmitDefaultValue; memberContract.Order = memberAttribute.Order; CheckAndAddMember(tempMembers, memberContract, memberNamesTable); } } else if (this.isNonAttributedType) { FieldInfo field = member as FieldInfo; PropertyInfo property = member as PropertyInfo; if ((field == null && property == null) || (field != null && field.IsInitOnly)) continue; object[] memberAttributes = member.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false); if (memberAttributes != null && memberAttributes.Length > 0) { if (memberAttributes.Length > 1) ThrowInvalidDataContractException(SR.GetString(SR.TooManyIgnoreDataMemberAttributes, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name)); else continue; } DataMember memberContract = new DataMember(member); if (property != null) { MethodInfo getMethod = property.GetGetMethod(); if (getMethod == null || IsMethodOverriding(getMethod) || getMethod.GetParameters().Length > 0) continue; MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null) { if (!SetIfGetOnlyCollection(memberContract)) continue; } else { if (!setMethod.IsPublic || IsMethodOverriding(setMethod)) continue; } //skip ExtensionData member of type ExtensionDataObject if IExtensibleDataObject is implemented in non-attributed type if (this.hasExtensionData && memberContract.MemberType == Globals.TypeOfExtensionDataObject && member.Name == Globals.ExtensionDataObjectPropertyName) continue; } memberContract.Name = DataContract.EncodeLocalName(member.Name); memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType); CheckAndAddMember(tempMembers, memberContract, memberNamesTable); } else { FieldInfo field = member as FieldInfo; if (field != null && !field.IsNotSerialized) { DataMember memberContract = new DataMember(member); memberContract.Name = DataContract.EncodeLocalName(member.Name); object[] optionalFields = field.GetCustomAttributes(Globals.TypeOfOptionalFieldAttribute, false); if (optionalFields == null || optionalFields.Length == 0) { if (this.IsReference) { ThrowInvalidDataContractException( SR.GetString(SR.NonOptionalFieldMemberOnIsReferenceSerializableType, DataContract.GetClrTypeFullName(member.DeclaringType), member.Name, true), type); } memberContract.IsRequired = true; } memberContract.IsNullable = DataContract.IsTypeNullable(memberContract.MemberType); CheckAndAddMember(tempMembers, memberContract, memberNamesTable); } } } if (tempMembers.Count > 1) tempMembers.Sort(DataMemberComparer.Singleton); SetIfMembersHaveConflict(tempMembers); Thread.MemoryBarrier(); members = tempMembers; } bool SetIfGetOnlyCollection(DataMember memberContract) { //OK to call IsCollection here since the use of surrogated collection types is not supported in get-only scenarios if (CollectionDataContract.IsCollection(memberContract.MemberType, false /*isConstructorRequired*/) && !memberContract.MemberType.IsValueType) { memberContract.IsGetOnlyCollection = true; return true; } return false; } void SetIfMembersHaveConflict(List members) { if (BaseContract == null) return; int baseTypeIndex = 0; List membersInHierarchy = new List (); foreach (DataMember member in members) { membersInHierarchy.Add(new Member(member, this.StableName.Namespace, baseTypeIndex)); } ClassDataContract currContract = BaseContract; while (currContract != null) { baseTypeIndex++; foreach (DataMember member in currContract.Members) { membersInHierarchy.Add(new Member(member, currContract.StableName.Namespace, baseTypeIndex)); } currContract = currContract.BaseContract; } IComparer comparer = DataMemberConflictComparer.Singleton; membersInHierarchy.Sort(comparer); for (int i = 0; i < membersInHierarchy.Count - 1; i++) { int startIndex = i; int endIndex = i; bool hasConflictingType = false; while (endIndex < membersInHierarchy.Count - 1 && String.CompareOrdinal(membersInHierarchy[endIndex].member.Name, membersInHierarchy[endIndex + 1].member.Name) == 0 && String.CompareOrdinal(membersInHierarchy[endIndex].ns, membersInHierarchy[endIndex + 1].ns) == 0) { membersInHierarchy[endIndex].member.ConflictingMember = membersInHierarchy[endIndex + 1].member; if (!hasConflictingType) { if (membersInHierarchy[endIndex + 1].member.HasConflictingNameAndType) { hasConflictingType = true; } else { hasConflictingType = (membersInHierarchy[endIndex].member.MemberType != membersInHierarchy[endIndex + 1].member.MemberType); } } endIndex++; } if (hasConflictingType) { for (int j = startIndex; j <= endIndex; j++) { membersInHierarchy[j].member.HasConflictingNameAndType = true; } } i = endIndex + 1; } } /// /// Critical - sets the critical hasDataContract field /// Safe - uses a trusted critical API (DataContract.GetStableName) to calculate the value /// does not accept the value from the caller /// [SecurityCritical, SecurityTreatAsSafe] XmlQualifiedName GetStableNameAndSetHasDataContract(Type type) { return DataContract.GetStableName(type, out this.hasDataContract); } ////// RequiresReview - marked SRR because callers may need to depend on isNonAttributedType for a security decision /// isNonAttributedType must be calculated correctly /// SetIsNonAttributedType should not be called before GetStableNameAndSetHasDataContract since it /// is dependent on the correct calculation of hasDataContract /// Safe - does not let caller influence isNonAttributedType calculation; no harm in leaking value /// [SecurityRequiresReview] void SetIsNonAttributedType(Type type) { this.isNonAttributedType = !type.IsSerializable && !this.hasDataContract && IsNonAttributedTypeValidForSerialization(type); } static bool IsMethodOverriding(MethodInfo method) { return method.IsVirtual && ((method.Attributes & MethodAttributes.NewSlot) == 0); } internal void EnsureMethodsImported() { if (!isMethodChecked && UnderlyingType != null) { lock (this) { if (!isMethodChecked) { Type type = this.UnderlyingType; MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ); for (int i=0;iMembers { get { return members; } set { members = value; } } internal MethodInfo OnSerializing { get { EnsureMethodsImported(); return onSerializing; } } internal MethodInfo OnSerialized { get { EnsureMethodsImported(); return onSerialized; } } internal MethodInfo OnDeserializing { get { EnsureMethodsImported(); return onDeserializing; } } internal MethodInfo OnDeserialized { get { EnsureMethodsImported(); return onDeserialized; } } internal MethodInfo ExtensionDataSetMethod { get { EnsureMethodsImported(); return extensionDataSetMethod; } } 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 override bool IsISerializable { get { return isISerializable; } set { isISerializable = value; } } internal bool HasDataContract { get { return hasDataContract; } } internal bool HasExtensionData { get { return hasExtensionData; } } internal bool IsNonAttributedType { get { return isNonAttributedType; } } internal ConstructorInfo GetISerializableConstructor() { if (!IsISerializable) return null; ConstructorInfo ctor = UnderlyingType.GetConstructor(Globals.ScanAllMembers, null, SerInfoCtorArgs, null); if (ctor == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.SerializationInfo_ConstructorNotFound, DataContract.GetClrTypeFullName(UnderlyingType)))); return ctor; } internal ConstructorInfo GetNonAttributedTypeConstructor() { if (!this.IsNonAttributedType) return null; Type type = UnderlyingType; if (type.IsValueType) return null; ConstructorInfo ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (ctor == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.NonAttributedSerializableTypesMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type)))); return ctor; } internal XmlFormatClassWriterDelegate XmlFormatWriterDelegate { get { return xmlFormatWriterDelegate; } set { xmlFormatWriterDelegate = value; } } internal XmlFormatClassReaderDelegate XmlFormatReaderDelegate { get { return xmlFormatReaderDelegate; } set { xmlFormatReaderDelegate = value; } } public XmlDictionaryString[] ChildElementNamespaces { get { return childElementNamespaces; } set { childElementNamespaces = value; } } static Type[] serInfoCtorArgs; static Type[] SerInfoCtorArgs { get { if (serInfoCtorArgs == null) serInfoCtorArgs = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) }; return serInfoCtorArgs; } } internal struct Member { internal Member(DataMember member, string ns, int baseTypeIndex) { this.member = member; this.ns = ns; this.baseTypeIndex = baseTypeIndex; } internal DataMember member; internal string ns; internal int baseTypeIndex; } internal class DataMemberConflictComparer : IComparer { public int Compare(Member x, Member y) { int nsCompare = String.CompareOrdinal(x.ns, y.ns); if (nsCompare != 0) return nsCompare; int nameCompare = String.CompareOrdinal(x.member.Name, y.member.Name); if (nameCompare != 0) return nameCompare; return x.baseTypeIndex - y.baseTypeIndex; } internal static DataMemberConflictComparer Singleton = new DataMemberConflictComparer(); } } /// /// Critical - sets critical properties on ClassDataContract /// Safe - called during schema import/code generation /// [SecurityCritical, SecurityTreatAsSafe] internal override DataContract BindGenericParameters(DataContract[] paramContracts, DictionaryboundContracts) { Type type = UnderlyingType; if(!type.IsGenericType || !type.ContainsGenericParameters) return this; lock(this) { DataContract boundContract; if(boundContracts.TryGetValue(this, out boundContract)) return boundContract; ClassDataContract boundClassContract = new ClassDataContract(); boundContracts.Add(this, boundClassContract); XmlQualifiedName stableName; object[] genericParams; if(type.IsGenericTypeDefinition) { stableName = this.StableName; genericParams = paramContracts; } else { //partial Generic: Construct stable name from its open generic type definition stableName = DataContract.GetStableName(type.GetGenericTypeDefinition()); Type[] paramTypes = type.GetGenericArguments(); genericParams = new object[paramTypes.Length]; for(int i=0;i (Members.Count); foreach(DataMember member in Members) boundClassContract.Members.Add(member.BindGenericParameters(paramContracts, boundContracts)); } return boundClassContract; } } internal override bool Equals(object other, Dictionary checkedContracts) { if (IsEqualOrChecked(other, checkedContracts)) return true; if (base.Equals(other, checkedContracts)) { ClassDataContract dataContract = other as ClassDataContract; if (dataContract != null) { if (IsISerializable) { if (!dataContract.IsISerializable) return false; } else { if (dataContract.IsISerializable) return false; if (Members == null) { if (dataContract.Members != null) return false; } else if (dataContract.Members == null) return false; else { if (Members.Count != dataContract.Members.Count) return false; for (int i = 0; i < Members.Count; i++) { if (!Members[i].Equals(dataContract.Members[i], checkedContracts)) return false; } } } if (BaseContract == null) return (dataContract.BaseContract == null); else if (dataContract.BaseContract == null) return false; else return BaseContract.Equals(dataContract.BaseContract, checkedContracts); } } return false; } public override int GetHashCode() { return base.GetHashCode(); } internal class DataMemberComparer : IComparer { public int Compare(DataMember x, DataMember y) { int orderCompare = x.Order - y.Order; if (orderCompare != 0) return orderCompare; return String.CompareOrdinal(x.Name, y.Name); } internal static DataMemberComparer Singleton = new DataMemberComparer(); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CodeDomConfigurationHandler.cs
- SafeMILHandle.cs
- BasePattern.cs
- RepeaterItemCollection.cs
- MediaPlayerState.cs
- ParseElement.cs
- ArcSegment.cs
- UdpRetransmissionSettings.cs
- RSAPKCS1SignatureDeformatter.cs
- BuildProviderCollection.cs
- CompilationUtil.cs
- UICuesEvent.cs
- IPPacketInformation.cs
- SrgsRulesCollection.cs
- DiscoveryClientDuplexChannel.cs
- EnumType.cs
- GlobalizationAssembly.cs
- listitem.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- StringToken.cs
- IndicFontClient.cs
- Soap.cs
- IImplicitResourceProvider.cs
- FloaterBaseParaClient.cs
- XmlAttributeProperties.cs
- TreeNodeBindingCollection.cs
- SurrogateDataContract.cs
- TextTrailingCharacterEllipsis.cs
- DotExpr.cs
- FrameworkContentElementAutomationPeer.cs
- PropertyConverter.cs
- QuadraticEase.cs
- PrintEvent.cs
- XamlFigureLengthSerializer.cs
- hebrewshape.cs
- SoundPlayer.cs
- SettingsAttributes.cs
- OleDbTransaction.cs
- WMIGenerator.cs
- FilteredXmlReader.cs
- EventLogger.cs
- SrgsRule.cs
- PopOutPanel.cs
- XmlSerializationWriter.cs
- DecoderFallback.cs
- Validator.cs
- BordersPage.cs
- RootProfilePropertySettingsCollection.cs
- MemberInfoSerializationHolder.cs
- TransactionChannel.cs
- AuthenticatedStream.cs
- RequestUriProcessor.cs
- CharacterBufferReference.cs
- DateTimeOffsetStorage.cs
- RadioButtonAutomationPeer.cs
- Switch.cs
- InstancePersistenceException.cs
- ResourcesChangeInfo.cs
- XDRSchema.cs
- TraceAsyncResult.cs
- HtmlEmptyTagControlBuilder.cs
- RequiredFieldValidator.cs
- HashMembershipCondition.cs
- ContainerUIElement3D.cs
- ThousandthOfEmRealPoints.cs
- TargetParameterCountException.cs
- SafeNativeMethodsOther.cs
- DiscoveryClientChannelFactory.cs
- Certificate.cs
- Encoding.cs
- TreeView.cs
- XmlArrayAttribute.cs
- ProtocolsConfiguration.cs
- EditingCoordinator.cs
- CreateBookmarkScope.cs
- CatalogPartChrome.cs
- XmlWriterSettings.cs
- RelatedView.cs
- DesignTimeParseData.cs
- PlainXmlDeserializer.cs
- LocatorGroup.cs
- ModelVisual3D.cs
- ControlCollection.cs
- LicFileLicenseProvider.cs
- CompressionTransform.cs
- SkewTransform.cs
- Util.cs
- TemplatePropertyEntry.cs
- InProcStateClientManager.cs
- BufferedReceiveElement.cs
- ImageButton.cs
- Resources.Designer.cs
- WindowsAltTab.cs
- ListComponentEditor.cs
- BlobPersonalizationState.cs
- CategoryEditor.cs
- EmptyReadOnlyDictionaryInternal.cs
- BevelBitmapEffect.cs
- InvalidComObjectException.cs
- WmlTextViewAdapter.cs