You've already forked linux-packaging-mono
1984 lines
101 KiB
C#
1984 lines
101 KiB
C#
![]() |
//------------------------------------------------------------
|
||
|
// 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<System.Xml.XmlQualifiedName, DataContract>;
|
||
|
|
||
|
class CodeExporter
|
||
|
{
|
||
|
DataContractSet dataContractSet;
|
||
|
CodeCompileUnit codeCompileUnit;
|
||
|
ImportOptions options;
|
||
|
Dictionary<string, string> namespaces;
|
||
|
Dictionary<string, string> 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<string, string>();
|
||
|
this.clrNamespaces = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||
|
|
||
|
// Update namespace tables for DataContract(s) that are already processed
|
||
|
foreach (KeyValuePair<XmlQualifiedName, DataContract> 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<string, string> 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
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareEvents); }
|
||
|
}
|
||
|
|
||
|
bool SupportsDeclareValueTypes
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.DeclareValueTypes); }
|
||
|
}
|
||
|
|
||
|
bool SupportsGenericTypeReference
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.GenericTypeReference); }
|
||
|
}
|
||
|
|
||
|
bool SupportsAssemblyAttributes
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.AssemblyAttributes); }
|
||
|
}
|
||
|
|
||
|
bool SupportsPartialTypes
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.PartialTypes); }
|
||
|
}
|
||
|
|
||
|
bool SupportsNestedTypes
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.Supports(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? true : CodeProvider.Supports(GeneratorSupport.NestedTypes); }
|
||
|
}
|
||
|
|
||
|
string FileExtension
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeProvider.FileExtension property that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
get { return (CodeProvider == null) ? String.Empty : CodeProvider.FileExtension; }
|
||
|
}
|
||
|
|
||
|
Dictionary<string, string> Namespaces
|
||
|
{
|
||
|
get { return namespaces; }
|
||
|
}
|
||
|
|
||
|
Dictionary<string, string> 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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(..) method that has a LinkDemand for FullTrust.")]
|
||
|
[SecurityCritical]
|
||
|
internal void Export()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
foreach (KeyValuePair<XmlQualifiedName, DataContract> 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<XmlQualifiedName, object>());
|
||
|
}
|
||
|
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<XmlQualifiedName, object> 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 < genInfo.Parameters.Count; i++)
|
||
|
{
|
||
|
GenericInfo paramInfo = genInfo.Parameters[i];
|
||
|
XmlQualifiedName stableName = paramInfo.GetExpandedStableName();
|
||
|
DataContract paramContract = dataContractSet[stableName];
|
||
|
|
||
|
CodeTypeReference paramTypeReference;
|
||
|
bool isParamValueType;
|
||
|
if (paramContract != null)
|
||
|
{
|
||
|
paramTypeReference = GetCodeTypeReference(paramContract);
|
||
|
isParamValueType = paramContract.IsValueType;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
paramTypeReference = GetReferencedGenericType(paramInfo, out paramContract);
|
||
|
isParamValueType = (paramTypeReference != null && paramTypeReference.ArrayRank == 0); // only value type information we can get from CodeTypeReference
|
||
|
}
|
||
|
paramContracts[i] = paramContract;
|
||
|
if (paramContract == null)
|
||
|
enableStructureCheck = false;
|
||
|
if (paramTypeReference == null)
|
||
|
return null;
|
||
|
if (type == Globals.TypeOfNullable && !isParamValueType)
|
||
|
return paramTypeReference;
|
||
|
else
|
||
|
typeReference.TypeArguments.Add(paramTypeReference);
|
||
|
}
|
||
|
if (enableStructureCheck)
|
||
|
dataContract = DataContract.GetDataContract(type).BindGenericParameters(paramContracts, new Dictionary<DataContract, DataContract>());
|
||
|
}
|
||
|
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);
|
||
|
|
||
|
bool raisePropertyChanged = EnableDataBinding && SupportsDeclareEvents;
|
||
|
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);
|
||
|
if (!Globals.TypeOfIPropertyChange.IsAssignableFrom(actualType))
|
||
|
{
|
||
|
AddPropertyChangedNotifier(contractCodeDomInfo, type.IsStruct);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
raisePropertyChanged = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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, raisePropertyChanged);
|
||
|
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<CodeTypeReference> GetKnownTypeReferences(DataContract dataContract)
|
||
|
{
|
||
|
DataContractDictionary knownTypeDictionary = GetKnownTypeContracts(dataContract);
|
||
|
if (knownTypeDictionary == null)
|
||
|
return null;
|
||
|
|
||
|
ICollection<DataContract> knownTypeContracts = knownTypeDictionary.Values;
|
||
|
if (knownTypeContracts == null || knownTypeContracts.Count == 0)
|
||
|
return null;
|
||
|
|
||
|
List<CodeTypeReference> knownTypeReferences = new List<CodeTypeReference>();
|
||
|
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<DataContract, object>());
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
DataContractDictionary GetKnownTypeContracts(ClassDataContract dataContract, Dictionary<DataContract, object> 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<XmlQualifiedName, DataContract> 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<DataContract, object>());
|
||
|
if (knownContractDictionary == null || knownContractDictionary.Count == 0)
|
||
|
return;
|
||
|
|
||
|
ICollection<DataContract> 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<string, object> baseMemberNames = baseContractCodeDomInfo.GetMemberNames();
|
||
|
Dictionary<string, object> memberNames = contractCodeDomInfo.GetMemberNames();
|
||
|
foreach (KeyValuePair<string, object> pair in baseMemberNames)
|
||
|
{
|
||
|
memberNames.Add(pair.Key, pair.Value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Critical because it calls the CodeGenerator.IsValidLanguageIndependentIdentifier(..) method that has a LinkDemand.",
|
||
|
Safe = "Safe because it doesn't leak security sensitive information.")]
|
||
|
[SecuritySafeCritical]
|
||
|
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<string, object> fragments = new Dictionary<string, object>(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<string, object> 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<string, object> 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)
|
||
|
{
|
||
|
return CreateProperty(type, propertyName, fieldName, isValueType, EnableDataBinding && SupportsDeclareEvents);
|
||
|
}
|
||
|
|
||
|
CodeMemberProperty CreateProperty(CodeTypeReference type, string propertyName, string fieldName, bool isValueType, bool raisePropertyChanged)
|
||
|
{
|
||
|
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 (raisePropertyChanged)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|