| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- //------------------------------------------------------------------------------
- // <copyright file="CodeExporter.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">Microsoft</owner>
- //------------------------------------------------------------------------------
- namespace System.Xml.Serialization {
-
- using System;
- using System.Collections;
- using System.IO;
- using System.ComponentModel;
- using System.Xml.Schema;
- using System.CodeDom;
- using System.CodeDom.Compiler;
- using System.Reflection;
- using System.Globalization;
- using System.Diagnostics;
- using System.Security.Permissions;
- /// <include file='doc\CodeExporter.uex' path='docs/doc[@for="CodeExporter"]/*' />
- ///<internalonly/>
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")]
- public abstract class CodeExporter {
- Hashtable exportedMappings;
- Hashtable exportedClasses; // TypeMapping -> CodeTypeDeclaration
- CodeNamespace codeNamespace;
- CodeCompileUnit codeCompileUnit;
- bool rootExported;
- TypeScope scope;
- CodeAttributeDeclarationCollection includeMetadata = new CodeAttributeDeclarationCollection();
- CodeGenerationOptions options;
- CodeDomProvider codeProvider;
- CodeAttributeDeclaration generatedCodeAttribute;
- internal CodeExporter(CodeNamespace codeNamespace, CodeCompileUnit codeCompileUnit, CodeDomProvider codeProvider, CodeGenerationOptions options, Hashtable exportedMappings) {
- if (codeNamespace != null)
- CodeGenerator.ValidateIdentifiers(codeNamespace);
- this.codeNamespace = codeNamespace;
- if (codeCompileUnit != null) {
- if (!codeCompileUnit.ReferencedAssemblies.Contains("System.dll"))
- codeCompileUnit.ReferencedAssemblies.Add("System.dll");
- if (!codeCompileUnit.ReferencedAssemblies.Contains("System.Xml.dll"))
- codeCompileUnit.ReferencedAssemblies.Add("System.Xml.dll");
- }
- this.codeCompileUnit = codeCompileUnit;
- this.options = options;
- this.exportedMappings = exportedMappings;
- this.codeProvider = codeProvider;
- }
- internal CodeCompileUnit CodeCompileUnit {
- get { return codeCompileUnit; }
- }
- internal CodeNamespace CodeNamespace {
- get {
- if (codeNamespace == null)
- codeNamespace = new CodeNamespace();
- return codeNamespace;
- }
- }
- internal CodeDomProvider CodeProvider {
- get {
- if (codeProvider == null)
- codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
- return codeProvider;
- }
- }
- internal Hashtable ExportedClasses {
- get {
- if (exportedClasses == null)
- exportedClasses = new Hashtable();
- return exportedClasses;
- }
- }
- internal Hashtable ExportedMappings {
- get {
- if (exportedMappings == null)
- exportedMappings = new Hashtable();
- return exportedMappings;
- }
- }
- internal bool GenerateProperties {
- get { return (options & CodeGenerationOptions.GenerateProperties) != 0; }
- }
- internal CodeAttributeDeclaration GeneratedCodeAttribute {
- get {
- if (generatedCodeAttribute == null) {
- CodeAttributeDeclaration decl = new CodeAttributeDeclaration(typeof(GeneratedCodeAttribute).FullName);
- Assembly a = Assembly.GetEntryAssembly();
- if (a == null) {
- a = Assembly.GetExecutingAssembly();
- if (a == null) {
- a = typeof(CodeExporter).Assembly;
- }
- }
- AssemblyName assemblyName = a.GetName();
- decl.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(assemblyName.Name)));
- string version = GetProductVersion(a);
- decl.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(version == null ? assemblyName.Version.ToString() : version)));
- generatedCodeAttribute = decl;
- }
- return generatedCodeAttribute;
- }
- }
- internal static CodeAttributeDeclaration FindAttributeDeclaration(Type type, CodeAttributeDeclarationCollection metadata) {
- foreach (CodeAttributeDeclaration attribute in metadata) {
- if (attribute.Name == type.FullName || attribute.Name == type.Name) {
- return attribute;
- }
- }
- return null;
- }
- private static string GetProductVersion(Assembly assembly) {
- object[] attributes = assembly.GetCustomAttributes(true);
- for ( int i = 0; i<attributes.Length; i++ ) {
- if (attributes[i] is AssemblyInformationalVersionAttribute) {
- AssemblyInformationalVersionAttribute version = (AssemblyInformationalVersionAttribute)attributes[i];
- return version.InformationalVersion;
- }
- }
- return null;
- }
- /// <include file='doc\XmlCodeExporter.uex' path='docs/doc[@for="XmlCodeExporter.IncludeMetadata"]/*' />
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- public CodeAttributeDeclarationCollection IncludeMetadata {
- get { return includeMetadata; }
- }
- internal TypeScope Scope {
- get { return scope; }
- }
- internal void CheckScope(TypeScope scope) {
- if (this.scope == null) {
- this.scope = scope;
- }
- else if (this.scope != scope) {
- throw new InvalidOperationException(Res.GetString(Res.XmlMappingsScopeMismatch));
- }
- }
- internal abstract void ExportDerivedStructs(StructMapping mapping);
- internal abstract void EnsureTypesExported(Accessor[] accessors, string ns);
- internal static void AddWarningComment(CodeCommentStatementCollection comments, string text) {
- Debug.Assert(comments != null);
- comments.Add(new CodeCommentStatement(Res.GetString(Res.XmlCodegenWarningDetails, text), false));
- }
- internal void ExportRoot(StructMapping mapping, Type includeType) {
- if (!rootExported) {
- rootExported = true;
- ExportDerivedStructs(mapping);
- for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
- if (!derived.ReferencedByElement && derived.IncludeInSchema && !derived.IsAnonymousType) {
- CodeAttributeDeclaration include = new CodeAttributeDeclaration(includeType.FullName);
- include.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(derived.TypeDesc.FullName)));
- includeMetadata.Add(include);
- }
- }
- Hashtable typesIncluded = new Hashtable();
- foreach (TypeMapping m in Scope.TypeMappings) {
- if (m is ArrayMapping) {
- ArrayMapping arrayMapping = (ArrayMapping) m;
- if (ShouldInclude(arrayMapping) && !typesIncluded.Contains(arrayMapping.TypeDesc.FullName)) {
- CodeAttributeDeclaration include = new CodeAttributeDeclaration(includeType.FullName);
- include.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(arrayMapping.TypeDesc.FullName)));
- includeMetadata.Add(include);
- typesIncluded.Add(arrayMapping.TypeDesc.FullName, string.Empty);
- EnsureTypesExported(arrayMapping.Elements, arrayMapping.Namespace);
- }
- }
- }
- }
- }
- private static bool ShouldInclude(ArrayMapping arrayMapping) {
- if (arrayMapping.ReferencedByElement)
- return false;
- if (arrayMapping.Next != null)
- return false;
- if (arrayMapping.Elements.Length == 1) {
- TypeKind kind = arrayMapping.Elements[0].Mapping.TypeDesc.Kind;
- if (kind == TypeKind.Node)
- return false;
- }
- for (int i = 0; i < arrayMapping.Elements.Length; i++) {
- if (arrayMapping.Elements[i].Name != arrayMapping.Elements[i].Mapping.DefaultElementName) {
- // in the case we need custom attributes to serialize an array instance, we cannot include arrau mapping without explicit reference.
- return false;
- }
- }
- return true;
- }
- internal CodeTypeDeclaration ExportEnum(EnumMapping mapping, Type type) {
- CodeTypeDeclaration codeClass = new CodeTypeDeclaration(mapping.TypeDesc.Name);
- codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.XmlRemarks), true));
- codeClass.IsEnum = true;
- if (mapping.IsFlags && mapping.Constants.Length > 31) {
- codeClass.BaseTypes.Add(new CodeTypeReference(typeof(long)));
- }
- codeClass.TypeAttributes |= TypeAttributes.Public;
- CodeNamespace.Types.Add(codeClass);
- for (int i = 0; i < mapping.Constants.Length; i++) {
- ExportConstant(codeClass, mapping.Constants[i], type, mapping.IsFlags, 1L << i);
- }
- if (mapping.IsFlags) {
- // Add [FlagsAttribute]
- CodeAttributeDeclaration flags = new CodeAttributeDeclaration(typeof(FlagsAttribute).FullName);
- codeClass.CustomAttributes.Add(flags);
- }
- CodeGenerator.ValidateIdentifiers(codeClass);
- return codeClass;
- }
- internal void AddTypeMetadata(CodeAttributeDeclarationCollection metadata, Type type, string defaultName, string name, string ns, bool includeInSchema) {
- CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(type.FullName);
- if (name == null || name.Length == 0) {
- attribute.Arguments.Add(new CodeAttributeArgument("AnonymousType", new CodePrimitiveExpression(true)));
- }
- else {
- if (defaultName != name) {
- attribute.Arguments.Add(new CodeAttributeArgument("TypeName", new CodePrimitiveExpression(name)));
- }
- }
- if (ns != null && ns.Length != 0) {
- attribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(ns)));
- }
- if (!includeInSchema) {
- attribute.Arguments.Add(new CodeAttributeArgument("IncludeInSchema", new CodePrimitiveExpression(false)));
- }
- if (attribute.Arguments.Count > 0) {
- metadata.Add(attribute);
- }
- }
- internal static void AddIncludeMetadata(CodeAttributeDeclarationCollection metadata, StructMapping mapping, Type type) {
- if (mapping.IsAnonymousType)
- return;
- for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
- CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(type.FullName);
- attribute.Arguments.Add(new CodeAttributeArgument(new CodeTypeOfExpression(derived.TypeDesc.FullName)));
- metadata.Add(attribute);
- AddIncludeMetadata(metadata, derived, type);
- }
- }
- internal static void ExportConstant(CodeTypeDeclaration codeClass, ConstantMapping constant, Type type, bool init, long enumValue) {
- CodeMemberField field = new CodeMemberField(typeof(int).FullName, constant.Name);
- field.Comments.Add(new CodeCommentStatement(Res.GetString(Res.XmlRemarks), true));
- if (init)
- field.InitExpression = new CodePrimitiveExpression(enumValue);
- codeClass.Members.Add(field);
- if (constant.XmlName != constant.Name) {
- CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(type.FullName);
- attribute.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(constant.XmlName)));
- field.CustomAttributes.Add(attribute);
- }
- }
- internal static object PromoteType(Type type, object value) {
- if (type == typeof(sbyte)) {
- return ((IConvertible)value).ToInt16(null);
- }
- else if (type == typeof(UInt16)) {
- return ((IConvertible)value).ToInt32(null);
- }
- else if (type == typeof(UInt32)) {
- return ((IConvertible)value).ToInt64(null);
- }
- else if (type == typeof(UInt64)) {
- return ((IConvertible)value).ToDecimal(null);
- }
- else {
- return value;
- }
- }
- internal CodeMemberProperty CreatePropertyDeclaration(CodeMemberField field, string name, string typeName) {
- CodeMemberProperty prop = new CodeMemberProperty();
- prop.Type = new CodeTypeReference(typeName);
- prop.Name = name;
- prop.Attributes = (prop.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Public;
- //add get
- CodeMethodReturnStatement ret = new CodeMethodReturnStatement();
- ret.Expression = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name);
- prop.GetStatements.Add(ret);
-
- CodeAssignStatement propertySet = new CodeAssignStatement();
- CodeExpression left = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name);
- CodeExpression right = new CodePropertySetValueReferenceExpression();
- propertySet.Left = left;
- propertySet.Right = right;
- if (EnableDataBinding)
- {
- prop.SetStatements.Add(propertySet);
- prop.SetStatements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), RaisePropertyChangedEventMethod.Name, new CodePrimitiveExpression(name)));
- }
- else
- prop.SetStatements.Add(propertySet);
- return prop;
- }
- internal static string MakeFieldName(string name) {
- return CodeIdentifier.MakeCamel(name) + "Field";
- }
- internal void AddPropertyChangedNotifier(CodeTypeDeclaration codeClass)
- {
- if (EnableDataBinding && codeClass != null)
- {
- if (codeClass.BaseTypes.Count == 0)
- {
- codeClass.BaseTypes.Add(typeof(object));
- }
- codeClass.BaseTypes.Add(new CodeTypeReference(typeof(System.ComponentModel.INotifyPropertyChanged)));
- codeClass.Members.Add(PropertyChangedEvent);
- codeClass.Members.Add(RaisePropertyChangedEventMethod);
- }
- }
-
- bool EnableDataBinding {
- get { return (options & CodeGenerationOptions.EnableDataBinding) != 0; }
- }
- internal static CodeMemberMethod RaisePropertyChangedEventMethod
- {
- get
- {
- CodeMemberMethod raisePropertyChangedEventMethod = new CodeMemberMethod();
- raisePropertyChangedEventMethod.Name = "RaisePropertyChanged";
- raisePropertyChangedEventMethod.Attributes = MemberAttributes.Family | 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(new CodeThisReferenceExpression(), PropertyChangedEvent.Name)));
- CodeConditionStatement ifStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(propertyChanged, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)));
- raisePropertyChangedEventMethod.Statements.Add(ifStatement);
- ifStatement.TrueStatements.Add(new CodeDelegateInvokeExpression(propertyChanged, new CodeThisReferenceExpression(), new CodeObjectCreateExpression(typeof(PropertyChangedEventArgs), propertyName)));
- return raisePropertyChangedEventMethod;
- }
- }
- internal static CodeMemberEvent PropertyChangedEvent
- {
- get
- {
- CodeMemberEvent propertyChangedEvent = new CodeMemberEvent();
- propertyChangedEvent.Attributes = MemberAttributes.Public;
- propertyChangedEvent.Name = "PropertyChanged";
- propertyChangedEvent.Type = new CodeTypeReference(typeof(PropertyChangedEventHandler));
- propertyChangedEvent.ImplementationTypes.Add(typeof(System.ComponentModel.INotifyPropertyChanged));
- return propertyChangedEvent;
- }
- }
- }
- }
|