Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / CodeExporter.cs / 1438166 / CodeExporter.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.Runtime.Serialization { using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Reflection; using System.Security; using System.Text; using System.Xml; using System.Xml.Schema; using DataContractDictionary = System.Collections.Generic.Dictionary; class CodeExporter { DataContractSet dataContractSet; CodeCompileUnit codeCompileUnit; ImportOptions options; Dictionary namespaces; Dictionary clrNamespaces; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly string wildcardNamespaceMapping = "*"; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly string typeNameFieldName = "typeName"; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly object codeUserDataActualTypeKey = new object(); [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly object surrogateDataKey = typeof(IDataContractSurrogate); const int MaxIdentifierLength = 511; internal CodeExporter(DataContractSet dataContractSet, ImportOptions options, CodeCompileUnit codeCompileUnit) { this.dataContractSet = dataContractSet; this.codeCompileUnit = codeCompileUnit; AddReferencedAssembly(Assembly.GetExecutingAssembly()); this.options = options; this.namespaces = new Dictionary (); this.clrNamespaces = new Dictionary (StringComparer.OrdinalIgnoreCase); // Update namespace tables for DataContract(s) that are already processed foreach (KeyValuePair pair in dataContractSet) { DataContract dataContract = pair.Value; if (!(dataContract.IsBuiltInDataContract || dataContract is CollectionDataContract)) { ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (contractCodeDomInfo.IsProcessed && !contractCodeDomInfo.UsesWildcardNamespace) { string clrNamespace = contractCodeDomInfo.ClrNamespace; if (clrNamespace != null && !this.clrNamespaces.ContainsKey(clrNamespace)) { this.clrNamespaces.Add(clrNamespace, dataContract.StableName.Namespace); this.namespaces.Add(dataContract.StableName.Namespace, clrNamespace); } } } } // Copy options.Namespaces to namespace tables if (this.options != null) { foreach (KeyValuePair pair in options.Namespaces) { string dataContractNamespace = pair.Key; string clrNamespace = pair.Value; if (clrNamespace == null) clrNamespace = String.Empty; string currentDataContractNamespace; if (this.clrNamespaces.TryGetValue(clrNamespace, out currentDataContractNamespace)) { if (dataContractNamespace != currentDataContractNamespace) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CLRNamespaceMappedMultipleTimes, currentDataContractNamespace, dataContractNamespace, clrNamespace))); } else this.clrNamespaces.Add(clrNamespace, dataContractNamespace); string currentClrNamespace; if (this.namespaces.TryGetValue(dataContractNamespace, out currentClrNamespace)) { if (clrNamespace != currentClrNamespace) { this.namespaces.Remove(dataContractNamespace); this.namespaces.Add(dataContractNamespace, clrNamespace); } } else this.namespaces.Add(dataContractNamespace, clrNamespace); } } // Update namespace tables for pre-existing namespaces in CodeCompileUnit foreach (CodeNamespace codeNS in codeCompileUnit.Namespaces) { string ns = codeNS.Name ?? string.Empty; if (!this.clrNamespaces.ContainsKey(ns)) { this.clrNamespaces.Add(ns, null); } if (ns.Length == 0) { foreach (CodeTypeDeclaration codeTypeDecl in codeNS.Types) { AddGlobalTypeName(codeTypeDecl.Name); } } } } void AddReferencedAssembly(Assembly assembly) { string assemblyName = System.IO.Path.GetFileName(assembly.Location); bool alreadyExisting = false; foreach (string existingName in this.codeCompileUnit.ReferencedAssemblies) { if (String.Compare(existingName, assemblyName, StringComparison.OrdinalIgnoreCase) == 0) { alreadyExisting = true; break; } } if (!alreadyExisting) this.codeCompileUnit.ReferencedAssemblies.Add(assemblyName); } bool GenerateSerializableTypes { get { return (options == null) ? false : options.GenerateSerializable; } } bool GenerateInternalTypes { get { return (options == null) ? false : options.GenerateInternal; } } bool EnableDataBinding { get { return (options == null) ? false : options.EnableDataBinding; } } CodeDomProvider CodeProvider { get { return (options == null) ? null : options.CodeProvider; } } bool SupportsDeclareEvents { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareEvents); } } bool SupportsDeclareValueTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareValueTypes); } } bool SupportsGenericTypeReference { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.GenericTypeReference); } } bool SupportsAssemblyAttributes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.AssemblyAttributes); } } bool SupportsPartialTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.PartialTypes); } } bool SupportsNestedTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.NestedTypes); } } string FileExtension { get { return (CodeProvider == null) ? String.Empty : CodeProvider.FileExtension; } } Dictionary Namespaces { get { return namespaces; } } Dictionary ClrNamespaces { get { return clrNamespaces; } } bool TryGetReferencedType(XmlQualifiedName stableName, DataContract dataContract, out Type type) { if (dataContract == null) { if (dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type)) return true; if (dataContractSet.TryGetReferencedType(stableName, dataContract, out type)) { // enforce that collection types only be specified via ReferencedCollectionTypes if (CollectionDataContract.IsCollection(type)) { type = null; return false; } return true; } return false; } else if (dataContract is CollectionDataContract) return dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type); else { XmlDataContract xmlDataContract = dataContract as XmlDataContract; if (xmlDataContract != null && xmlDataContract.IsAnonymous) { stableName = SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, stableName, dataContract.StableName); } return dataContractSet.TryGetReferencedType(stableName, dataContract, out type); } } internal void Export() { try { foreach (KeyValuePair pair in dataContractSet) { DataContract dataContract = pair.Value; if (dataContract.IsBuiltInDataContract) continue; ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (!contractCodeDomInfo.IsProcessed) { if (dataContract is ClassDataContract) { ClassDataContract classDataContract = (ClassDataContract)dataContract; if (classDataContract.IsISerializable) ExportISerializableDataContract(classDataContract, contractCodeDomInfo); else ExportClassDataContractHierarchy(classDataContract.StableName, classDataContract, contractCodeDomInfo, new Dictionary ()); } else if (dataContract is CollectionDataContract) ExportCollectionDataContract((CollectionDataContract)dataContract, contractCodeDomInfo); else if (dataContract is EnumDataContract) ExportEnumDataContract((EnumDataContract)dataContract, contractCodeDomInfo); else if (dataContract is XmlDataContract) ExportXmlDataContract((XmlDataContract)dataContract, contractCodeDomInfo); else throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(dataContract.GetType()), DataContract.GetClrTypeFullName(dataContract.UnderlyingType)))); contractCodeDomInfo.IsProcessed = true; } } if (dataContractSet.DataContractSurrogate != null) { CodeNamespace[] namespaces = new CodeNamespace[codeCompileUnit.Namespaces.Count]; codeCompileUnit.Namespaces.CopyTo(namespaces, 0); foreach (CodeNamespace codeNamespace in namespaces) InvokeProcessImportedType(codeNamespace.Types); } } finally { System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(codeCompileUnit); } } void ExportClassDataContractHierarchy(XmlQualifiedName typeName, ClassDataContract classContract, ContractCodeDomInfo contractCodeDomInfo, Dictionary contractNamesInHierarchy) { if (contractNamesInHierarchy.ContainsKey(classContract.StableName)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeCannotBeImported, typeName.Name, typeName.Namespace, SR.GetString(SR.CircularTypeReference, classContract.StableName.Name, classContract.StableName.Namespace)))); contractNamesInHierarchy.Add(classContract.StableName, null); ClassDataContract baseContract = classContract.BaseContract; if (baseContract != null) { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(baseContract); if (!baseContractCodeDomInfo.IsProcessed) { ExportClassDataContractHierarchy(typeName, baseContract, baseContractCodeDomInfo, contractNamesInHierarchy); baseContractCodeDomInfo.IsProcessed = true; } } ExportClassDataContract(classContract, contractCodeDomInfo); } void InvokeProcessImportedType(CollectionBase collection) { object[] objects = new object[collection.Count]; ((ICollection)collection).CopyTo(objects, 0); foreach (object obj in objects) { CodeTypeDeclaration codeTypeDeclaration = obj as CodeTypeDeclaration; if (codeTypeDeclaration == null) continue; CodeTypeDeclaration newCodeTypeDeclaration = DataContractSurrogateCaller.ProcessImportedType( dataContractSet.DataContractSurrogate, codeTypeDeclaration, codeCompileUnit); if (newCodeTypeDeclaration != codeTypeDeclaration) { ((IList)collection).Remove(codeTypeDeclaration); if (newCodeTypeDeclaration != null) ((IList)collection).Add(newCodeTypeDeclaration); } if(newCodeTypeDeclaration != null) InvokeProcessImportedType(newCodeTypeDeclaration.Members); } } internal CodeTypeReference GetCodeTypeReference(DataContract dataContract) { if (dataContract.IsBuiltInDataContract) return GetCodeTypeReference(dataContract.UnderlyingType); ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); GenerateType(dataContract, contractCodeDomInfo); return contractCodeDomInfo.TypeReference; } CodeTypeReference GetCodeTypeReference(Type type) { AddReferencedAssembly(type.Assembly); return new CodeTypeReference(type); } internal CodeTypeReference GetElementTypeReference(DataContract dataContract, bool isElementTypeNullable) { CodeTypeReference elementTypeReference = GetCodeTypeReference(dataContract); if (dataContract.IsValueType && isElementTypeNullable) elementTypeReference = WrapNullable(elementTypeReference); return elementTypeReference; } XmlQualifiedName GenericListName { get { return DataContract.GetStableName(Globals.TypeOfListGeneric); } } CollectionDataContract GenericListContract { get { return dataContractSet.GetDataContract(Globals.TypeOfListGeneric) as CollectionDataContract; } } XmlQualifiedName GenericDictionaryName { get { return DataContract.GetStableName(Globals.TypeOfDictionaryGeneric); } } CollectionDataContract GenericDictionaryContract { get { return dataContractSet.GetDataContract(Globals.TypeOfDictionaryGeneric) as CollectionDataContract; } } ContractCodeDomInfo GetContractCodeDomInfo(DataContract dataContract) { ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(dataContract); if (contractCodeDomInfo == null) { contractCodeDomInfo = new ContractCodeDomInfo(); dataContractSet.SetContractCodeDomInfo(dataContract, contractCodeDomInfo); } return contractCodeDomInfo; } void GenerateType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { if (!contractCodeDomInfo.IsProcessed) { CodeTypeReference referencedType = GetReferencedType(dataContract); if (referencedType != null) { contractCodeDomInfo.TypeReference = referencedType; contractCodeDomInfo.ReferencedTypeExists = true; } else { CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (type == null) { string clrNamespace = GetClrNamespace(dataContract, contractCodeDomInfo); CodeNamespace ns = GetCodeNamespace(clrNamespace, dataContract.StableName.Namespace, contractCodeDomInfo); type = GetNestedType(dataContract, contractCodeDomInfo); if (type == null) { string typeName = XmlConvert.DecodeName(dataContract.StableName.Name); typeName = GetClrIdentifier(typeName, Globals.DefaultTypeName); if (NamespaceContainsType(ns, typeName) || GlobalTypeNameConflicts(clrNamespace, typeName)) { for (int i = 1; ; i++) { string uniqueName = AppendToValidClrIdentifier(typeName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!NamespaceContainsType(ns, uniqueName) && !GlobalTypeNameConflicts(clrNamespace, uniqueName)) { typeName = uniqueName; break; } if(i == Int32.MaxValue) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, typeName))); } } type = CreateTypeDeclaration(typeName, dataContract); ns.Types.Add(type); if (string.IsNullOrEmpty(clrNamespace)) { AddGlobalTypeName(typeName); } contractCodeDomInfo.TypeReference = new CodeTypeReference((clrNamespace == null || clrNamespace.Length == 0) ? typeName : clrNamespace+"."+typeName); if (GenerateInternalTypes) type.TypeAttributes = TypeAttributes.NotPublic; else type.TypeAttributes = TypeAttributes.Public; } if (dataContractSet.DataContractSurrogate != null) type.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataContract)); contractCodeDomInfo.TypeDeclaration = type; } } } } CodeTypeDeclaration GetNestedType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { if (!SupportsNestedTypes) return null; string originalName = dataContract.StableName.Name; int nestedTypeIndex = originalName.LastIndexOf('.'); if (nestedTypeIndex <= 0) return null; string containingTypeName = originalName.Substring(0, nestedTypeIndex); DataContract containingDataContract = dataContractSet[new XmlQualifiedName(containingTypeName, dataContract.StableName.Namespace)]; if (containingDataContract == null) return null; string nestedTypeName = XmlConvert.DecodeName(originalName.Substring(nestedTypeIndex+1)); nestedTypeName = GetClrIdentifier(nestedTypeName, Globals.DefaultTypeName); ContractCodeDomInfo containingContractCodeDomInfo = GetContractCodeDomInfo(containingDataContract); GenerateType(containingDataContract, containingContractCodeDomInfo); if (containingContractCodeDomInfo.ReferencedTypeExists) return null; CodeTypeDeclaration containingType = containingContractCodeDomInfo.TypeDeclaration; if (TypeContainsNestedType(containingType, nestedTypeName)) { for (int i = 1; ; i++) { string uniqueName = AppendToValidClrIdentifier(nestedTypeName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!TypeContainsNestedType(containingType, uniqueName)) { nestedTypeName = uniqueName; break; } } } CodeTypeDeclaration type = CreateTypeDeclaration(nestedTypeName, dataContract); containingType.Members.Add(type); contractCodeDomInfo.TypeReference = new CodeTypeReference(containingContractCodeDomInfo.TypeReference.BaseType + "+" + nestedTypeName); if (GenerateInternalTypes) type.TypeAttributes = TypeAttributes.NestedAssembly; else type.TypeAttributes = TypeAttributes.NestedPublic; return type; } static CodeTypeDeclaration CreateTypeDeclaration(string typeName, DataContract dataContract) { CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeName); CodeAttributeDeclaration debuggerStepThroughAttribute = new CodeAttributeDeclaration(typeof(System.Diagnostics.DebuggerStepThroughAttribute).FullName); CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration(typeof(GeneratedCodeAttribute).FullName); AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName(); generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name))); generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Version.ToString()))); // System.Diagnostics.DebuggerStepThroughAttribute not allowed on enums // ensure that the attribute is only generated on types that are not enums EnumDataContract enumDataContract = dataContract as EnumDataContract; if (enumDataContract == null) { typeDecl.CustomAttributes.Add(debuggerStepThroughAttribute); } typeDecl.CustomAttributes.Add(generatedCodeAttribute); return typeDecl; } [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal XmlDataContract.", Safe = "Called during schema import/code generation.")] [SecuritySafeCritical] CodeTypeReference GetReferencedType(DataContract dataContract) { Type type = null; CodeTypeReference typeReference = GetSurrogatedTypeReference(dataContract); if(typeReference != null) return typeReference; if (TryGetReferencedType(dataContract.StableName, dataContract, out type) && !type.IsGenericTypeDefinition && !type.ContainsGenericParameters) { if (dataContract is XmlDataContract) { if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type)) { XmlDataContract xmlContract = (XmlDataContract)dataContract; if(xmlContract.IsTypeDefinedOnImport) { if(!xmlContract.Equals(dataContractSet.GetDataContract(type))) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace))); } else { xmlContract.IsValueType = type.IsValueType; xmlContract.IsTypeDefinedOnImport = true; } return GetCodeTypeReference(type); } throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeMustBeIXmlSerializable, DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable), dataContract.StableName.Name, dataContract.StableName.Namespace))); } DataContract referencedContract = dataContractSet.GetDataContract(type); if (referencedContract.Equals(dataContract)) { typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); return typeReference; } throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace))); } else if (dataContract.GenericInfo != null) { DataContract referencedContract; XmlQualifiedName genericStableName = dataContract.GenericInfo.GetExpandedStableName(); if(genericStableName != dataContract.StableName) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericTypeNameMismatch, dataContract.StableName.Name, dataContract.StableName.Namespace, genericStableName.Name, genericStableName.Namespace))); typeReference = GetReferencedGenericType(dataContract.GenericInfo, out referencedContract); if (referencedContract != null && !referencedContract.Equals(dataContract)) { type = (Type)typeReference.UserData[codeUserDataActualTypeKey]; throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, referencedContract.StableName.Name, referencedContract.StableName.Namespace))); } return typeReference; } return GetReferencedCollectionType(dataContract as CollectionDataContract); } CodeTypeReference GetReferencedCollectionType(CollectionDataContract collectionContract) { if (collectionContract == null) return null; if (HasDefaultCollectionNames(collectionContract)) { CodeTypeReference typeReference; if (!TryGetReferencedDictionaryType(collectionContract, out typeReference)) { DataContract itemContract = collectionContract.ItemContract; if (collectionContract.IsDictionary) { GenerateKeyValueType(itemContract as ClassDataContract); } bool isItemTypeNullable = collectionContract.IsItemTypeNullable; if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out typeReference)) typeReference = new CodeTypeReference(GetElementTypeReference(itemContract, isItemTypeNullable), 1); } return typeReference; } return null; } bool HasDefaultCollectionNames(CollectionDataContract collectionContract) { DataContract itemContract = collectionContract.ItemContract; if (collectionContract.ItemName != itemContract.StableName.Name) return false; if (collectionContract.IsDictionary && (collectionContract.KeyName != Globals.KeyLocalName || collectionContract.ValueName != Globals.ValueLocalName)) return false; XmlQualifiedName expectedType = itemContract.GetArrayTypeName(collectionContract.IsItemTypeNullable); return (collectionContract.StableName.Name == expectedType.Name && collectionContract.StableName.Namespace == expectedType.Namespace); } bool TryGetReferencedDictionaryType(CollectionDataContract collectionContract, out CodeTypeReference typeReference) { // Check if it is a dictionary and use referenced dictionary type if present if (collectionContract.IsDictionary && SupportsGenericTypeReference) { Type type; if (!TryGetReferencedType(GenericDictionaryName, GenericDictionaryContract, out type)) type = Globals.TypeOfDictionaryGeneric; ClassDataContract itemContract = collectionContract.ItemContract as ClassDataContract; DataMember keyMember = itemContract.Members[0]; DataMember valueMember = itemContract.Members[1]; CodeTypeReference keyTypeReference = GetElementTypeReference(keyMember.MemberTypeContract, keyMember.IsNullable); CodeTypeReference valueTypeReference = GetElementTypeReference(valueMember.MemberTypeContract, valueMember.IsNullable); if (keyTypeReference != null && valueTypeReference != null) { typeReference = GetCodeTypeReference(type); typeReference.TypeArguments.Add(keyTypeReference); typeReference.TypeArguments.Add(valueTypeReference); return true; } } typeReference = null; return false; } bool TryGetReferencedListType(DataContract itemContract, bool isItemTypeNullable, out CodeTypeReference typeReference) { Type type; if (SupportsGenericTypeReference && TryGetReferencedType(GenericListName, GenericListContract, out type)) { typeReference = GetCodeTypeReference(type); typeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable)); return true; } typeReference = null; return false; } CodeTypeReference GetSurrogatedTypeReference(DataContract dataContract) { IDataContractSurrogate dataContractSurrogate = this.dataContractSet.DataContractSurrogate; if (dataContractSurrogate != null) { Type type = DataContractSurrogateCaller.GetReferencedTypeOnImport( dataContractSurrogate, dataContract.StableName.Name, dataContract.StableName.Namespace, dataContractSet.GetSurrogateData(dataContract)); if (type != null) { CodeTypeReference typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); return typeReference; } } return null; } CodeTypeReference GetReferencedGenericType(GenericInfo genInfo, out DataContract dataContract) { dataContract = null; if (!SupportsGenericTypeReference) return null; Type type; if (!TryGetReferencedType(genInfo.StableName, null, out type)) { if(genInfo.Parameters != null) return null; dataContract = dataContractSet[genInfo.StableName]; if (dataContract == null) return null; if (dataContract.GenericInfo != null) return null; return GetCodeTypeReference(dataContract); } bool enableStructureCheck = (type != Globals.TypeOfNullable); CodeTypeReference typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); if (genInfo.Parameters != null) { DataContract[] paramContracts = new DataContract[genInfo.Parameters.Count]; for(int i=0;i ()); } return typeReference; } bool NamespaceContainsType(CodeNamespace ns, string typeName) { foreach (CodeTypeDeclaration type in ns.Types) { if (String.Compare(typeName, type.Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } return false; } bool GlobalTypeNameConflicts(string clrNamespace, string typeName) { return (string.IsNullOrEmpty(clrNamespace) && this.clrNamespaces.ContainsKey(typeName)); } void AddGlobalTypeName(string typeName) { if (!this.clrNamespaces.ContainsKey(typeName)) { this.clrNamespaces.Add(typeName, null); } } bool TypeContainsNestedType(CodeTypeDeclaration containingType, string typeName) { foreach (CodeTypeMember member in containingType.Members) { if (member is CodeTypeDeclaration) { if (String.Compare(typeName, ((CodeTypeDeclaration)member).Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } } return false; } string GetNameForAttribute(string name) { string decodedName = XmlConvert.DecodeName(name); if (string.CompareOrdinal(name, decodedName) == 0) return name; string reencodedName = DataContract.EncodeLocalName(decodedName); return (string.CompareOrdinal(name, reencodedName) == 0) ? decodedName : name; } void AddSerializableAttribute(bool generateSerializable, CodeTypeDeclaration type, ContractCodeDomInfo contractCodeDomInfo) { if (generateSerializable) { type.CustomAttributes.Add(SerializableAttribute); AddImportStatement(Globals.TypeOfSerializableAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } } void ExportClassDataContract(ClassDataContract classDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(classDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if (classDataContract.IsValueType && SupportsDeclareValueTypes) type.IsStruct = true; else type.IsClass = true; string dataContractName = GetNameForAttribute(classDataContract.StableName.Name); CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute)); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(classDataContract.StableName.Namespace))); if (classDataContract.IsReference != Globals.DefaultIsReference) dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(classDataContract.IsReference))); type.CustomAttributes.Add(dataContractAttribute); AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo); AddKnownTypes(classDataContract, contractCodeDomInfo); if (classDataContract.BaseContract == null) { if (!type.IsStruct) type.BaseTypes.Add(Globals.TypeOfObject); AddExtensionData(contractCodeDomInfo); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } else { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(classDataContract.BaseContract); Fx.Assert(baseContractCodeDomInfo.IsProcessed, "Cannot generate code for type if code for base type has not been generated"); type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); AddBaseMemberNames(baseContractCodeDomInfo, contractCodeDomInfo); if (baseContractCodeDomInfo.ReferencedTypeExists) { Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey]; ThrowIfReferencedBaseTypeSealed(actualType, classDataContract); if(!Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(actualType)) AddExtensionData(contractCodeDomInfo); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } } if (classDataContract.Members != null) { for (int i=0; i < classDataContract.Members.Count; i++) { DataMember dataMember = classDataContract.Members[i]; CodeTypeReference memberType = GetElementTypeReference(dataMember.MemberTypeContract, (dataMember.IsNullable && dataMember.MemberTypeContract.IsValueType)); string dataMemberName = GetNameForAttribute(dataMember.Name); string propertyName = GetMemberName(dataMemberName, contractCodeDomInfo); string fieldName = GetMemberName(AppendToValidClrIdentifier(propertyName, Globals.DefaultFieldSuffix), contractCodeDomInfo); CodeMemberField field = new CodeMemberField(); field.Type = memberType; field.Name = fieldName; field.Attributes = MemberAttributes.Private; CodeMemberProperty property = CreateProperty(memberType, propertyName, fieldName, dataMember.MemberTypeContract.IsValueType && SupportsDeclareValueTypes); if (dataContractSet.DataContractSurrogate != null) property.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataMember)); CodeAttributeDeclaration dataMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataMemberAttribute)); if (dataMemberName != property.Name) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataMemberName))); if (dataMember.IsRequired != Globals.DefaultIsRequired) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsRequiredProperty, new CodePrimitiveExpression(dataMember.IsRequired))); if (dataMember.EmitDefaultValue!= Globals.DefaultEmitDefaultValue) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.EmitDefaultValueProperty, new CodePrimitiveExpression(dataMember.EmitDefaultValue))); if (dataMember.Order != Globals.DefaultOrder) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.OrderProperty, new CodePrimitiveExpression(dataMember.Order))); property.CustomAttributes.Add(dataMemberAttribute); if (GenerateSerializableTypes && !dataMember.IsRequired) { CodeAttributeDeclaration optionalFieldAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfOptionalFieldAttribute)); field.CustomAttributes.Add(optionalFieldAttribute); } type.Members.Add(field); type.Members.Add(property); } } } bool CanDeclareAssemblyAttribute(ContractCodeDomInfo contractCodeDomInfo) { return SupportsAssemblyAttributes && !contractCodeDomInfo.UsesWildcardNamespace; } bool NeedsExplicitNamespace(string dataContractNamespace, string clrNamespace) { return (DataContract.GetDefaultStableNamespace(clrNamespace) != dataContractNamespace); } internal ICollection GetKnownTypeReferences(DataContract dataContract) { DataContractDictionary knownTypeDictionary = GetKnownTypeContracts(dataContract); if (knownTypeDictionary == null) return null; ICollection knownTypeContracts = knownTypeDictionary.Values; if (knownTypeContracts == null || knownTypeContracts.Count == 0) return null; List knownTypeReferences = new List (); foreach (DataContract knownTypeContract in knownTypeContracts) { knownTypeReferences.Add(GetCodeTypeReference(knownTypeContract)); } return knownTypeReferences; } DataContractDictionary GetKnownTypeContracts(DataContract dataContract) { if (dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(dataContract)) { return dataContractSet.KnownTypesForObject; } else if (dataContract is ClassDataContract) { ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (!contractCodeDomInfo.IsProcessed) GenerateType(dataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return GetKnownTypeContracts((ClassDataContract)dataContract, new Dictionary ()); } return null; } DataContractDictionary GetKnownTypeContracts(ClassDataContract dataContract, Dictionary handledContracts) { if (handledContracts.ContainsKey(dataContract)) return dataContract.KnownDataContracts; handledContracts.Add(dataContract, null); if (dataContract.Members != null) { bool objectMemberHandled = false; foreach (DataMember dataMember in dataContract.Members) { DataContract memberContract = dataMember.MemberTypeContract; if (!objectMemberHandled && dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(memberContract)) { AddKnownTypeContracts(dataContract, dataContractSet.KnownTypesForObject); objectMemberHandled = true; } else if (memberContract is ClassDataContract) { ContractCodeDomInfo memberCodeDomInfo = GetContractCodeDomInfo(memberContract); if (!memberCodeDomInfo.IsProcessed) GenerateType(memberContract, memberCodeDomInfo); if (memberCodeDomInfo.ReferencedTypeExists) { AddKnownTypeContracts(dataContract, GetKnownTypeContracts((ClassDataContract)memberContract, handledContracts)); } } } } return dataContract.KnownDataContracts; } [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal DataContract.", Safe = "Called during schema import/code generation.")] [SecuritySafeCritical] void AddKnownTypeContracts(ClassDataContract dataContract, DataContractDictionary knownContracts) { if (knownContracts == null || knownContracts.Count == 0) return; if (dataContract.KnownDataContracts == null) dataContract.KnownDataContracts = new DataContractDictionary(); foreach (KeyValuePair pair in knownContracts) { if (dataContract.StableName != pair.Key && !dataContract.KnownDataContracts.ContainsKey(pair.Key) && !pair.Value.IsBuiltInDataContract) dataContract.KnownDataContracts.Add(pair.Key, pair.Value); } } void AddKnownTypes(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { DataContractDictionary knownContractDictionary = GetKnownTypeContracts(dataContract, new Dictionary ()); if (knownContractDictionary == null || knownContractDictionary.Count == 0) return; ICollection knownTypeContracts = knownContractDictionary.Values; foreach (DataContract knownTypeContract in knownTypeContracts) { CodeAttributeDeclaration knownTypeAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfKnownTypeAttribute)); knownTypeAttribute.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(GetCodeTypeReference(knownTypeContract)))); contractCodeDomInfo.TypeDeclaration.CustomAttributes.Add(knownTypeAttribute); } AddImportStatement(Globals.TypeOfKnownTypeAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } CodeTypeReference WrapNullable(CodeTypeReference memberType) { if (!SupportsGenericTypeReference) return memberType; CodeTypeReference nullableOfMemberType = GetCodeTypeReference(Globals.TypeOfNullable); nullableOfMemberType.TypeArguments.Add(memberType); return nullableOfMemberType; } void AddExtensionData(ContractCodeDomInfo contractCodeDomInfo) { if(contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null) { CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIExtensibleDataObject)); CodeMemberField extensionDataObjectField = ExtensionDataObjectField; if (GenerateSerializableTypes) { CodeAttributeDeclaration nonSerializedAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfNonSerializedAttribute)); extensionDataObjectField.CustomAttributes.Add(nonSerializedAttribute); } type.Members.Add(extensionDataObjectField); contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectField.Name, null); CodeMemberProperty extensionDataObjectProperty = ExtensionDataObjectProperty; type.Members.Add(extensionDataObjectProperty); contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectProperty.Name, null); } } void AddPropertyChangedNotifier(ContractCodeDomInfo contractCodeDomInfo, bool isValueType) { if (EnableDataBinding && SupportsDeclareEvents && contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null) { CodeTypeDeclaration codeTypeDeclaration = contractCodeDomInfo.TypeDeclaration; codeTypeDeclaration.BaseTypes.Add(CodeTypeIPropertyChange); CodeMemberEvent memberEvent = PropertyChangedEvent; codeTypeDeclaration.Members.Add(memberEvent); CodeMemberMethod raisePropertyChangedEventMethod = RaisePropertyChangedEventMethod; if (!isValueType) raisePropertyChangedEventMethod.Attributes |= MemberAttributes.Family; codeTypeDeclaration.Members.Add(raisePropertyChangedEventMethod); contractCodeDomInfo.GetMemberNames().Add(memberEvent.Name, null); contractCodeDomInfo.GetMemberNames().Add(raisePropertyChangedEventMethod.Name, null); } } void ThrowIfReferencedBaseTypeSealed(Type baseType, DataContract dataContract) { if (baseType.IsSealed) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotDeriveFromSealedReferenceType, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetClrTypeFullName(baseType)))); } void ExportEnumDataContract(EnumDataContract enumDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(enumDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; type.IsEnum = true; type.BaseTypes.Add(EnumDataContract.GetBaseType(enumDataContract.BaseContractName)); if (enumDataContract.IsFlags) { type.CustomAttributes.Add(new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfFlagsAttribute))); AddImportStatement(Globals.TypeOfFlagsAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } string dataContractName = GetNameForAttribute(enumDataContract.StableName.Name); CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute)); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(enumDataContract.StableName.Namespace))); type.CustomAttributes.Add(dataContractAttribute); AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); if (enumDataContract.Members != null) { for (int i=0; i < enumDataContract.Members.Count; i++) { string stringValue = enumDataContract.Members[i].Name; long longValue = enumDataContract.Values[i]; CodeMemberField enumMember = new CodeMemberField(); if (enumDataContract.IsULong) enumMember.InitExpression = new CodeSnippetExpression(enumDataContract.GetStringFromEnumValue(longValue)); else enumMember.InitExpression = new CodePrimitiveExpression(longValue); enumMember.Name = GetMemberName(stringValue, contractCodeDomInfo); CodeAttributeDeclaration enumMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfEnumMemberAttribute)); if (enumMember.Name != stringValue) enumMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueProperty, new CodePrimitiveExpression(stringValue))); enumMember.CustomAttributes.Add(enumMemberAttribute); type.Members.Add(enumMember); } } } void ExportISerializableDataContract(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(dataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; if (DataContract.GetDefaultStableNamespace(contractCodeDomInfo.ClrNamespace) != dataContract.StableName.Namespace) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNamespaceGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetDataContractNamespaceFromUri(dataContract.StableName.Namespace), contractCodeDomInfo.ClrNamespace))); string dataContractName = GetNameForAttribute(dataContract.StableName.Name); int nestedTypeIndex = dataContractName.LastIndexOf('.'); string expectedName = (nestedTypeIndex <= 0 || nestedTypeIndex == dataContractName.Length-1) ? dataContractName : dataContractName.Substring(nestedTypeIndex+1); if (contractCodeDomInfo.TypeDeclaration.Name != expectedName) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNameGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, contractCodeDomInfo.TypeDeclaration.Name))); CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if (dataContract.IsValueType && SupportsDeclareValueTypes) type.IsStruct = true; else type.IsClass = true; AddSerializableAttribute(true /*generateSerializable*/, type, contractCodeDomInfo); AddKnownTypes(dataContract, contractCodeDomInfo); if (dataContract.BaseContract == null) { if (!type.IsStruct) type.BaseTypes.Add(Globals.TypeOfObject); type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfISerializable)); type.Members.Add(ISerializableBaseConstructor); type.Members.Add(SerializationInfoField); type.Members.Add(SerializationInfoProperty); type.Members.Add(GetObjectDataMethod); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } else { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(dataContract.BaseContract); GenerateType(dataContract.BaseContract, baseContractCodeDomInfo); type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); if (baseContractCodeDomInfo.ReferencedTypeExists) { Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey]; ThrowIfReferencedBaseTypeSealed(actualType, dataContract); } type.Members.Add(ISerializableDerivedConstructor); } } void GenerateKeyValueType(ClassDataContract keyValueContract) { // Add code for KeyValue item type in the case where its usage is limited to dictionary // and dictionary is not found in referenced types if (keyValueContract != null && dataContractSet[keyValueContract.StableName] == null) { ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(keyValueContract); if (contractCodeDomInfo == null) { contractCodeDomInfo = new ContractCodeDomInfo(); dataContractSet.SetContractCodeDomInfo(keyValueContract, contractCodeDomInfo); ExportClassDataContract(keyValueContract, contractCodeDomInfo); contractCodeDomInfo.IsProcessed = true; } } } void ExportCollectionDataContract(CollectionDataContract collectionContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(collectionContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; string dataContractName = GetNameForAttribute(collectionContract.StableName.Name); // If type name is not expected, generate collection type that derives from referenced list type and uses [CollectionDataContract] if (!SupportsGenericTypeReference) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.CannotUseGenericTypeAsBase, dataContractName, collectionContract.StableName.Namespace))); DataContract itemContract = collectionContract.ItemContract; bool isItemTypeNullable = collectionContract.IsItemTypeNullable; CodeTypeReference baseTypeReference; bool foundDictionaryBase = TryGetReferencedDictionaryType(collectionContract, out baseTypeReference); if (!foundDictionaryBase) { if (collectionContract.IsDictionary) { GenerateKeyValueType(collectionContract.ItemContract as ClassDataContract); } if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out baseTypeReference)) { if (SupportsGenericTypeReference) { baseTypeReference = GetCodeTypeReference(Globals.TypeOfListGeneric); baseTypeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable)); } else { string expectedTypeName = Globals.ArrayPrefix + itemContract.StableName.Name; string expectedTypeNs = DataContract.GetCollectionNamespace(itemContract.StableName.Namespace); throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedBaseTypeDoesNotExist, dataContractName, collectionContract.StableName.Namespace, expectedTypeName, expectedTypeNs, DataContract.GetClrTypeFullName(Globals.TypeOfIListGeneric), DataContract.GetClrTypeFullName(Globals.TypeOfICollectionGeneric)))); } } } CodeTypeDeclaration generatedType = contractCodeDomInfo.TypeDeclaration; generatedType.BaseTypes.Add(baseTypeReference); CodeAttributeDeclaration collectionContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfCollectionDataContractAttribute)); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(collectionContract.StableName.Namespace))); if (collectionContract.IsReference != Globals.DefaultIsReference) collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(collectionContract.IsReference))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ItemNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ItemName)))); if (foundDictionaryBase) { collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.KeyNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.KeyName)))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ValueName)))); } generatedType.CustomAttributes.Add(collectionContractAttribute); AddImportStatement(Globals.TypeOfCollectionDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); AddSerializableAttribute(GenerateSerializableTypes, generatedType, contractCodeDomInfo); } private void ExportXmlDataContract(XmlDataContract xmlDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(xmlDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if(xmlDataContract.IsValueType) type.IsStruct = true; else { type.IsClass = true; type.BaseTypes.Add(Globals.TypeOfObject); } AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo); type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable)); type.Members.Add(NodeArrayField); type.Members.Add(NodeArrayProperty); type.Members.Add(ReadXmlMethod); type.Members.Add(WriteXmlMethod); type.Members.Add(GetSchemaMethod); if (xmlDataContract.IsAnonymous && !xmlDataContract.HasRoot) { type.CustomAttributes.Add(new CodeAttributeDeclaration( DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute), new CodeAttributeArgument(NullReference), new CodeAttributeArgument(Globals.IsAnyProperty, new CodePrimitiveExpression(true))) ); } else { type.CustomAttributes.Add(new CodeAttributeDeclaration( DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute), new CodeAttributeArgument(new CodePrimitiveExpression(Globals.ExportSchemaMethod))) ); CodeMemberField typeNameField = new CodeMemberField(Globals.TypeOfXmlQualifiedName, typeNameFieldName); typeNameField.Attributes |= MemberAttributes.Static | MemberAttributes.Private; XmlQualifiedName typeName = xmlDataContract.IsAnonymous ? SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, xmlDataContract.StableName, xmlDataContract.StableName) : xmlDataContract.StableName; typeNameField.InitExpression = new CodeObjectCreateExpression(Globals.TypeOfXmlQualifiedName, new CodePrimitiveExpression(typeName.Name), new CodePrimitiveExpression(typeName.Namespace)); type.Members.Add(typeNameField); type.Members.Add(GetSchemaStaticMethod); bool isElementNameDifferent = (xmlDataContract.TopLevelElementName != null && xmlDataContract.TopLevelElementName.Value != xmlDataContract.StableName.Name) || (xmlDataContract.TopLevelElementNamespace != null && xmlDataContract.TopLevelElementNamespace.Value != xmlDataContract.StableName.Namespace); if (isElementNameDifferent || xmlDataContract.IsTopLevelElementNullable == false) { CodeAttributeDeclaration xmlRootAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfXmlRootAttribute)); if (isElementNameDifferent) { if (xmlDataContract.TopLevelElementName != null) { xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("ElementName", new CodePrimitiveExpression(xmlDataContract.TopLevelElementName.Value))); } if (xmlDataContract.TopLevelElementNamespace != null) { xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(xmlDataContract.TopLevelElementNamespace.Value))); } } if (xmlDataContract.IsTopLevelElementNullable == false) xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("IsNullable", new CodePrimitiveExpression(false))); type.CustomAttributes.Add(xmlRootAttribute); } } AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } CodeNamespace GetCodeNamespace(string clrNamespace, string dataContractNamespace, ContractCodeDomInfo contractCodeDomInfo) { if (contractCodeDomInfo.CodeNamespace != null) return contractCodeDomInfo.CodeNamespace; CodeNamespaceCollection codeNamespaceCollection = codeCompileUnit.Namespaces; foreach (CodeNamespace ns in codeNamespaceCollection) { if (ns.Name == clrNamespace) { contractCodeDomInfo.CodeNamespace = ns; return ns; } } CodeNamespace codeNamespace = new CodeNamespace(clrNamespace); codeNamespaceCollection.Add(codeNamespace); if (CanDeclareAssemblyAttribute(contractCodeDomInfo) && NeedsExplicitNamespace(dataContractNamespace, clrNamespace)) { CodeAttributeDeclaration namespaceAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfContractNamespaceAttribute)); namespaceAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(dataContractNamespace))); namespaceAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ClrNamespaceProperty, new CodePrimitiveExpression(clrNamespace))); codeCompileUnit.AssemblyCustomAttributes.Add(namespaceAttribute); } contractCodeDomInfo.CodeNamespace = codeNamespace; return codeNamespace; } string GetMemberName(string memberName, ContractCodeDomInfo contractCodeDomInfo) { memberName = GetClrIdentifier(memberName, Globals.DefaultGeneratedMember); if (memberName == contractCodeDomInfo.TypeDeclaration.Name) memberName = AppendToValidClrIdentifier(memberName, Globals.DefaultMemberSuffix); if (contractCodeDomInfo.GetMemberNames().ContainsKey(memberName)) { string uniqueMemberName = null; for (int i = 1; ; i++) { uniqueMemberName = AppendToValidClrIdentifier(memberName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!contractCodeDomInfo.GetMemberNames().ContainsKey(uniqueMemberName)) { memberName = uniqueMemberName; break; } } } contractCodeDomInfo.GetMemberNames().Add(memberName, null); return memberName; } void AddBaseMemberNames(ContractCodeDomInfo baseContractCodeDomInfo, ContractCodeDomInfo contractCodeDomInfo) { if (!baseContractCodeDomInfo.ReferencedTypeExists) { Dictionary baseMemberNames = baseContractCodeDomInfo.GetMemberNames(); Dictionary memberNames = contractCodeDomInfo.GetMemberNames(); foreach (KeyValuePair pair in baseMemberNames) { memberNames.Add(pair.Key, pair.Value); } } } static string GetClrIdentifier(string identifier, string defaultIdentifier) { if (identifier.Length <= MaxIdentifierLength && System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(identifier)) return identifier; bool isStart = true; StringBuilder builder = new StringBuilder(); for (int i = 0; i < identifier.Length && builder.Length < MaxIdentifierLength; i++) { char c = identifier[i]; if (IsValid(c)) { if (isStart && !IsValidStart(c)) builder.Append("_"); builder.Append(c); isStart = false; } } if (builder.Length == 0) return defaultIdentifier; return builder.ToString(); } static string AppendToValidClrIdentifier(string identifier, string appendString) { int availableLength = MaxIdentifierLength - identifier.Length; int requiredLength = appendString.Length; if (availableLength < requiredLength) identifier = identifier.Substring(0, MaxIdentifierLength - requiredLength); identifier += appendString; return identifier; } string GetClrNamespace(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { string clrNamespace = contractCodeDomInfo.ClrNamespace; bool usesWildcardNamespace = false; if (clrNamespace == null) { if (!Namespaces.TryGetValue(dataContract.StableName.Namespace, out clrNamespace)) { if (Namespaces.TryGetValue(wildcardNamespaceMapping, out clrNamespace)) { usesWildcardNamespace = true; } else { clrNamespace = GetClrNamespace(dataContract.StableName.Namespace); if (ClrNamespaces.ContainsKey(clrNamespace)) { string uniqueNamespace = null; for (int i = 1; ; i++) { uniqueNamespace = ((clrNamespace.Length == 0) ? Globals.DefaultClrNamespace : clrNamespace) + i.ToString(NumberFormatInfo.InvariantInfo); if (!ClrNamespaces.ContainsKey(uniqueNamespace)) { clrNamespace = uniqueNamespace; break; } } } AddNamespacePair(dataContract.StableName.Namespace, clrNamespace); } } contractCodeDomInfo.ClrNamespace = clrNamespace; contractCodeDomInfo.UsesWildcardNamespace = usesWildcardNamespace; } return clrNamespace; } void AddNamespacePair(string dataContractNamespace, string clrNamespace) { Namespaces.Add(dataContractNamespace, clrNamespace); ClrNamespaces.Add(clrNamespace, dataContractNamespace); } void AddImportStatement(string clrNamespace, CodeNamespace codeNamespace) { if (clrNamespace == codeNamespace.Name) return; CodeNamespaceImportCollection importCollection = codeNamespace.Imports; foreach (CodeNamespaceImport import in importCollection) { if (import.Namespace == clrNamespace) return; } importCollection.Add(new CodeNamespaceImport(clrNamespace)); } static string GetClrNamespace(string dataContractNamespace) { if (dataContractNamespace == null || dataContractNamespace.Length == 0) return String.Empty; Uri uri = null; StringBuilder builder = new StringBuilder(); if (Uri.TryCreate(dataContractNamespace, UriKind.RelativeOrAbsolute, out uri)) { Dictionary fragments = new Dictionary (StringComparer.OrdinalIgnoreCase); if (!uri.IsAbsoluteUri) AddToNamespace(builder, uri.OriginalString, fragments); else { string uriString = uri.AbsoluteUri; if (uriString.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal)) AddToNamespace(builder, uriString.Substring(Globals.DataContractXsdBaseNamespace.Length), fragments); else { string host = uri.Host; if (host != null) AddToNamespace(builder, host, fragments); string path = uri.PathAndQuery; if (path != null) AddToNamespace(builder, path, fragments); } } } if (builder.Length == 0) return String.Empty; int length = builder.Length; if (builder[builder.Length-1] == '.') length--; length = Math.Min(MaxIdentifierLength, length); return builder.ToString(0, length); } static void AddToNamespace(StringBuilder builder, string fragment, Dictionary fragments) { if (fragment == null) return; bool isStart = true; int fragmentOffset = builder.Length; int fragmentLength = 0; for (int i = 0; i < fragment.Length && builder.Length < MaxIdentifierLength; i++) { char c = fragment[i]; if (IsValid(c)) { if (isStart && !IsValidStart(c)) builder.Append("_"); builder.Append(c); fragmentLength++; isStart = false; } else if ((c == '.' || c == '/' || c == ':') && (builder.Length == 1 || (builder.Length > 1 && builder[builder.Length-1] != '.'))) { AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments); builder.Append('.'); fragmentOffset = builder.Length; fragmentLength = 0; isStart = true; } } AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments); } static void AddNamespaceFragment(StringBuilder builder, int fragmentOffset, int fragmentLength, Dictionary fragments) { if (fragmentLength == 0) return; string nsFragment = builder.ToString(fragmentOffset, fragmentLength); if (fragments.ContainsKey(nsFragment)) { for (int i = 1; ; i++) { string uniquifier = i.ToString(NumberFormatInfo.InvariantInfo); string uniqueNsFragment = AppendToValidClrIdentifier(nsFragment, uniquifier); if (!fragments.ContainsKey(uniqueNsFragment)) { builder.Append(uniquifier); nsFragment = uniqueNsFragment; break; } if (i == Int32.MaxValue) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, nsFragment))); } } fragments.Add(nsFragment, null); } static bool IsValidStart(char c) { return (Char.GetUnicodeCategory(c) != UnicodeCategory.DecimalDigitNumber); } static bool IsValid(char c) { UnicodeCategory uc = Char.GetUnicodeCategory(c); // each char must be Lu, Ll, Lt, Lm, Lo, Nd, Mn, Mc, Pc switch (uc) { case UnicodeCategory.UppercaseLetter: // Lu case UnicodeCategory.LowercaseLetter: // Ll case UnicodeCategory.TitlecaseLetter: // Lt case UnicodeCategory.ModifierLetter: // Lm case UnicodeCategory.OtherLetter: // Lo case UnicodeCategory.DecimalDigitNumber: // Nd case UnicodeCategory.NonSpacingMark: // Mn case UnicodeCategory.SpacingCombiningMark: // Mc case UnicodeCategory.ConnectorPunctuation: // Pc return true; default: return false; } } CodeTypeReference CodeTypeIPropertyChange { get { return GetCodeTypeReference(typeof(System.ComponentModel.INotifyPropertyChanged)); } } CodeThisReferenceExpression ThisReference { get { return new CodeThisReferenceExpression(); } } CodePrimitiveExpression NullReference { get { return new CodePrimitiveExpression(null); } } CodeParameterDeclarationExpression SerializationInfoParameter { get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoFieldName); } } CodeParameterDeclarationExpression StreamingContextParameter { get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfStreamingContext), Globals.ContextFieldName); } } CodeAttributeDeclaration SerializableAttribute { get { return new CodeAttributeDeclaration(GetCodeTypeReference(Globals.TypeOfSerializableAttribute)); } } CodeMemberProperty NodeArrayProperty { get { return CreateProperty(GetCodeTypeReference(Globals.TypeOfXmlNodeArray),Globals.NodeArrayPropertyName, Globals.NodeArrayFieldName, false/*isValueType*/); } } CodeMemberField NodeArrayField { get { CodeMemberField nodeArrayField = new CodeMemberField(); nodeArrayField.Type = GetCodeTypeReference(Globals.TypeOfXmlNodeArray); nodeArrayField.Name = Globals.NodeArrayFieldName; nodeArrayField.Attributes = MemberAttributes.Private; return nodeArrayField; } } CodeMemberMethod ReadXmlMethod { get { CodeMemberMethod readXmlMethod = new CodeMemberMethod(); readXmlMethod.Name = "ReadXml"; CodeParameterDeclarationExpression readerArg = new CodeParameterDeclarationExpression(typeof(XmlReader), "reader"); readXmlMethod.Parameters.Add(readerArg); readXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; readXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); CodeAssignStatement setNode = new CodeAssignStatement(); setNode.Left = new CodeFieldReferenceExpression(ThisReference, Globals.NodeArrayFieldName); setNode.Right = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)), XmlSerializableServices.ReadNodesMethodName, new CodeArgumentReferenceExpression(readerArg.Name) ); readXmlMethod.Statements.Add(setNode); return readXmlMethod; } } CodeMemberMethod WriteXmlMethod { get { CodeMemberMethod writeXmlMethod = new CodeMemberMethod(); writeXmlMethod.Name = "WriteXml"; CodeParameterDeclarationExpression writerArg = new CodeParameterDeclarationExpression(typeof(XmlWriter), "writer"); writeXmlMethod.Parameters.Add(writerArg); writeXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; writeXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); writeXmlMethod.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)), XmlSerializableServices.WriteNodesMethodName, new CodeArgumentReferenceExpression(writerArg.Name), new CodePropertyReferenceExpression(ThisReference, Globals.NodeArrayPropertyName) ) ); return writeXmlMethod; } } CodeMemberMethod GetSchemaMethod { get { CodeMemberMethod getSchemaMethod = new CodeMemberMethod(); getSchemaMethod.Name = "GetSchema"; getSchemaMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; getSchemaMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); getSchemaMethod.ReturnType = GetCodeTypeReference(typeof(XmlSchema)); getSchemaMethod.Statements.Add(new CodeMethodReturnStatement(NullReference)); return getSchemaMethod; } } CodeMemberMethod GetSchemaStaticMethod { get { CodeMemberMethod getSchemaStaticMethod = new CodeMemberMethod(); getSchemaStaticMethod.Name = Globals.ExportSchemaMethod; getSchemaStaticMethod.ReturnType = GetCodeTypeReference(Globals.TypeOfXmlQualifiedName); CodeParameterDeclarationExpression paramDeclaration = new CodeParameterDeclarationExpression(Globals.TypeOfXmlSchemaSet, "schemas"); getSchemaStaticMethod.Parameters.Add(paramDeclaration); getSchemaStaticMethod.Attributes = MemberAttributes.Static | MemberAttributes.Public; getSchemaStaticMethod.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(typeof(XmlSerializableServices))), XmlSerializableServices.AddDefaultSchemaMethodName, new CodeArgumentReferenceExpression(paramDeclaration.Name), new CodeFieldReferenceExpression(null, typeNameFieldName) ) ); getSchemaStaticMethod.Statements.Add( new CodeMethodReturnStatement( new CodeFieldReferenceExpression(null, typeNameFieldName) ) ); return getSchemaStaticMethod; } } CodeConstructor ISerializableBaseConstructor { get { CodeConstructor baseConstructor = new CodeConstructor(); baseConstructor.Attributes = MemberAttributes.Public; baseConstructor.Parameters.Add(SerializationInfoParameter); baseConstructor.Parameters.Add(StreamingContextParameter); CodeAssignStatement setObjectData = new CodeAssignStatement(); setObjectData.Left = new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoFieldName); setObjectData.Right = new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName); baseConstructor.Statements.Add(setObjectData); // Special-cased check for vb here since CodeGeneratorOptions does not provide information indicating that VB cannot initialize event member if (EnableDataBinding && SupportsDeclareEvents && String.CompareOrdinal(FileExtension, "vb") != 0) { baseConstructor.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(ThisReference, PropertyChangedEvent.Name), NullReference)); } return baseConstructor; } } CodeConstructor ISerializableDerivedConstructor { get { CodeConstructor derivedConstructor = new CodeConstructor(); derivedConstructor.Attributes = MemberAttributes.Public; derivedConstructor.Parameters.Add(SerializationInfoParameter); derivedConstructor.Parameters.Add(StreamingContextParameter); derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.SerializationInfoFieldName)); derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.ContextFieldName)); return derivedConstructor; } } CodeMemberField SerializationInfoField { get { CodeMemberField serializationInfoField = new CodeMemberField(); serializationInfoField.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfo); serializationInfoField.Name = Globals.SerializationInfoFieldName; serializationInfoField.Attributes = MemberAttributes.Private; return serializationInfoField; } } CodeMemberProperty SerializationInfoProperty { get { return CreateProperty(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoPropertyName, Globals.SerializationInfoFieldName, false/*isValueType*/); } } CodeMemberMethod GetObjectDataMethod { get { CodeMemberMethod getObjectDataMethod = new CodeMemberMethod(); getObjectDataMethod.Name = Globals.GetObjectDataMethodName; getObjectDataMethod.Parameters.Add(SerializationInfoParameter); getObjectDataMethod.Parameters.Add(StreamingContextParameter); getObjectDataMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; getObjectDataMethod.ImplementationTypes.Add(Globals.TypeOfISerializable); // Generates: if (this.SerializationInfo == null) return; CodeConditionStatement returnIfNull = new CodeConditionStatement(); returnIfNull.Condition = new CodeBinaryOperatorExpression( new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName), CodeBinaryOperatorType.IdentityEquality, NullReference); returnIfNull.TrueStatements.Add(new CodeMethodReturnStatement()); // Generates: SerializationInfoEnumerator enumerator = this.SerializationInfo.GetEnumerator(); CodeVariableDeclarationStatement getEnumerator = new CodeVariableDeclarationStatement(); getEnumerator.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfoEnumerator); getEnumerator.Name = Globals.EnumeratorFieldName; getEnumerator.InitExpression = new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName), Globals.GetEnumeratorMethodName); //Generates: SerializationEntry entry = enumerator.Current; CodeVariableDeclarationStatement getCurrent = new CodeVariableDeclarationStatement(); getCurrent.Type = GetCodeTypeReference(Globals.TypeOfSerializationEntry); getCurrent.Name = Globals.SerializationEntryFieldName; getCurrent.InitExpression = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.EnumeratorFieldName), Globals.CurrentPropertyName); //Generates: info.AddValue(entry.Name, entry.Value); CodeExpressionStatement addValue = new CodeExpressionStatement(); CodePropertyReferenceExpression getCurrentName = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName), Globals.NameProperty); CodePropertyReferenceExpression getCurrentValue = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName), Globals.ValueProperty); addValue.Expression = new CodeMethodInvokeExpression( new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName), Globals.AddValueMethodName, new CodeExpression[] { getCurrentName, getCurrentValue }); //Generates: for (; enumerator.MoveNext(); ) CodeIterationStatement loop = new CodeIterationStatement(); loop.TestExpression = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression(Globals.EnumeratorFieldName), Globals.MoveNextMethodName); loop.InitStatement = loop.IncrementStatement = new CodeSnippetStatement(String.Empty); loop.Statements.Add(getCurrent); loop.Statements.Add(addValue); getObjectDataMethod.Statements.Add(returnIfNull); getObjectDataMethod.Statements.Add(getEnumerator); getObjectDataMethod.Statements.Add(loop); return getObjectDataMethod; } } CodeMemberField ExtensionDataObjectField { get { CodeMemberField extensionDataObjectField = new CodeMemberField(); extensionDataObjectField.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject); extensionDataObjectField.Name = Globals.ExtensionDataObjectFieldName; extensionDataObjectField.Attributes = MemberAttributes.Private; return extensionDataObjectField; } } CodeMemberProperty ExtensionDataObjectProperty { get { CodeMemberProperty extensionDataObjectProperty = new CodeMemberProperty(); extensionDataObjectProperty.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject); extensionDataObjectProperty.Name = Globals.ExtensionDataObjectPropertyName; extensionDataObjectProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; extensionDataObjectProperty.ImplementationTypes.Add(Globals.TypeOfIExtensibleDataObject); CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement(); propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName); extensionDataObjectProperty.GetStatements.Add(propertyGet); CodeAssignStatement propertySet = new CodeAssignStatement(); propertySet.Left = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName); propertySet.Right = new CodePropertySetValueReferenceExpression(); extensionDataObjectProperty.SetStatements.Add(propertySet); return extensionDataObjectProperty; } } CodeMemberMethod RaisePropertyChangedEventMethod { get { CodeMemberMethod raisePropertyChangedEventMethod = new CodeMemberMethod(); raisePropertyChangedEventMethod.Name = "RaisePropertyChanged"; raisePropertyChangedEventMethod.Attributes = MemberAttributes.Final; CodeArgumentReferenceExpression propertyName = new CodeArgumentReferenceExpression("propertyName"); raisePropertyChangedEventMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), propertyName.ParameterName)); CodeVariableReferenceExpression propertyChanged = new CodeVariableReferenceExpression("propertyChanged"); raisePropertyChangedEventMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(PropertyChangedEventHandler), propertyChanged.VariableName, new CodeEventReferenceExpression(ThisReference, PropertyChangedEvent.Name))); CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(propertyChanged, CodeBinaryOperatorType.IdentityInequality, NullReference)); raisePropertyChangedEventMethod.Statements.Add(ifStatement); ifStatement.TrueStatements.Add(new CodeDelegateInvokeExpression(propertyChanged, ThisReference, new CodeObjectCreateExpression(typeof(PropertyChangedEventArgs), propertyName))); return raisePropertyChangedEventMethod; } } CodeMemberEvent PropertyChangedEvent { get { CodeMemberEvent propertyChangedEvent = new CodeMemberEvent(); propertyChangedEvent.Attributes = MemberAttributes.Public; propertyChangedEvent.Name = "PropertyChanged"; propertyChangedEvent.Type = GetCodeTypeReference(typeof(PropertyChangedEventHandler)); propertyChangedEvent.ImplementationTypes.Add(Globals.TypeOfIPropertyChange); return propertyChangedEvent; } } CodeMemberProperty CreateProperty(CodeTypeReference type, string propertyName, string fieldName, bool isValueType) { CodeMemberProperty property = new CodeMemberProperty(); property.Type = type; property.Name = propertyName; property.Attributes = MemberAttributes.Final; if(GenerateInternalTypes) property.Attributes |= MemberAttributes.Assembly; else property.Attributes |= MemberAttributes.Public; CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement(); propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, fieldName); property.GetStatements.Add(propertyGet); CodeAssignStatement propertySet = new CodeAssignStatement(); propertySet.Left = new CodeFieldReferenceExpression(ThisReference, fieldName); propertySet.Right = new CodePropertySetValueReferenceExpression(); if (EnableDataBinding && SupportsDeclareEvents) { CodeConditionStatement ifStatement = new CodeConditionStatement(); CodeExpression left = new CodeFieldReferenceExpression(ThisReference, fieldName); CodeExpression right = new CodePropertySetValueReferenceExpression(); if(!isValueType) { left = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(Globals.TypeOfObject), "ReferenceEquals", new CodeExpression[] { left, right } ); } else { left = new CodeMethodInvokeExpression(left, "Equals", new CodeExpression[] { right } ); } right = new CodePrimitiveExpression(true); ifStatement.Condition = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.IdentityInequality, right); ifStatement.TrueStatements.Add(propertySet); ifStatement.TrueStatements.Add(new CodeMethodInvokeExpression(ThisReference, RaisePropertyChangedEventMethod.Name, new CodePrimitiveExpression(propertyName))); property.SetStatements.Add(ifStatement); } else property.SetStatements.Add(propertySet); return property; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.Runtime.Serialization { using System; using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Reflection; using System.Security; using System.Text; using System.Xml; using System.Xml.Schema; using DataContractDictionary = System.Collections.Generic.Dictionary ; class CodeExporter { DataContractSet dataContractSet; CodeCompileUnit codeCompileUnit; ImportOptions options; Dictionary namespaces; Dictionary clrNamespaces; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly string wildcardNamespaceMapping = "*"; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly string typeNameFieldName = "typeName"; [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly object codeUserDataActualTypeKey = new object(); [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" + " data from being modified or leaked to other components in appdomain.")] static readonly object surrogateDataKey = typeof(IDataContractSurrogate); const int MaxIdentifierLength = 511; internal CodeExporter(DataContractSet dataContractSet, ImportOptions options, CodeCompileUnit codeCompileUnit) { this.dataContractSet = dataContractSet; this.codeCompileUnit = codeCompileUnit; AddReferencedAssembly(Assembly.GetExecutingAssembly()); this.options = options; this.namespaces = new Dictionary (); this.clrNamespaces = new Dictionary (StringComparer.OrdinalIgnoreCase); // Update namespace tables for DataContract(s) that are already processed foreach (KeyValuePair pair in dataContractSet) { DataContract dataContract = pair.Value; if (!(dataContract.IsBuiltInDataContract || dataContract is CollectionDataContract)) { ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (contractCodeDomInfo.IsProcessed && !contractCodeDomInfo.UsesWildcardNamespace) { string clrNamespace = contractCodeDomInfo.ClrNamespace; if (clrNamespace != null && !this.clrNamespaces.ContainsKey(clrNamespace)) { this.clrNamespaces.Add(clrNamespace, dataContract.StableName.Namespace); this.namespaces.Add(dataContract.StableName.Namespace, clrNamespace); } } } } // Copy options.Namespaces to namespace tables if (this.options != null) { foreach (KeyValuePair pair in options.Namespaces) { string dataContractNamespace = pair.Key; string clrNamespace = pair.Value; if (clrNamespace == null) clrNamespace = String.Empty; string currentDataContractNamespace; if (this.clrNamespaces.TryGetValue(clrNamespace, out currentDataContractNamespace)) { if (dataContractNamespace != currentDataContractNamespace) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CLRNamespaceMappedMultipleTimes, currentDataContractNamespace, dataContractNamespace, clrNamespace))); } else this.clrNamespaces.Add(clrNamespace, dataContractNamespace); string currentClrNamespace; if (this.namespaces.TryGetValue(dataContractNamespace, out currentClrNamespace)) { if (clrNamespace != currentClrNamespace) { this.namespaces.Remove(dataContractNamespace); this.namespaces.Add(dataContractNamespace, clrNamespace); } } else this.namespaces.Add(dataContractNamespace, clrNamespace); } } // Update namespace tables for pre-existing namespaces in CodeCompileUnit foreach (CodeNamespace codeNS in codeCompileUnit.Namespaces) { string ns = codeNS.Name ?? string.Empty; if (!this.clrNamespaces.ContainsKey(ns)) { this.clrNamespaces.Add(ns, null); } if (ns.Length == 0) { foreach (CodeTypeDeclaration codeTypeDecl in codeNS.Types) { AddGlobalTypeName(codeTypeDecl.Name); } } } } void AddReferencedAssembly(Assembly assembly) { string assemblyName = System.IO.Path.GetFileName(assembly.Location); bool alreadyExisting = false; foreach (string existingName in this.codeCompileUnit.ReferencedAssemblies) { if (String.Compare(existingName, assemblyName, StringComparison.OrdinalIgnoreCase) == 0) { alreadyExisting = true; break; } } if (!alreadyExisting) this.codeCompileUnit.ReferencedAssemblies.Add(assemblyName); } bool GenerateSerializableTypes { get { return (options == null) ? false : options.GenerateSerializable; } } bool GenerateInternalTypes { get { return (options == null) ? false : options.GenerateInternal; } } bool EnableDataBinding { get { return (options == null) ? false : options.EnableDataBinding; } } CodeDomProvider CodeProvider { get { return (options == null) ? null : options.CodeProvider; } } bool SupportsDeclareEvents { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareEvents); } } bool SupportsDeclareValueTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareValueTypes); } } bool SupportsGenericTypeReference { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.GenericTypeReference); } } bool SupportsAssemblyAttributes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.AssemblyAttributes); } } bool SupportsPartialTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.PartialTypes); } } bool SupportsNestedTypes { get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.NestedTypes); } } string FileExtension { get { return (CodeProvider == null) ? String.Empty : CodeProvider.FileExtension; } } Dictionary Namespaces { get { return namespaces; } } Dictionary ClrNamespaces { get { return clrNamespaces; } } bool TryGetReferencedType(XmlQualifiedName stableName, DataContract dataContract, out Type type) { if (dataContract == null) { if (dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type)) return true; if (dataContractSet.TryGetReferencedType(stableName, dataContract, out type)) { // enforce that collection types only be specified via ReferencedCollectionTypes if (CollectionDataContract.IsCollection(type)) { type = null; return false; } return true; } return false; } else if (dataContract is CollectionDataContract) return dataContractSet.TryGetReferencedCollectionType(stableName, dataContract, out type); else { XmlDataContract xmlDataContract = dataContract as XmlDataContract; if (xmlDataContract != null && xmlDataContract.IsAnonymous) { stableName = SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, stableName, dataContract.StableName); } return dataContractSet.TryGetReferencedType(stableName, dataContract, out type); } } internal void Export() { try { foreach (KeyValuePair pair in dataContractSet) { DataContract dataContract = pair.Value; if (dataContract.IsBuiltInDataContract) continue; ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (!contractCodeDomInfo.IsProcessed) { if (dataContract is ClassDataContract) { ClassDataContract classDataContract = (ClassDataContract)dataContract; if (classDataContract.IsISerializable) ExportISerializableDataContract(classDataContract, contractCodeDomInfo); else ExportClassDataContractHierarchy(classDataContract.StableName, classDataContract, contractCodeDomInfo, new Dictionary ()); } else if (dataContract is CollectionDataContract) ExportCollectionDataContract((CollectionDataContract)dataContract, contractCodeDomInfo); else if (dataContract is EnumDataContract) ExportEnumDataContract((EnumDataContract)dataContract, contractCodeDomInfo); else if (dataContract is XmlDataContract) ExportXmlDataContract((XmlDataContract)dataContract, contractCodeDomInfo); else throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.UnexpectedContractType, DataContract.GetClrTypeFullName(dataContract.GetType()), DataContract.GetClrTypeFullName(dataContract.UnderlyingType)))); contractCodeDomInfo.IsProcessed = true; } } if (dataContractSet.DataContractSurrogate != null) { CodeNamespace[] namespaces = new CodeNamespace[codeCompileUnit.Namespaces.Count]; codeCompileUnit.Namespaces.CopyTo(namespaces, 0); foreach (CodeNamespace codeNamespace in namespaces) InvokeProcessImportedType(codeNamespace.Types); } } finally { System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(codeCompileUnit); } } void ExportClassDataContractHierarchy(XmlQualifiedName typeName, ClassDataContract classContract, ContractCodeDomInfo contractCodeDomInfo, Dictionary contractNamesInHierarchy) { if (contractNamesInHierarchy.ContainsKey(classContract.StableName)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeCannotBeImported, typeName.Name, typeName.Namespace, SR.GetString(SR.CircularTypeReference, classContract.StableName.Name, classContract.StableName.Namespace)))); contractNamesInHierarchy.Add(classContract.StableName, null); ClassDataContract baseContract = classContract.BaseContract; if (baseContract != null) { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(baseContract); if (!baseContractCodeDomInfo.IsProcessed) { ExportClassDataContractHierarchy(typeName, baseContract, baseContractCodeDomInfo, contractNamesInHierarchy); baseContractCodeDomInfo.IsProcessed = true; } } ExportClassDataContract(classContract, contractCodeDomInfo); } void InvokeProcessImportedType(CollectionBase collection) { object[] objects = new object[collection.Count]; ((ICollection)collection).CopyTo(objects, 0); foreach (object obj in objects) { CodeTypeDeclaration codeTypeDeclaration = obj as CodeTypeDeclaration; if (codeTypeDeclaration == null) continue; CodeTypeDeclaration newCodeTypeDeclaration = DataContractSurrogateCaller.ProcessImportedType( dataContractSet.DataContractSurrogate, codeTypeDeclaration, codeCompileUnit); if (newCodeTypeDeclaration != codeTypeDeclaration) { ((IList)collection).Remove(codeTypeDeclaration); if (newCodeTypeDeclaration != null) ((IList)collection).Add(newCodeTypeDeclaration); } if(newCodeTypeDeclaration != null) InvokeProcessImportedType(newCodeTypeDeclaration.Members); } } internal CodeTypeReference GetCodeTypeReference(DataContract dataContract) { if (dataContract.IsBuiltInDataContract) return GetCodeTypeReference(dataContract.UnderlyingType); ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); GenerateType(dataContract, contractCodeDomInfo); return contractCodeDomInfo.TypeReference; } CodeTypeReference GetCodeTypeReference(Type type) { AddReferencedAssembly(type.Assembly); return new CodeTypeReference(type); } internal CodeTypeReference GetElementTypeReference(DataContract dataContract, bool isElementTypeNullable) { CodeTypeReference elementTypeReference = GetCodeTypeReference(dataContract); if (dataContract.IsValueType && isElementTypeNullable) elementTypeReference = WrapNullable(elementTypeReference); return elementTypeReference; } XmlQualifiedName GenericListName { get { return DataContract.GetStableName(Globals.TypeOfListGeneric); } } CollectionDataContract GenericListContract { get { return dataContractSet.GetDataContract(Globals.TypeOfListGeneric) as CollectionDataContract; } } XmlQualifiedName GenericDictionaryName { get { return DataContract.GetStableName(Globals.TypeOfDictionaryGeneric); } } CollectionDataContract GenericDictionaryContract { get { return dataContractSet.GetDataContract(Globals.TypeOfDictionaryGeneric) as CollectionDataContract; } } ContractCodeDomInfo GetContractCodeDomInfo(DataContract dataContract) { ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(dataContract); if (contractCodeDomInfo == null) { contractCodeDomInfo = new ContractCodeDomInfo(); dataContractSet.SetContractCodeDomInfo(dataContract, contractCodeDomInfo); } return contractCodeDomInfo; } void GenerateType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { if (!contractCodeDomInfo.IsProcessed) { CodeTypeReference referencedType = GetReferencedType(dataContract); if (referencedType != null) { contractCodeDomInfo.TypeReference = referencedType; contractCodeDomInfo.ReferencedTypeExists = true; } else { CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (type == null) { string clrNamespace = GetClrNamespace(dataContract, contractCodeDomInfo); CodeNamespace ns = GetCodeNamespace(clrNamespace, dataContract.StableName.Namespace, contractCodeDomInfo); type = GetNestedType(dataContract, contractCodeDomInfo); if (type == null) { string typeName = XmlConvert.DecodeName(dataContract.StableName.Name); typeName = GetClrIdentifier(typeName, Globals.DefaultTypeName); if (NamespaceContainsType(ns, typeName) || GlobalTypeNameConflicts(clrNamespace, typeName)) { for (int i = 1; ; i++) { string uniqueName = AppendToValidClrIdentifier(typeName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!NamespaceContainsType(ns, uniqueName) && !GlobalTypeNameConflicts(clrNamespace, uniqueName)) { typeName = uniqueName; break; } if(i == Int32.MaxValue) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, typeName))); } } type = CreateTypeDeclaration(typeName, dataContract); ns.Types.Add(type); if (string.IsNullOrEmpty(clrNamespace)) { AddGlobalTypeName(typeName); } contractCodeDomInfo.TypeReference = new CodeTypeReference((clrNamespace == null || clrNamespace.Length == 0) ? typeName : clrNamespace+"."+typeName); if (GenerateInternalTypes) type.TypeAttributes = TypeAttributes.NotPublic; else type.TypeAttributes = TypeAttributes.Public; } if (dataContractSet.DataContractSurrogate != null) type.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataContract)); contractCodeDomInfo.TypeDeclaration = type; } } } } CodeTypeDeclaration GetNestedType(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { if (!SupportsNestedTypes) return null; string originalName = dataContract.StableName.Name; int nestedTypeIndex = originalName.LastIndexOf('.'); if (nestedTypeIndex <= 0) return null; string containingTypeName = originalName.Substring(0, nestedTypeIndex); DataContract containingDataContract = dataContractSet[new XmlQualifiedName(containingTypeName, dataContract.StableName.Namespace)]; if (containingDataContract == null) return null; string nestedTypeName = XmlConvert.DecodeName(originalName.Substring(nestedTypeIndex+1)); nestedTypeName = GetClrIdentifier(nestedTypeName, Globals.DefaultTypeName); ContractCodeDomInfo containingContractCodeDomInfo = GetContractCodeDomInfo(containingDataContract); GenerateType(containingDataContract, containingContractCodeDomInfo); if (containingContractCodeDomInfo.ReferencedTypeExists) return null; CodeTypeDeclaration containingType = containingContractCodeDomInfo.TypeDeclaration; if (TypeContainsNestedType(containingType, nestedTypeName)) { for (int i = 1; ; i++) { string uniqueName = AppendToValidClrIdentifier(nestedTypeName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!TypeContainsNestedType(containingType, uniqueName)) { nestedTypeName = uniqueName; break; } } } CodeTypeDeclaration type = CreateTypeDeclaration(nestedTypeName, dataContract); containingType.Members.Add(type); contractCodeDomInfo.TypeReference = new CodeTypeReference(containingContractCodeDomInfo.TypeReference.BaseType + "+" + nestedTypeName); if (GenerateInternalTypes) type.TypeAttributes = TypeAttributes.NestedAssembly; else type.TypeAttributes = TypeAttributes.NestedPublic; return type; } static CodeTypeDeclaration CreateTypeDeclaration(string typeName, DataContract dataContract) { CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeName); CodeAttributeDeclaration debuggerStepThroughAttribute = new CodeAttributeDeclaration(typeof(System.Diagnostics.DebuggerStepThroughAttribute).FullName); CodeAttributeDeclaration generatedCodeAttribute = new CodeAttributeDeclaration(typeof(GeneratedCodeAttribute).FullName); AssemblyName assemblyName = Assembly.GetExecutingAssembly().GetName(); generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name))); generatedCodeAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Version.ToString()))); // System.Diagnostics.DebuggerStepThroughAttribute not allowed on enums // ensure that the attribute is only generated on types that are not enums EnumDataContract enumDataContract = dataContract as EnumDataContract; if (enumDataContract == null) { typeDecl.CustomAttributes.Add(debuggerStepThroughAttribute); } typeDecl.CustomAttributes.Add(generatedCodeAttribute); return typeDecl; } [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal XmlDataContract.", Safe = "Called during schema import/code generation.")] [SecuritySafeCritical] CodeTypeReference GetReferencedType(DataContract dataContract) { Type type = null; CodeTypeReference typeReference = GetSurrogatedTypeReference(dataContract); if(typeReference != null) return typeReference; if (TryGetReferencedType(dataContract.StableName, dataContract, out type) && !type.IsGenericTypeDefinition && !type.ContainsGenericParameters) { if (dataContract is XmlDataContract) { if (Globals.TypeOfIXmlSerializable.IsAssignableFrom(type)) { XmlDataContract xmlContract = (XmlDataContract)dataContract; if(xmlContract.IsTypeDefinedOnImport) { if(!xmlContract.Equals(dataContractSet.GetDataContract(type))) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace))); } else { xmlContract.IsValueType = type.IsValueType; xmlContract.IsTypeDefinedOnImport = true; } return GetCodeTypeReference(type); } throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeMustBeIXmlSerializable, DataContract.GetClrTypeFullName(type), DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable), dataContract.StableName.Name, dataContract.StableName.Namespace))); } DataContract referencedContract = dataContractSet.GetDataContract(type); if (referencedContract.Equals(dataContract)) { typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); return typeReference; } throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, dataContract.StableName.Name, dataContract.StableName.Namespace))); } else if (dataContract.GenericInfo != null) { DataContract referencedContract; XmlQualifiedName genericStableName = dataContract.GenericInfo.GetExpandedStableName(); if(genericStableName != dataContract.StableName) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.GenericTypeNameMismatch, dataContract.StableName.Name, dataContract.StableName.Namespace, genericStableName.Name, genericStableName.Namespace))); typeReference = GetReferencedGenericType(dataContract.GenericInfo, out referencedContract); if (referencedContract != null && !referencedContract.Equals(dataContract)) { type = (Type)typeReference.UserData[codeUserDataActualTypeKey]; throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedTypeDoesNotMatch, type.AssemblyQualifiedName, referencedContract.StableName.Name, referencedContract.StableName.Namespace))); } return typeReference; } return GetReferencedCollectionType(dataContract as CollectionDataContract); } CodeTypeReference GetReferencedCollectionType(CollectionDataContract collectionContract) { if (collectionContract == null) return null; if (HasDefaultCollectionNames(collectionContract)) { CodeTypeReference typeReference; if (!TryGetReferencedDictionaryType(collectionContract, out typeReference)) { DataContract itemContract = collectionContract.ItemContract; if (collectionContract.IsDictionary) { GenerateKeyValueType(itemContract as ClassDataContract); } bool isItemTypeNullable = collectionContract.IsItemTypeNullable; if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out typeReference)) typeReference = new CodeTypeReference(GetElementTypeReference(itemContract, isItemTypeNullable), 1); } return typeReference; } return null; } bool HasDefaultCollectionNames(CollectionDataContract collectionContract) { DataContract itemContract = collectionContract.ItemContract; if (collectionContract.ItemName != itemContract.StableName.Name) return false; if (collectionContract.IsDictionary && (collectionContract.KeyName != Globals.KeyLocalName || collectionContract.ValueName != Globals.ValueLocalName)) return false; XmlQualifiedName expectedType = itemContract.GetArrayTypeName(collectionContract.IsItemTypeNullable); return (collectionContract.StableName.Name == expectedType.Name && collectionContract.StableName.Namespace == expectedType.Namespace); } bool TryGetReferencedDictionaryType(CollectionDataContract collectionContract, out CodeTypeReference typeReference) { // Check if it is a dictionary and use referenced dictionary type if present if (collectionContract.IsDictionary && SupportsGenericTypeReference) { Type type; if (!TryGetReferencedType(GenericDictionaryName, GenericDictionaryContract, out type)) type = Globals.TypeOfDictionaryGeneric; ClassDataContract itemContract = collectionContract.ItemContract as ClassDataContract; DataMember keyMember = itemContract.Members[0]; DataMember valueMember = itemContract.Members[1]; CodeTypeReference keyTypeReference = GetElementTypeReference(keyMember.MemberTypeContract, keyMember.IsNullable); CodeTypeReference valueTypeReference = GetElementTypeReference(valueMember.MemberTypeContract, valueMember.IsNullable); if (keyTypeReference != null && valueTypeReference != null) { typeReference = GetCodeTypeReference(type); typeReference.TypeArguments.Add(keyTypeReference); typeReference.TypeArguments.Add(valueTypeReference); return true; } } typeReference = null; return false; } bool TryGetReferencedListType(DataContract itemContract, bool isItemTypeNullable, out CodeTypeReference typeReference) { Type type; if (SupportsGenericTypeReference && TryGetReferencedType(GenericListName, GenericListContract, out type)) { typeReference = GetCodeTypeReference(type); typeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable)); return true; } typeReference = null; return false; } CodeTypeReference GetSurrogatedTypeReference(DataContract dataContract) { IDataContractSurrogate dataContractSurrogate = this.dataContractSet.DataContractSurrogate; if (dataContractSurrogate != null) { Type type = DataContractSurrogateCaller.GetReferencedTypeOnImport( dataContractSurrogate, dataContract.StableName.Name, dataContract.StableName.Namespace, dataContractSet.GetSurrogateData(dataContract)); if (type != null) { CodeTypeReference typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); return typeReference; } } return null; } CodeTypeReference GetReferencedGenericType(GenericInfo genInfo, out DataContract dataContract) { dataContract = null; if (!SupportsGenericTypeReference) return null; Type type; if (!TryGetReferencedType(genInfo.StableName, null, out type)) { if(genInfo.Parameters != null) return null; dataContract = dataContractSet[genInfo.StableName]; if (dataContract == null) return null; if (dataContract.GenericInfo != null) return null; return GetCodeTypeReference(dataContract); } bool enableStructureCheck = (type != Globals.TypeOfNullable); CodeTypeReference typeReference = GetCodeTypeReference(type); typeReference.UserData.Add(codeUserDataActualTypeKey, type); if (genInfo.Parameters != null) { DataContract[] paramContracts = new DataContract[genInfo.Parameters.Count]; for(int i=0;i ()); } return typeReference; } bool NamespaceContainsType(CodeNamespace ns, string typeName) { foreach (CodeTypeDeclaration type in ns.Types) { if (String.Compare(typeName, type.Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } return false; } bool GlobalTypeNameConflicts(string clrNamespace, string typeName) { return (string.IsNullOrEmpty(clrNamespace) && this.clrNamespaces.ContainsKey(typeName)); } void AddGlobalTypeName(string typeName) { if (!this.clrNamespaces.ContainsKey(typeName)) { this.clrNamespaces.Add(typeName, null); } } bool TypeContainsNestedType(CodeTypeDeclaration containingType, string typeName) { foreach (CodeTypeMember member in containingType.Members) { if (member is CodeTypeDeclaration) { if (String.Compare(typeName, ((CodeTypeDeclaration)member).Name, StringComparison.OrdinalIgnoreCase) == 0) return true; } } return false; } string GetNameForAttribute(string name) { string decodedName = XmlConvert.DecodeName(name); if (string.CompareOrdinal(name, decodedName) == 0) return name; string reencodedName = DataContract.EncodeLocalName(decodedName); return (string.CompareOrdinal(name, reencodedName) == 0) ? decodedName : name; } void AddSerializableAttribute(bool generateSerializable, CodeTypeDeclaration type, ContractCodeDomInfo contractCodeDomInfo) { if (generateSerializable) { type.CustomAttributes.Add(SerializableAttribute); AddImportStatement(Globals.TypeOfSerializableAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } } void ExportClassDataContract(ClassDataContract classDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(classDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if (classDataContract.IsValueType && SupportsDeclareValueTypes) type.IsStruct = true; else type.IsClass = true; string dataContractName = GetNameForAttribute(classDataContract.StableName.Name); CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute)); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(classDataContract.StableName.Namespace))); if (classDataContract.IsReference != Globals.DefaultIsReference) dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(classDataContract.IsReference))); type.CustomAttributes.Add(dataContractAttribute); AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo); AddKnownTypes(classDataContract, contractCodeDomInfo); if (classDataContract.BaseContract == null) { if (!type.IsStruct) type.BaseTypes.Add(Globals.TypeOfObject); AddExtensionData(contractCodeDomInfo); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } else { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(classDataContract.BaseContract); Fx.Assert(baseContractCodeDomInfo.IsProcessed, "Cannot generate code for type if code for base type has not been generated"); type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); AddBaseMemberNames(baseContractCodeDomInfo, contractCodeDomInfo); if (baseContractCodeDomInfo.ReferencedTypeExists) { Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey]; ThrowIfReferencedBaseTypeSealed(actualType, classDataContract); if(!Globals.TypeOfIExtensibleDataObject.IsAssignableFrom(actualType)) AddExtensionData(contractCodeDomInfo); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } } if (classDataContract.Members != null) { for (int i=0; i < classDataContract.Members.Count; i++) { DataMember dataMember = classDataContract.Members[i]; CodeTypeReference memberType = GetElementTypeReference(dataMember.MemberTypeContract, (dataMember.IsNullable && dataMember.MemberTypeContract.IsValueType)); string dataMemberName = GetNameForAttribute(dataMember.Name); string propertyName = GetMemberName(dataMemberName, contractCodeDomInfo); string fieldName = GetMemberName(AppendToValidClrIdentifier(propertyName, Globals.DefaultFieldSuffix), contractCodeDomInfo); CodeMemberField field = new CodeMemberField(); field.Type = memberType; field.Name = fieldName; field.Attributes = MemberAttributes.Private; CodeMemberProperty property = CreateProperty(memberType, propertyName, fieldName, dataMember.MemberTypeContract.IsValueType && SupportsDeclareValueTypes); if (dataContractSet.DataContractSurrogate != null) property.UserData.Add(surrogateDataKey, dataContractSet.GetSurrogateData(dataMember)); CodeAttributeDeclaration dataMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataMemberAttribute)); if (dataMemberName != property.Name) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataMemberName))); if (dataMember.IsRequired != Globals.DefaultIsRequired) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsRequiredProperty, new CodePrimitiveExpression(dataMember.IsRequired))); if (dataMember.EmitDefaultValue!= Globals.DefaultEmitDefaultValue) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.EmitDefaultValueProperty, new CodePrimitiveExpression(dataMember.EmitDefaultValue))); if (dataMember.Order != Globals.DefaultOrder) dataMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.OrderProperty, new CodePrimitiveExpression(dataMember.Order))); property.CustomAttributes.Add(dataMemberAttribute); if (GenerateSerializableTypes && !dataMember.IsRequired) { CodeAttributeDeclaration optionalFieldAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfOptionalFieldAttribute)); field.CustomAttributes.Add(optionalFieldAttribute); } type.Members.Add(field); type.Members.Add(property); } } } bool CanDeclareAssemblyAttribute(ContractCodeDomInfo contractCodeDomInfo) { return SupportsAssemblyAttributes && !contractCodeDomInfo.UsesWildcardNamespace; } bool NeedsExplicitNamespace(string dataContractNamespace, string clrNamespace) { return (DataContract.GetDefaultStableNamespace(clrNamespace) != dataContractNamespace); } internal ICollection GetKnownTypeReferences(DataContract dataContract) { DataContractDictionary knownTypeDictionary = GetKnownTypeContracts(dataContract); if (knownTypeDictionary == null) return null; ICollection knownTypeContracts = knownTypeDictionary.Values; if (knownTypeContracts == null || knownTypeContracts.Count == 0) return null; List knownTypeReferences = new List (); foreach (DataContract knownTypeContract in knownTypeContracts) { knownTypeReferences.Add(GetCodeTypeReference(knownTypeContract)); } return knownTypeReferences; } DataContractDictionary GetKnownTypeContracts(DataContract dataContract) { if (dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(dataContract)) { return dataContractSet.KnownTypesForObject; } else if (dataContract is ClassDataContract) { ContractCodeDomInfo contractCodeDomInfo = GetContractCodeDomInfo(dataContract); if (!contractCodeDomInfo.IsProcessed) GenerateType(dataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return GetKnownTypeContracts((ClassDataContract)dataContract, new Dictionary ()); } return null; } DataContractDictionary GetKnownTypeContracts(ClassDataContract dataContract, Dictionary handledContracts) { if (handledContracts.ContainsKey(dataContract)) return dataContract.KnownDataContracts; handledContracts.Add(dataContract, null); if (dataContract.Members != null) { bool objectMemberHandled = false; foreach (DataMember dataMember in dataContract.Members) { DataContract memberContract = dataMember.MemberTypeContract; if (!objectMemberHandled && dataContractSet.KnownTypesForObject != null && SchemaImporter.IsObjectContract(memberContract)) { AddKnownTypeContracts(dataContract, dataContractSet.KnownTypesForObject); objectMemberHandled = true; } else if (memberContract is ClassDataContract) { ContractCodeDomInfo memberCodeDomInfo = GetContractCodeDomInfo(memberContract); if (!memberCodeDomInfo.IsProcessed) GenerateType(memberContract, memberCodeDomInfo); if (memberCodeDomInfo.ReferencedTypeExists) { AddKnownTypeContracts(dataContract, GetKnownTypeContracts((ClassDataContract)memberContract, handledContracts)); } } } } return dataContract.KnownDataContracts; } [Fx.Tag.SecurityNote(Critical = "Sets critical properties on internal DataContract.", Safe = "Called during schema import/code generation.")] [SecuritySafeCritical] void AddKnownTypeContracts(ClassDataContract dataContract, DataContractDictionary knownContracts) { if (knownContracts == null || knownContracts.Count == 0) return; if (dataContract.KnownDataContracts == null) dataContract.KnownDataContracts = new DataContractDictionary(); foreach (KeyValuePair pair in knownContracts) { if (dataContract.StableName != pair.Key && !dataContract.KnownDataContracts.ContainsKey(pair.Key) && !pair.Value.IsBuiltInDataContract) dataContract.KnownDataContracts.Add(pair.Key, pair.Value); } } void AddKnownTypes(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { DataContractDictionary knownContractDictionary = GetKnownTypeContracts(dataContract, new Dictionary ()); if (knownContractDictionary == null || knownContractDictionary.Count == 0) return; ICollection knownTypeContracts = knownContractDictionary.Values; foreach (DataContract knownTypeContract in knownTypeContracts) { CodeAttributeDeclaration knownTypeAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfKnownTypeAttribute)); knownTypeAttribute.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(GetCodeTypeReference(knownTypeContract)))); contractCodeDomInfo.TypeDeclaration.CustomAttributes.Add(knownTypeAttribute); } AddImportStatement(Globals.TypeOfKnownTypeAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } CodeTypeReference WrapNullable(CodeTypeReference memberType) { if (!SupportsGenericTypeReference) return memberType; CodeTypeReference nullableOfMemberType = GetCodeTypeReference(Globals.TypeOfNullable); nullableOfMemberType.TypeArguments.Add(memberType); return nullableOfMemberType; } void AddExtensionData(ContractCodeDomInfo contractCodeDomInfo) { if(contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null) { CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIExtensibleDataObject)); CodeMemberField extensionDataObjectField = ExtensionDataObjectField; if (GenerateSerializableTypes) { CodeAttributeDeclaration nonSerializedAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfNonSerializedAttribute)); extensionDataObjectField.CustomAttributes.Add(nonSerializedAttribute); } type.Members.Add(extensionDataObjectField); contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectField.Name, null); CodeMemberProperty extensionDataObjectProperty = ExtensionDataObjectProperty; type.Members.Add(extensionDataObjectProperty); contractCodeDomInfo.GetMemberNames().Add(extensionDataObjectProperty.Name, null); } } void AddPropertyChangedNotifier(ContractCodeDomInfo contractCodeDomInfo, bool isValueType) { if (EnableDataBinding && SupportsDeclareEvents && contractCodeDomInfo != null && contractCodeDomInfo.TypeDeclaration != null) { CodeTypeDeclaration codeTypeDeclaration = contractCodeDomInfo.TypeDeclaration; codeTypeDeclaration.BaseTypes.Add(CodeTypeIPropertyChange); CodeMemberEvent memberEvent = PropertyChangedEvent; codeTypeDeclaration.Members.Add(memberEvent); CodeMemberMethod raisePropertyChangedEventMethod = RaisePropertyChangedEventMethod; if (!isValueType) raisePropertyChangedEventMethod.Attributes |= MemberAttributes.Family; codeTypeDeclaration.Members.Add(raisePropertyChangedEventMethod); contractCodeDomInfo.GetMemberNames().Add(memberEvent.Name, null); contractCodeDomInfo.GetMemberNames().Add(raisePropertyChangedEventMethod.Name, null); } } void ThrowIfReferencedBaseTypeSealed(Type baseType, DataContract dataContract) { if (baseType.IsSealed) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotDeriveFromSealedReferenceType, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetClrTypeFullName(baseType)))); } void ExportEnumDataContract(EnumDataContract enumDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(enumDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; type.IsEnum = true; type.BaseTypes.Add(EnumDataContract.GetBaseType(enumDataContract.BaseContractName)); if (enumDataContract.IsFlags) { type.CustomAttributes.Add(new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfFlagsAttribute))); AddImportStatement(Globals.TypeOfFlagsAttribute.Namespace, contractCodeDomInfo.CodeNamespace); } string dataContractName = GetNameForAttribute(enumDataContract.StableName.Name); CodeAttributeDeclaration dataContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfDataContractAttribute)); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); dataContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(enumDataContract.StableName.Namespace))); type.CustomAttributes.Add(dataContractAttribute); AddImportStatement(Globals.TypeOfDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); if (enumDataContract.Members != null) { for (int i=0; i < enumDataContract.Members.Count; i++) { string stringValue = enumDataContract.Members[i].Name; long longValue = enumDataContract.Values[i]; CodeMemberField enumMember = new CodeMemberField(); if (enumDataContract.IsULong) enumMember.InitExpression = new CodeSnippetExpression(enumDataContract.GetStringFromEnumValue(longValue)); else enumMember.InitExpression = new CodePrimitiveExpression(longValue); enumMember.Name = GetMemberName(stringValue, contractCodeDomInfo); CodeAttributeDeclaration enumMemberAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfEnumMemberAttribute)); if (enumMember.Name != stringValue) enumMemberAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueProperty, new CodePrimitiveExpression(stringValue))); enumMember.CustomAttributes.Add(enumMemberAttribute); type.Members.Add(enumMember); } } } void ExportISerializableDataContract(ClassDataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(dataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; if (DataContract.GetDefaultStableNamespace(contractCodeDomInfo.ClrNamespace) != dataContract.StableName.Namespace) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNamespaceGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, DataContract.GetDataContractNamespaceFromUri(dataContract.StableName.Namespace), contractCodeDomInfo.ClrNamespace))); string dataContractName = GetNameForAttribute(dataContract.StableName.Name); int nestedTypeIndex = dataContractName.LastIndexOf('.'); string expectedName = (nestedTypeIndex <= 0 || nestedTypeIndex == dataContractName.Length-1) ? dataContractName : dataContractName.Substring(nestedTypeIndex+1); if (contractCodeDomInfo.TypeDeclaration.Name != expectedName) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.InvalidClrNameGeneratedForISerializable, dataContract.StableName.Name, dataContract.StableName.Namespace, contractCodeDomInfo.TypeDeclaration.Name))); CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if (dataContract.IsValueType && SupportsDeclareValueTypes) type.IsStruct = true; else type.IsClass = true; AddSerializableAttribute(true /*generateSerializable*/, type, contractCodeDomInfo); AddKnownTypes(dataContract, contractCodeDomInfo); if (dataContract.BaseContract == null) { if (!type.IsStruct) type.BaseTypes.Add(Globals.TypeOfObject); type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfISerializable)); type.Members.Add(ISerializableBaseConstructor); type.Members.Add(SerializationInfoField); type.Members.Add(SerializationInfoProperty); type.Members.Add(GetObjectDataMethod); AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } else { ContractCodeDomInfo baseContractCodeDomInfo = GetContractCodeDomInfo(dataContract.BaseContract); GenerateType(dataContract.BaseContract, baseContractCodeDomInfo); type.BaseTypes.Add(baseContractCodeDomInfo.TypeReference); if (baseContractCodeDomInfo.ReferencedTypeExists) { Type actualType = (Type)baseContractCodeDomInfo.TypeReference.UserData[codeUserDataActualTypeKey]; ThrowIfReferencedBaseTypeSealed(actualType, dataContract); } type.Members.Add(ISerializableDerivedConstructor); } } void GenerateKeyValueType(ClassDataContract keyValueContract) { // Add code for KeyValue item type in the case where its usage is limited to dictionary // and dictionary is not found in referenced types if (keyValueContract != null && dataContractSet[keyValueContract.StableName] == null) { ContractCodeDomInfo contractCodeDomInfo = dataContractSet.GetContractCodeDomInfo(keyValueContract); if (contractCodeDomInfo == null) { contractCodeDomInfo = new ContractCodeDomInfo(); dataContractSet.SetContractCodeDomInfo(keyValueContract, contractCodeDomInfo); ExportClassDataContract(keyValueContract, contractCodeDomInfo); contractCodeDomInfo.IsProcessed = true; } } } void ExportCollectionDataContract(CollectionDataContract collectionContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(collectionContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; string dataContractName = GetNameForAttribute(collectionContract.StableName.Name); // If type name is not expected, generate collection type that derives from referenced list type and uses [CollectionDataContract] if (!SupportsGenericTypeReference) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( SR.GetString(SR.CannotUseGenericTypeAsBase, dataContractName, collectionContract.StableName.Namespace))); DataContract itemContract = collectionContract.ItemContract; bool isItemTypeNullable = collectionContract.IsItemTypeNullable; CodeTypeReference baseTypeReference; bool foundDictionaryBase = TryGetReferencedDictionaryType(collectionContract, out baseTypeReference); if (!foundDictionaryBase) { if (collectionContract.IsDictionary) { GenerateKeyValueType(collectionContract.ItemContract as ClassDataContract); } if (!TryGetReferencedListType(itemContract, isItemTypeNullable, out baseTypeReference)) { if (SupportsGenericTypeReference) { baseTypeReference = GetCodeTypeReference(Globals.TypeOfListGeneric); baseTypeReference.TypeArguments.Add(GetElementTypeReference(itemContract, isItemTypeNullable)); } else { string expectedTypeName = Globals.ArrayPrefix + itemContract.StableName.Name; string expectedTypeNs = DataContract.GetCollectionNamespace(itemContract.StableName.Namespace); throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ReferencedBaseTypeDoesNotExist, dataContractName, collectionContract.StableName.Namespace, expectedTypeName, expectedTypeNs, DataContract.GetClrTypeFullName(Globals.TypeOfIListGeneric), DataContract.GetClrTypeFullName(Globals.TypeOfICollectionGeneric)))); } } } CodeTypeDeclaration generatedType = contractCodeDomInfo.TypeDeclaration; generatedType.BaseTypes.Add(baseTypeReference); CodeAttributeDeclaration collectionContractAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfCollectionDataContractAttribute)); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NameProperty, new CodePrimitiveExpression(dataContractName))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.NamespaceProperty, new CodePrimitiveExpression(collectionContract.StableName.Namespace))); if (collectionContract.IsReference != Globals.DefaultIsReference) collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.IsReferenceProperty, new CodePrimitiveExpression(collectionContract.IsReference))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ItemNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ItemName)))); if (foundDictionaryBase) { collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.KeyNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.KeyName)))); collectionContractAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ValueNameProperty, new CodePrimitiveExpression(GetNameForAttribute(collectionContract.ValueName)))); } generatedType.CustomAttributes.Add(collectionContractAttribute); AddImportStatement(Globals.TypeOfCollectionDataContractAttribute.Namespace, contractCodeDomInfo.CodeNamespace); AddSerializableAttribute(GenerateSerializableTypes, generatedType, contractCodeDomInfo); } private void ExportXmlDataContract(XmlDataContract xmlDataContract, ContractCodeDomInfo contractCodeDomInfo) { GenerateType(xmlDataContract, contractCodeDomInfo); if (contractCodeDomInfo.ReferencedTypeExists) return; CodeTypeDeclaration type = contractCodeDomInfo.TypeDeclaration; if (SupportsPartialTypes) type.IsPartial = true; if(xmlDataContract.IsValueType) type.IsStruct = true; else { type.IsClass = true; type.BaseTypes.Add(Globals.TypeOfObject); } AddSerializableAttribute(GenerateSerializableTypes, type, contractCodeDomInfo); type.BaseTypes.Add(DataContract.GetClrTypeFullName(Globals.TypeOfIXmlSerializable)); type.Members.Add(NodeArrayField); type.Members.Add(NodeArrayProperty); type.Members.Add(ReadXmlMethod); type.Members.Add(WriteXmlMethod); type.Members.Add(GetSchemaMethod); if (xmlDataContract.IsAnonymous && !xmlDataContract.HasRoot) { type.CustomAttributes.Add(new CodeAttributeDeclaration( DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute), new CodeAttributeArgument(NullReference), new CodeAttributeArgument(Globals.IsAnyProperty, new CodePrimitiveExpression(true))) ); } else { type.CustomAttributes.Add(new CodeAttributeDeclaration( DataContract.GetClrTypeFullName(Globals.TypeOfXmlSchemaProviderAttribute), new CodeAttributeArgument(new CodePrimitiveExpression(Globals.ExportSchemaMethod))) ); CodeMemberField typeNameField = new CodeMemberField(Globals.TypeOfXmlQualifiedName, typeNameFieldName); typeNameField.Attributes |= MemberAttributes.Static | MemberAttributes.Private; XmlQualifiedName typeName = xmlDataContract.IsAnonymous ? SchemaImporter.ImportActualType(xmlDataContract.XsdType.Annotation, xmlDataContract.StableName, xmlDataContract.StableName) : xmlDataContract.StableName; typeNameField.InitExpression = new CodeObjectCreateExpression(Globals.TypeOfXmlQualifiedName, new CodePrimitiveExpression(typeName.Name), new CodePrimitiveExpression(typeName.Namespace)); type.Members.Add(typeNameField); type.Members.Add(GetSchemaStaticMethod); bool isElementNameDifferent = (xmlDataContract.TopLevelElementName != null && xmlDataContract.TopLevelElementName.Value != xmlDataContract.StableName.Name) || (xmlDataContract.TopLevelElementNamespace != null && xmlDataContract.TopLevelElementNamespace.Value != xmlDataContract.StableName.Namespace); if (isElementNameDifferent || xmlDataContract.IsTopLevelElementNullable == false) { CodeAttributeDeclaration xmlRootAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfXmlRootAttribute)); if (isElementNameDifferent) { if (xmlDataContract.TopLevelElementName != null) { xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("ElementName", new CodePrimitiveExpression(xmlDataContract.TopLevelElementName.Value))); } if (xmlDataContract.TopLevelElementNamespace != null) { xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(xmlDataContract.TopLevelElementNamespace.Value))); } } if (xmlDataContract.IsTopLevelElementNullable == false) xmlRootAttribute.Arguments.Add(new CodeAttributeArgument("IsNullable", new CodePrimitiveExpression(false))); type.CustomAttributes.Add(xmlRootAttribute); } } AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct); } CodeNamespace GetCodeNamespace(string clrNamespace, string dataContractNamespace, ContractCodeDomInfo contractCodeDomInfo) { if (contractCodeDomInfo.CodeNamespace != null) return contractCodeDomInfo.CodeNamespace; CodeNamespaceCollection codeNamespaceCollection = codeCompileUnit.Namespaces; foreach (CodeNamespace ns in codeNamespaceCollection) { if (ns.Name == clrNamespace) { contractCodeDomInfo.CodeNamespace = ns; return ns; } } CodeNamespace codeNamespace = new CodeNamespace(clrNamespace); codeNamespaceCollection.Add(codeNamespace); if (CanDeclareAssemblyAttribute(contractCodeDomInfo) && NeedsExplicitNamespace(dataContractNamespace, clrNamespace)) { CodeAttributeDeclaration namespaceAttribute = new CodeAttributeDeclaration(DataContract.GetClrTypeFullName(Globals.TypeOfContractNamespaceAttribute)); namespaceAttribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(dataContractNamespace))); namespaceAttribute.Arguments.Add(new CodeAttributeArgument(Globals.ClrNamespaceProperty, new CodePrimitiveExpression(clrNamespace))); codeCompileUnit.AssemblyCustomAttributes.Add(namespaceAttribute); } contractCodeDomInfo.CodeNamespace = codeNamespace; return codeNamespace; } string GetMemberName(string memberName, ContractCodeDomInfo contractCodeDomInfo) { memberName = GetClrIdentifier(memberName, Globals.DefaultGeneratedMember); if (memberName == contractCodeDomInfo.TypeDeclaration.Name) memberName = AppendToValidClrIdentifier(memberName, Globals.DefaultMemberSuffix); if (contractCodeDomInfo.GetMemberNames().ContainsKey(memberName)) { string uniqueMemberName = null; for (int i = 1; ; i++) { uniqueMemberName = AppendToValidClrIdentifier(memberName, i.ToString(NumberFormatInfo.InvariantInfo)); if (!contractCodeDomInfo.GetMemberNames().ContainsKey(uniqueMemberName)) { memberName = uniqueMemberName; break; } } } contractCodeDomInfo.GetMemberNames().Add(memberName, null); return memberName; } void AddBaseMemberNames(ContractCodeDomInfo baseContractCodeDomInfo, ContractCodeDomInfo contractCodeDomInfo) { if (!baseContractCodeDomInfo.ReferencedTypeExists) { Dictionary baseMemberNames = baseContractCodeDomInfo.GetMemberNames(); Dictionary memberNames = contractCodeDomInfo.GetMemberNames(); foreach (KeyValuePair pair in baseMemberNames) { memberNames.Add(pair.Key, pair.Value); } } } static string GetClrIdentifier(string identifier, string defaultIdentifier) { if (identifier.Length <= MaxIdentifierLength && System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(identifier)) return identifier; bool isStart = true; StringBuilder builder = new StringBuilder(); for (int i = 0; i < identifier.Length && builder.Length < MaxIdentifierLength; i++) { char c = identifier[i]; if (IsValid(c)) { if (isStart && !IsValidStart(c)) builder.Append("_"); builder.Append(c); isStart = false; } } if (builder.Length == 0) return defaultIdentifier; return builder.ToString(); } static string AppendToValidClrIdentifier(string identifier, string appendString) { int availableLength = MaxIdentifierLength - identifier.Length; int requiredLength = appendString.Length; if (availableLength < requiredLength) identifier = identifier.Substring(0, MaxIdentifierLength - requiredLength); identifier += appendString; return identifier; } string GetClrNamespace(DataContract dataContract, ContractCodeDomInfo contractCodeDomInfo) { string clrNamespace = contractCodeDomInfo.ClrNamespace; bool usesWildcardNamespace = false; if (clrNamespace == null) { if (!Namespaces.TryGetValue(dataContract.StableName.Namespace, out clrNamespace)) { if (Namespaces.TryGetValue(wildcardNamespaceMapping, out clrNamespace)) { usesWildcardNamespace = true; } else { clrNamespace = GetClrNamespace(dataContract.StableName.Namespace); if (ClrNamespaces.ContainsKey(clrNamespace)) { string uniqueNamespace = null; for (int i = 1; ; i++) { uniqueNamespace = ((clrNamespace.Length == 0) ? Globals.DefaultClrNamespace : clrNamespace) + i.ToString(NumberFormatInfo.InvariantInfo); if (!ClrNamespaces.ContainsKey(uniqueNamespace)) { clrNamespace = uniqueNamespace; break; } } } AddNamespacePair(dataContract.StableName.Namespace, clrNamespace); } } contractCodeDomInfo.ClrNamespace = clrNamespace; contractCodeDomInfo.UsesWildcardNamespace = usesWildcardNamespace; } return clrNamespace; } void AddNamespacePair(string dataContractNamespace, string clrNamespace) { Namespaces.Add(dataContractNamespace, clrNamespace); ClrNamespaces.Add(clrNamespace, dataContractNamespace); } void AddImportStatement(string clrNamespace, CodeNamespace codeNamespace) { if (clrNamespace == codeNamespace.Name) return; CodeNamespaceImportCollection importCollection = codeNamespace.Imports; foreach (CodeNamespaceImport import in importCollection) { if (import.Namespace == clrNamespace) return; } importCollection.Add(new CodeNamespaceImport(clrNamespace)); } static string GetClrNamespace(string dataContractNamespace) { if (dataContractNamespace == null || dataContractNamespace.Length == 0) return String.Empty; Uri uri = null; StringBuilder builder = new StringBuilder(); if (Uri.TryCreate(dataContractNamespace, UriKind.RelativeOrAbsolute, out uri)) { Dictionary fragments = new Dictionary (StringComparer.OrdinalIgnoreCase); if (!uri.IsAbsoluteUri) AddToNamespace(builder, uri.OriginalString, fragments); else { string uriString = uri.AbsoluteUri; if (uriString.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal)) AddToNamespace(builder, uriString.Substring(Globals.DataContractXsdBaseNamespace.Length), fragments); else { string host = uri.Host; if (host != null) AddToNamespace(builder, host, fragments); string path = uri.PathAndQuery; if (path != null) AddToNamespace(builder, path, fragments); } } } if (builder.Length == 0) return String.Empty; int length = builder.Length; if (builder[builder.Length-1] == '.') length--; length = Math.Min(MaxIdentifierLength, length); return builder.ToString(0, length); } static void AddToNamespace(StringBuilder builder, string fragment, Dictionary fragments) { if (fragment == null) return; bool isStart = true; int fragmentOffset = builder.Length; int fragmentLength = 0; for (int i = 0; i < fragment.Length && builder.Length < MaxIdentifierLength; i++) { char c = fragment[i]; if (IsValid(c)) { if (isStart && !IsValidStart(c)) builder.Append("_"); builder.Append(c); fragmentLength++; isStart = false; } else if ((c == '.' || c == '/' || c == ':') && (builder.Length == 1 || (builder.Length > 1 && builder[builder.Length-1] != '.'))) { AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments); builder.Append('.'); fragmentOffset = builder.Length; fragmentLength = 0; isStart = true; } } AddNamespaceFragment(builder, fragmentOffset, fragmentLength, fragments); } static void AddNamespaceFragment(StringBuilder builder, int fragmentOffset, int fragmentLength, Dictionary fragments) { if (fragmentLength == 0) return; string nsFragment = builder.ToString(fragmentOffset, fragmentLength); if (fragments.ContainsKey(nsFragment)) { for (int i = 1; ; i++) { string uniquifier = i.ToString(NumberFormatInfo.InvariantInfo); string uniqueNsFragment = AppendToValidClrIdentifier(nsFragment, uniquifier); if (!fragments.ContainsKey(uniqueNsFragment)) { builder.Append(uniquifier); nsFragment = uniqueNsFragment; break; } if (i == Int32.MaxValue) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.CannotComputeUniqueName, nsFragment))); } } fragments.Add(nsFragment, null); } static bool IsValidStart(char c) { return (Char.GetUnicodeCategory(c) != UnicodeCategory.DecimalDigitNumber); } static bool IsValid(char c) { UnicodeCategory uc = Char.GetUnicodeCategory(c); // each char must be Lu, Ll, Lt, Lm, Lo, Nd, Mn, Mc, Pc switch (uc) { case UnicodeCategory.UppercaseLetter: // Lu case UnicodeCategory.LowercaseLetter: // Ll case UnicodeCategory.TitlecaseLetter: // Lt case UnicodeCategory.ModifierLetter: // Lm case UnicodeCategory.OtherLetter: // Lo case UnicodeCategory.DecimalDigitNumber: // Nd case UnicodeCategory.NonSpacingMark: // Mn case UnicodeCategory.SpacingCombiningMark: // Mc case UnicodeCategory.ConnectorPunctuation: // Pc return true; default: return false; } } CodeTypeReference CodeTypeIPropertyChange { get { return GetCodeTypeReference(typeof(System.ComponentModel.INotifyPropertyChanged)); } } CodeThisReferenceExpression ThisReference { get { return new CodeThisReferenceExpression(); } } CodePrimitiveExpression NullReference { get { return new CodePrimitiveExpression(null); } } CodeParameterDeclarationExpression SerializationInfoParameter { get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoFieldName); } } CodeParameterDeclarationExpression StreamingContextParameter { get { return new CodeParameterDeclarationExpression(GetCodeTypeReference(Globals.TypeOfStreamingContext), Globals.ContextFieldName); } } CodeAttributeDeclaration SerializableAttribute { get { return new CodeAttributeDeclaration(GetCodeTypeReference(Globals.TypeOfSerializableAttribute)); } } CodeMemberProperty NodeArrayProperty { get { return CreateProperty(GetCodeTypeReference(Globals.TypeOfXmlNodeArray),Globals.NodeArrayPropertyName, Globals.NodeArrayFieldName, false/*isValueType*/); } } CodeMemberField NodeArrayField { get { CodeMemberField nodeArrayField = new CodeMemberField(); nodeArrayField.Type = GetCodeTypeReference(Globals.TypeOfXmlNodeArray); nodeArrayField.Name = Globals.NodeArrayFieldName; nodeArrayField.Attributes = MemberAttributes.Private; return nodeArrayField; } } CodeMemberMethod ReadXmlMethod { get { CodeMemberMethod readXmlMethod = new CodeMemberMethod(); readXmlMethod.Name = "ReadXml"; CodeParameterDeclarationExpression readerArg = new CodeParameterDeclarationExpression(typeof(XmlReader), "reader"); readXmlMethod.Parameters.Add(readerArg); readXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; readXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); CodeAssignStatement setNode = new CodeAssignStatement(); setNode.Left = new CodeFieldReferenceExpression(ThisReference, Globals.NodeArrayFieldName); setNode.Right = new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)), XmlSerializableServices.ReadNodesMethodName, new CodeArgumentReferenceExpression(readerArg.Name) ); readXmlMethod.Statements.Add(setNode); return readXmlMethod; } } CodeMemberMethod WriteXmlMethod { get { CodeMemberMethod writeXmlMethod = new CodeMemberMethod(); writeXmlMethod.Name = "WriteXml"; CodeParameterDeclarationExpression writerArg = new CodeParameterDeclarationExpression(typeof(XmlWriter), "writer"); writeXmlMethod.Parameters.Add(writerArg); writeXmlMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; writeXmlMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); writeXmlMethod.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(Globals.TypeOfXmlSerializableServices)), XmlSerializableServices.WriteNodesMethodName, new CodeArgumentReferenceExpression(writerArg.Name), new CodePropertyReferenceExpression(ThisReference, Globals.NodeArrayPropertyName) ) ); return writeXmlMethod; } } CodeMemberMethod GetSchemaMethod { get { CodeMemberMethod getSchemaMethod = new CodeMemberMethod(); getSchemaMethod.Name = "GetSchema"; getSchemaMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; getSchemaMethod.ImplementationTypes.Add(Globals.TypeOfIXmlSerializable); getSchemaMethod.ReturnType = GetCodeTypeReference(typeof(XmlSchema)); getSchemaMethod.Statements.Add(new CodeMethodReturnStatement(NullReference)); return getSchemaMethod; } } CodeMemberMethod GetSchemaStaticMethod { get { CodeMemberMethod getSchemaStaticMethod = new CodeMemberMethod(); getSchemaStaticMethod.Name = Globals.ExportSchemaMethod; getSchemaStaticMethod.ReturnType = GetCodeTypeReference(Globals.TypeOfXmlQualifiedName); CodeParameterDeclarationExpression paramDeclaration = new CodeParameterDeclarationExpression(Globals.TypeOfXmlSchemaSet, "schemas"); getSchemaStaticMethod.Parameters.Add(paramDeclaration); getSchemaStaticMethod.Attributes = MemberAttributes.Static | MemberAttributes.Public; getSchemaStaticMethod.Statements.Add( new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(GetCodeTypeReference(typeof(XmlSerializableServices))), XmlSerializableServices.AddDefaultSchemaMethodName, new CodeArgumentReferenceExpression(paramDeclaration.Name), new CodeFieldReferenceExpression(null, typeNameFieldName) ) ); getSchemaStaticMethod.Statements.Add( new CodeMethodReturnStatement( new CodeFieldReferenceExpression(null, typeNameFieldName) ) ); return getSchemaStaticMethod; } } CodeConstructor ISerializableBaseConstructor { get { CodeConstructor baseConstructor = new CodeConstructor(); baseConstructor.Attributes = MemberAttributes.Public; baseConstructor.Parameters.Add(SerializationInfoParameter); baseConstructor.Parameters.Add(StreamingContextParameter); CodeAssignStatement setObjectData = new CodeAssignStatement(); setObjectData.Left = new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoFieldName); setObjectData.Right = new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName); baseConstructor.Statements.Add(setObjectData); // Special-cased check for vb here since CodeGeneratorOptions does not provide information indicating that VB cannot initialize event member if (EnableDataBinding && SupportsDeclareEvents && String.CompareOrdinal(FileExtension, "vb") != 0) { baseConstructor.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(ThisReference, PropertyChangedEvent.Name), NullReference)); } return baseConstructor; } } CodeConstructor ISerializableDerivedConstructor { get { CodeConstructor derivedConstructor = new CodeConstructor(); derivedConstructor.Attributes = MemberAttributes.Public; derivedConstructor.Parameters.Add(SerializationInfoParameter); derivedConstructor.Parameters.Add(StreamingContextParameter); derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.SerializationInfoFieldName)); derivedConstructor.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(Globals.ContextFieldName)); return derivedConstructor; } } CodeMemberField SerializationInfoField { get { CodeMemberField serializationInfoField = new CodeMemberField(); serializationInfoField.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfo); serializationInfoField.Name = Globals.SerializationInfoFieldName; serializationInfoField.Attributes = MemberAttributes.Private; return serializationInfoField; } } CodeMemberProperty SerializationInfoProperty { get { return CreateProperty(GetCodeTypeReference(Globals.TypeOfSerializationInfo), Globals.SerializationInfoPropertyName, Globals.SerializationInfoFieldName, false/*isValueType*/); } } CodeMemberMethod GetObjectDataMethod { get { CodeMemberMethod getObjectDataMethod = new CodeMemberMethod(); getObjectDataMethod.Name = Globals.GetObjectDataMethodName; getObjectDataMethod.Parameters.Add(SerializationInfoParameter); getObjectDataMethod.Parameters.Add(StreamingContextParameter); getObjectDataMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; getObjectDataMethod.ImplementationTypes.Add(Globals.TypeOfISerializable); // Generates: if (this.SerializationInfo == null) return; CodeConditionStatement returnIfNull = new CodeConditionStatement(); returnIfNull.Condition = new CodeBinaryOperatorExpression( new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName), CodeBinaryOperatorType.IdentityEquality, NullReference); returnIfNull.TrueStatements.Add(new CodeMethodReturnStatement()); // Generates: SerializationInfoEnumerator enumerator = this.SerializationInfo.GetEnumerator(); CodeVariableDeclarationStatement getEnumerator = new CodeVariableDeclarationStatement(); getEnumerator.Type = GetCodeTypeReference(Globals.TypeOfSerializationInfoEnumerator); getEnumerator.Name = Globals.EnumeratorFieldName; getEnumerator.InitExpression = new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(ThisReference, Globals.SerializationInfoPropertyName), Globals.GetEnumeratorMethodName); //Generates: SerializationEntry entry = enumerator.Current; CodeVariableDeclarationStatement getCurrent = new CodeVariableDeclarationStatement(); getCurrent.Type = GetCodeTypeReference(Globals.TypeOfSerializationEntry); getCurrent.Name = Globals.SerializationEntryFieldName; getCurrent.InitExpression = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.EnumeratorFieldName), Globals.CurrentPropertyName); //Generates: info.AddValue(entry.Name, entry.Value); CodeExpressionStatement addValue = new CodeExpressionStatement(); CodePropertyReferenceExpression getCurrentName = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName), Globals.NameProperty); CodePropertyReferenceExpression getCurrentValue = new CodePropertyReferenceExpression( new CodeVariableReferenceExpression(Globals.SerializationEntryFieldName), Globals.ValueProperty); addValue.Expression = new CodeMethodInvokeExpression( new CodeArgumentReferenceExpression(Globals.SerializationInfoFieldName), Globals.AddValueMethodName, new CodeExpression[] { getCurrentName, getCurrentValue }); //Generates: for (; enumerator.MoveNext(); ) CodeIterationStatement loop = new CodeIterationStatement(); loop.TestExpression = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression(Globals.EnumeratorFieldName), Globals.MoveNextMethodName); loop.InitStatement = loop.IncrementStatement = new CodeSnippetStatement(String.Empty); loop.Statements.Add(getCurrent); loop.Statements.Add(addValue); getObjectDataMethod.Statements.Add(returnIfNull); getObjectDataMethod.Statements.Add(getEnumerator); getObjectDataMethod.Statements.Add(loop); return getObjectDataMethod; } } CodeMemberField ExtensionDataObjectField { get { CodeMemberField extensionDataObjectField = new CodeMemberField(); extensionDataObjectField.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject); extensionDataObjectField.Name = Globals.ExtensionDataObjectFieldName; extensionDataObjectField.Attributes = MemberAttributes.Private; return extensionDataObjectField; } } CodeMemberProperty ExtensionDataObjectProperty { get { CodeMemberProperty extensionDataObjectProperty = new CodeMemberProperty(); extensionDataObjectProperty.Type = GetCodeTypeReference(Globals.TypeOfExtensionDataObject); extensionDataObjectProperty.Name = Globals.ExtensionDataObjectPropertyName; extensionDataObjectProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; extensionDataObjectProperty.ImplementationTypes.Add(Globals.TypeOfIExtensibleDataObject); CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement(); propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName); extensionDataObjectProperty.GetStatements.Add(propertyGet); CodeAssignStatement propertySet = new CodeAssignStatement(); propertySet.Left = new CodeFieldReferenceExpression(ThisReference, Globals.ExtensionDataObjectFieldName); propertySet.Right = new CodePropertySetValueReferenceExpression(); extensionDataObjectProperty.SetStatements.Add(propertySet); return extensionDataObjectProperty; } } CodeMemberMethod RaisePropertyChangedEventMethod { get { CodeMemberMethod raisePropertyChangedEventMethod = new CodeMemberMethod(); raisePropertyChangedEventMethod.Name = "RaisePropertyChanged"; raisePropertyChangedEventMethod.Attributes = MemberAttributes.Final; CodeArgumentReferenceExpression propertyName = new CodeArgumentReferenceExpression("propertyName"); raisePropertyChangedEventMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), propertyName.ParameterName)); CodeVariableReferenceExpression propertyChanged = new CodeVariableReferenceExpression("propertyChanged"); raisePropertyChangedEventMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(PropertyChangedEventHandler), propertyChanged.VariableName, new CodeEventReferenceExpression(ThisReference, PropertyChangedEvent.Name))); CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(propertyChanged, CodeBinaryOperatorType.IdentityInequality, NullReference)); raisePropertyChangedEventMethod.Statements.Add(ifStatement); ifStatement.TrueStatements.Add(new CodeDelegateInvokeExpression(propertyChanged, ThisReference, new CodeObjectCreateExpression(typeof(PropertyChangedEventArgs), propertyName))); return raisePropertyChangedEventMethod; } } CodeMemberEvent PropertyChangedEvent { get { CodeMemberEvent propertyChangedEvent = new CodeMemberEvent(); propertyChangedEvent.Attributes = MemberAttributes.Public; propertyChangedEvent.Name = "PropertyChanged"; propertyChangedEvent.Type = GetCodeTypeReference(typeof(PropertyChangedEventHandler)); propertyChangedEvent.ImplementationTypes.Add(Globals.TypeOfIPropertyChange); return propertyChangedEvent; } } CodeMemberProperty CreateProperty(CodeTypeReference type, string propertyName, string fieldName, bool isValueType) { CodeMemberProperty property = new CodeMemberProperty(); property.Type = type; property.Name = propertyName; property.Attributes = MemberAttributes.Final; if(GenerateInternalTypes) property.Attributes |= MemberAttributes.Assembly; else property.Attributes |= MemberAttributes.Public; CodeMethodReturnStatement propertyGet = new CodeMethodReturnStatement(); propertyGet.Expression = new CodeFieldReferenceExpression(ThisReference, fieldName); property.GetStatements.Add(propertyGet); CodeAssignStatement propertySet = new CodeAssignStatement(); propertySet.Left = new CodeFieldReferenceExpression(ThisReference, fieldName); propertySet.Right = new CodePropertySetValueReferenceExpression(); if (EnableDataBinding && SupportsDeclareEvents) { CodeConditionStatement ifStatement = new CodeConditionStatement(); CodeExpression left = new CodeFieldReferenceExpression(ThisReference, fieldName); CodeExpression right = new CodePropertySetValueReferenceExpression(); if(!isValueType) { left = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(Globals.TypeOfObject), "ReferenceEquals", new CodeExpression[] { left, right } ); } else { left = new CodeMethodInvokeExpression(left, "Equals", new CodeExpression[] { right } ); } right = new CodePrimitiveExpression(true); ifStatement.Condition = new CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.IdentityInequality, right); ifStatement.TrueStatements.Add(propertySet); ifStatement.TrueStatements.Add(new CodeMethodInvokeExpression(ThisReference, RaisePropertyChangedEventMethod.Name, new CodePrimitiveExpression(propertyName))); property.SetStatements.Add(ifStatement); } else property.SetStatements.Add(propertySet); return property; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataViewManager.cs
- FormsAuthentication.cs
- RemotingConfiguration.cs
- SecurityDocument.cs
- Timer.cs
- StatusStrip.cs
- StreamReader.cs
- DataGridViewRowStateChangedEventArgs.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- _NetworkingPerfCounters.cs
- Pen.cs
- RegisteredDisposeScript.cs
- SmiRecordBuffer.cs
- XmlSchemaAnnotated.cs
- BinaryCommonClasses.cs
- BaseTemplateCodeDomTreeGenerator.cs
- PersonalizationProvider.cs
- Atom10FormatterFactory.cs
- CodeTypeConstructor.cs
- NegotiateStream.cs
- DescendentsWalker.cs
- WebPartConnectionsConnectVerb.cs
- log.cs
- Matrix3DStack.cs
- TypeListConverter.cs
- LoadItemsEventArgs.cs
- UnmanagedMarshal.cs
- DataFormat.cs
- TreeNodeStyleCollectionEditor.cs
- DisplayInformation.cs
- DLinqDataModelProvider.cs
- Win32Exception.cs
- PolygonHotSpot.cs
- CompoundFileDeflateTransform.cs
- XmlSignificantWhitespace.cs
- WebPartZoneCollection.cs
- AnnotationMap.cs
- HijriCalendar.cs
- GenericWebPart.cs
- UIElementHelper.cs
- InputLanguageEventArgs.cs
- MemberPath.cs
- _SSPIWrapper.cs
- ToolStripScrollButton.cs
- HtmlWindowCollection.cs
- TextRange.cs
- EntityDataSource.cs
- ErrorHandler.cs
- UnmanagedMemoryStreamWrapper.cs
- OutOfMemoryException.cs
- TextDecorationCollection.cs
- ReaderWriterLockWrapper.cs
- _ListenerRequestStream.cs
- SystemBrushes.cs
- DBConcurrencyException.cs
- RegexBoyerMoore.cs
- DocumentPageView.cs
- FunctionParameter.cs
- EmissiveMaterial.cs
- RouteUrlExpressionBuilder.cs
- ValueHandle.cs
- OleDbRowUpdatedEvent.cs
- DataGridViewToolTip.cs
- FloatUtil.cs
- LoginName.cs
- ContentIterators.cs
- EntryIndex.cs
- DES.cs
- BamlTreeNode.cs
- DataBindingCollection.cs
- validationstate.cs
- MenuCommandService.cs
- StateDesigner.cs
- KeyNotFoundException.cs
- FontDialog.cs
- ShutDownListener.cs
- ContravarianceAdapter.cs
- DataControlLinkButton.cs
- Evidence.cs
- ResourceReader.cs
- InfoCardClaimCollection.cs
- TypeUsageBuilder.cs
- CodeTypeDeclarationCollection.cs
- AnnotationAdorner.cs
- Rotation3DAnimation.cs
- WebPageTraceListener.cs
- RenderContext.cs
- cookie.cs
- AnnotationComponentChooser.cs
- RTLAwareMessageBox.cs
- XmlILStorageConverter.cs
- PointCollectionConverter.cs
- FileDialog_Vista.cs
- PolicyStatement.cs
- SmtpLoginAuthenticationModule.cs
- AsyncResult.cs
- DataGrid.cs
- TransactedReceiveScope.cs
- basecomparevalidator.cs
- NativeCompoundFileAPIs.cs