The Labs \ Source Viewer \ SSCLI \ System.Xml.Serialization \ XmlSerializationCodeGen

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSerializationGeneratedCode.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <owner current="true" primary="true">ElenaK</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Serialization
  17. {
  18.     using System;
  19.     using System.IO;
  20.     using System.Collections;
  21.     using System.ComponentModel;
  22.     using System.Threading;
  23.     using System.Reflection;
  24.     using System.Security;
  25.     using System.Globalization;
  26.    
  27.     /// <include file='doc\XmlSerializationGeneratedCode.uex' path='docs/doc[@for="XmlSerializationGeneratedCode"]/*' />
  28.     ///<internalonly/>
  29.     public abstract class XmlSerializationGeneratedCode
  30.     {
  31.         TempAssembly tempAssembly;
  32.         int threadCode;
  33.         ResolveEventHandler assemblyResolver;
  34.        
  35.         internal void Init(TempAssembly tempAssembly)
  36.         {
  37.             this.tempAssembly = tempAssembly;
  38.             // only hook the assembly resolver if we have something to help us do the resolution
  39.             if (tempAssembly != null && tempAssembly.NeedAssembyResolve) {
  40.                 // we save the threadcode to make sure we don't handle any resolve events for any other threads
  41.                 threadCode = Thread.CurrentThread.GetHashCode();
  42.                 assemblyResolver = new ResolveEventHandler(OnAssemblyResolve);
  43.                 AppDomain.CurrentDomain.AssemblyResolve += assemblyResolver;
  44.             }
  45.         }
  46.        
  47.         // this method must be called at the end of serialization
  48.         internal void Dispose()
  49.         {
  50.             if (assemblyResolver != null)
  51.                 AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolver;
  52.             assemblyResolver = null;
  53.         }
  54.        
  55.         internal Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
  56.         {
  57.             if (tempAssembly != null && Thread.CurrentThread.GetHashCode() == threadCode)
  58.                 return tempAssembly.GetReferencedAssembly(args.Name);
  59.             return null;
  60.         }
  61.     }
  62.    
  63.     internal class XmlSerializationCodeGen
  64.     {
  65.         IndentedWriter writer;
  66.         int nextMethodNumber = 0;
  67.         Hashtable methodNames = new Hashtable();
  68.         ReflectionAwareCodeGen raCodeGen;
  69.         TypeScope[] scopes;
  70.         TypeDesc stringTypeDesc = null;
  71.         TypeDesc qnameTypeDesc = null;
  72.         string access;
  73.         string className;
  74.         TypeMapping[] referencedMethods;
  75.         int references = 0;
  76.         Hashtable generatedMethods = new Hashtable();
  77.        
  78.         internal XmlSerializationCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className)
  79.         {
  80.             this.writer = writer;
  81.             this.scopes = scopes;
  82.             if (scopes.Length > 0) {
  83.                 stringTypeDesc = scopes[0].GetTypeDesc(typeof(string));
  84.                 qnameTypeDesc = scopes[0].GetTypeDesc(typeof(XmlQualifiedName));
  85.             }
  86.             this.raCodeGen = new ReflectionAwareCodeGen(writer);
  87.             this.className = className;
  88.             this.access = access;
  89.         }
  90.        
  91.         internal IndentedWriter Writer {
  92.             get { return writer; }
  93.         }
  94.         internal int NextMethodNumber {
  95.             get { return nextMethodNumber; }
  96.             set { nextMethodNumber = value; }
  97.         }
  98.         internal ReflectionAwareCodeGen RaCodeGen {
  99.             get { return raCodeGen; }
  100.         }
  101.         internal TypeDesc StringTypeDesc {
  102.             get { return stringTypeDesc; }
  103.         }
  104.         internal TypeDesc QnameTypeDesc {
  105.             get { return qnameTypeDesc; }
  106.         }
  107.         internal string ClassName {
  108.             get { return className; }
  109.         }
  110.         internal string Access {
  111.             get { return access; }
  112.         }
  113.         internal TypeScope[] Scopes {
  114.             get { return scopes; }
  115.         }
  116.         internal Hashtable MethodNames {
  117.             get { return methodNames; }
  118.         }
  119.         internal Hashtable GeneratedMethods {
  120.             get { return generatedMethods; }
  121.         }
  122.        
  123.         internal virtual void GenerateMethod(TypeMapping mapping)
  124.         {
  125.         }
  126.        
  127.         internal void GenerateReferencedMethods()
  128.         {
  129.             while (references > 0) {
  130.                 TypeMapping mapping = referencedMethods[--references];
  131.                 GenerateMethod(mapping);
  132.             }
  133.         }
  134.        
  135.         internal string ReferenceMapping(TypeMapping mapping)
  136.         {
  137.             if (!mapping.IsSoap) {
  138.                 if (generatedMethods[mapping] == null) {
  139.                     referencedMethods = EnsureArrayIndex(referencedMethods, references);
  140.                     referencedMethods[references++] = mapping;
  141.                 }
  142.             }
  143.             return (string)methodNames[mapping];
  144.         }
  145.        
  146.         TypeMapping[] EnsureArrayIndex(TypeMapping[] a, int index)
  147.         {
  148.             if (a == null)
  149.                 return new TypeMapping[32];
  150.             if (index < a.Length)
  151.                 return a;
  152.             TypeMapping[] b = new TypeMapping[a.Length + 32];
  153.             Array.Copy(a, b, index);
  154.             return b;
  155.         }
  156.        
  157.         internal void WriteQuotedCSharpString(string value)
  158.         {
  159.             raCodeGen.WriteQuotedCSharpString(value);
  160.         }
  161.        
  162.         internal void GenerateHashtableGetBegin(string privateName, string publicName)
  163.         {
  164.             writer.Write(typeof(Hashtable).FullName);
  165.             writer.Write(" ");
  166.             writer.Write(privateName);
  167.             writer.WriteLine(" = null;");
  168.             writer.Write("public override ");
  169.             writer.Write(typeof(Hashtable).FullName);
  170.            
  171.             writer.Write(" ");
  172.             writer.Write(publicName);
  173.             writer.WriteLine(" {");
  174.             writer.Indent++;
  175.            
  176.             writer.WriteLine("get {");
  177.             writer.Indent++;
  178.            
  179.             writer.Write("if (");
  180.             writer.Write(privateName);
  181.             writer.WriteLine(" == null) {");
  182.             writer.Indent++;
  183.            
  184.             writer.Write(typeof(Hashtable).FullName);
  185.             writer.Write(" _tmp = new ");
  186.             writer.Write(typeof(Hashtable).FullName);
  187.             writer.WriteLine("();");
  188.            
  189.         }
  190.        
  191.         internal void GenerateHashtableGetEnd(string privateName)
  192.         {
  193.             writer.Write("if (");
  194.             writer.Write(privateName);
  195.             writer.Write(" == null) ");
  196.             writer.Write(privateName);
  197.             writer.WriteLine(" = _tmp;");
  198.             writer.Indent--;
  199.             writer.WriteLine("}");
  200.            
  201.             writer.Write("return ");
  202.             writer.Write(privateName);
  203.             writer.WriteLine(";");
  204.             writer.Indent--;
  205.             writer.WriteLine("}");
  206.            
  207.             writer.Indent--;
  208.             writer.WriteLine("}");
  209.         }
  210.         internal void GeneratePublicMethods(string privateName, string publicName, string[] methods, XmlMapping[] xmlMappings)
  211.         {
  212.             GenerateHashtableGetBegin(privateName, publicName);
  213.             if (methods != null && methods.Length != 0 && xmlMappings != null && xmlMappings.Length == methods.Length) {
  214.                 for (int i = 0; i < methods.Length; i++) {
  215.                     if (methods[i] == null)
  216.                         continue;
  217.                     writer.Write("_tmp[");
  218.                     WriteQuotedCSharpString(xmlMappings[i].Key);
  219.                     writer.Write("] = ");
  220.                     WriteQuotedCSharpString(methods[i]);
  221.                     writer.WriteLine(";");
  222.                 }
  223.             }
  224.             GenerateHashtableGetEnd(privateName);
  225.         }
  226.        
  227.         internal void GenerateSupportedTypes(Type[] types)
  228.         {
  229.             writer.Write("public override ");
  230.             writer.Write(typeof(bool).FullName);
  231.             writer.Write(" CanSerialize(");
  232.             writer.Write(typeof(Type).FullName);
  233.             writer.WriteLine(" type) {");
  234.             writer.Indent++;
  235.             Hashtable uniqueTypes = new Hashtable();
  236.             for (int i = 0; i < types.Length; i++) {
  237.                 Type type = types[i];
  238.                
  239.                 if (type == null)
  240.                     continue;
  241.                 if (!type.IsPublic && !type.IsNestedPublic)
  242.                     continue;
  243.                 if (uniqueTypes[type] != null)
  244.                     continue;
  245.                 if (DynamicAssemblies.IsTypeDynamic(type))
  246.                     continue;
  247.                 if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments()))
  248.                     continue;
  249.                 uniqueTypes[type] = type;
  250.                 writer.Write("if (type == typeof(");
  251.                 writer.Write(CodeIdentifier.GetCSharpName(type));
  252.                 writer.WriteLine(")) return true;");
  253.             }
  254.             writer.WriteLine("return false;");
  255.             writer.Indent--;
  256.             writer.WriteLine("}");
  257.         }
  258.        
  259.         internal string GenerateBaseSerializer(string baseSerializer, string readerClass, string writerClass, CodeIdentifiers classes)
  260.         {
  261.             baseSerializer = CodeIdentifier.MakeValid(baseSerializer);
  262.             baseSerializer = classes.AddUnique(baseSerializer, baseSerializer);
  263.            
  264.             writer.WriteLine();
  265.             writer.Write("public abstract class ");
  266.             writer.Write(CodeIdentifier.GetCSharpName(baseSerializer));
  267.             writer.Write(" : ");
  268.             writer.Write(typeof(XmlSerializer).FullName);
  269.             writer.WriteLine(" {");
  270.             writer.Indent++;
  271.            
  272.             writer.Write("protected override ");
  273.             writer.Write(typeof(XmlSerializationReader).FullName);
  274.             writer.WriteLine(" CreateReader() {");
  275.             writer.Indent++;
  276.             writer.Write("return new ");
  277.             writer.Write(readerClass);
  278.             writer.WriteLine("();");
  279.             writer.Indent--;
  280.             writer.WriteLine("}");
  281.            
  282.             writer.Write("protected override ");
  283.             writer.Write(typeof(XmlSerializationWriter).FullName);
  284.             writer.WriteLine(" CreateWriter() {");
  285.             writer.Indent++;
  286.             writer.Write("return new ");
  287.             writer.Write(writerClass);
  288.             writer.WriteLine("();");
  289.             writer.Indent--;
  290.             writer.WriteLine("}");
  291.            
  292.             writer.Indent--;
  293.             writer.WriteLine("}");
  294.            
  295.             return baseSerializer;
  296.         }
  297.        
  298.         internal string GenerateTypedSerializer(string readMethod, string writeMethod, XmlMapping mapping, CodeIdentifiers classes, string baseSerializer, string readerClass, string writerClass)
  299.         {
  300.             string serializerName = CodeIdentifier.MakeValid(Accessor.UnescapeName(mapping.Accessor.Mapping.TypeDesc.Name));
  301.             serializerName = classes.AddUnique(serializerName + "Serializer", mapping);
  302.            
  303.             writer.WriteLine();
  304.             writer.Write("public sealed class ");
  305.             writer.Write(CodeIdentifier.GetCSharpName(serializerName));
  306.             writer.Write(" : ");
  307.             writer.Write(baseSerializer);
  308.             writer.WriteLine(" {");
  309.             writer.Indent++;
  310.            
  311.             writer.WriteLine();
  312.             writer.Write("public override ");
  313.             writer.Write(typeof(bool).FullName);
  314.             writer.Write(" CanDeserialize(");
  315.             writer.Write(typeof(XmlReader).FullName);
  316.             writer.WriteLine(" xmlReader) {");
  317.             writer.Indent++;
  318.            
  319.             if (mapping.Accessor.Any) {
  320.                 writer.WriteLine("return true;");
  321.             }
  322.             else {
  323.                 writer.Write("return xmlReader.IsStartElement(");
  324.                 WriteQuotedCSharpString(mapping.Accessor.Name);
  325.                 writer.Write(", ");
  326.                 WriteQuotedCSharpString(mapping.Accessor.Namespace);
  327.                 writer.WriteLine(");");
  328.             }
  329.             writer.Indent--;
  330.             writer.WriteLine("}");
  331.            
  332.             if (writeMethod != null) {
  333.                 writer.WriteLine();
  334.                 writer.Write("protected override void Serialize(object objectToSerialize, ");
  335.                 writer.Write(typeof(XmlSerializationWriter).FullName);
  336.                 writer.WriteLine(" writer) {");
  337.                 writer.Indent++;
  338.                 writer.Write("((");
  339.                 writer.Write(writerClass);
  340.                 writer.Write(")writer).");
  341.                 writer.Write(writeMethod);
  342.                 writer.Write("(");
  343.                 if (mapping is XmlMembersMapping) {
  344.                     writer.Write("(object[])");
  345.                 }
  346.                 writer.WriteLine("objectToSerialize);");
  347.                 writer.Indent--;
  348.                 writer.WriteLine("}");
  349.             }
  350.             if (readMethod != null) {
  351.                 writer.WriteLine();
  352.                 writer.Write("protected override object Deserialize(");
  353.                 writer.Write(typeof(XmlSerializationReader).FullName);
  354.                 writer.WriteLine(" reader) {");
  355.                 writer.Indent++;
  356.                 writer.Write("return ((");
  357.                 writer.Write(readerClass);
  358.                 writer.Write(")reader).");
  359.                 writer.Write(readMethod);
  360.                 writer.WriteLine("();");
  361.                 writer.Indent--;
  362.                 writer.WriteLine("}");
  363.             }
  364.             writer.Indent--;
  365.             writer.WriteLine("}");
  366.            
  367.             return serializerName;
  368.         }
  369.        
  370.         void GenerateTypedSerializers(Hashtable serializers)
  371.         {
  372.             string privateName = "typedSerializers";
  373.             GenerateHashtableGetBegin(privateName, "TypedSerializers");
  374.            
  375.             foreach (string key in serializers.Keys) {
  376.                 writer.Write("_tmp.Add(");
  377.                 WriteQuotedCSharpString(key);
  378.                 writer.Write(", new ");
  379.                 writer.Write((string)serializers[key]);
  380.                 writer.WriteLine("());");
  381.             }
  382.             GenerateHashtableGetEnd("typedSerializers");
  383.         }
  384.        
  385.         //GenerateGetSerializer(serializers, xmlMappings);
  386.         void GenerateGetSerializer(Hashtable serializers, XmlMapping[] xmlMappings)
  387.         {
  388.             writer.Write("public override ");
  389.             writer.Write(typeof(XmlSerializer).FullName);
  390.             writer.Write(" GetSerializer(");
  391.             writer.Write(typeof(Type).FullName);
  392.             writer.WriteLine(" type) {");
  393.             writer.Indent++;
  394.            
  395.             for (int i = 0; i < xmlMappings.Length; i++) {
  396.                 if (xmlMappings[i] is XmlTypeMapping) {
  397.                     Type type = xmlMappings[i].Accessor.Mapping.TypeDesc.Type;
  398.                     if (type == null)
  399.                         continue;
  400.                     if (!type.IsPublic && !type.IsNestedPublic)
  401.                         continue;
  402.                     if (DynamicAssemblies.IsTypeDynamic(type))
  403.                         continue;
  404.                     if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments()))
  405.                         continue;
  406.                     writer.Write("if (type == typeof(");
  407.                     writer.Write(CodeIdentifier.GetCSharpName(type));
  408.                     writer.Write(")) return new ");
  409.                     writer.Write((string)serializers[xmlMappings[i].Key]);
  410.                     writer.WriteLine("();");
  411.                 }
  412.             }
  413.             writer.WriteLine("return null;");
  414.             writer.Indent--;
  415.             writer.WriteLine("}");
  416.         }
  417.        
  418.         internal void GenerateSerializerContract(string className, XmlMapping[] xmlMappings, Type[] types, string readerType, string[] readMethods, string writerType, string[] writerMethods, Hashtable serializers)
  419.         {
  420.             writer.WriteLine();
  421.             writer.Write("public class XmlSerializerContract : global::");
  422.             writer.Write(typeof(XmlSerializerImplementation).FullName);
  423.             writer.WriteLine(" {");
  424.             writer.Indent++;
  425.            
  426.             writer.Write("public override global::");
  427.             writer.Write(typeof(XmlSerializationReader).FullName);
  428.             writer.Write(" Reader { get { return new ");
  429.             writer.Write(readerType);
  430.             writer.WriteLine("(); } }");
  431.            
  432.             writer.Write("public override global::");
  433.             writer.Write(typeof(XmlSerializationWriter).FullName);
  434.             writer.Write(" Writer { get { return new ");
  435.             writer.Write(writerType);
  436.             writer.WriteLine("(); } }");
  437.            
  438.             GeneratePublicMethods("readMethods", "ReadMethods", readMethods, xmlMappings);
  439.             GeneratePublicMethods("writeMethods", "WriteMethods", writerMethods, xmlMappings);
  440.             GenerateTypedSerializers(serializers);
  441.             GenerateSupportedTypes(types);
  442.             GenerateGetSerializer(serializers, xmlMappings);
  443.            
  444.             writer.Indent--;
  445.             writer.WriteLine("}");
  446.            
  447.         }
  448.        
  449.         static internal bool IsAnyElement(SpecialMapping mapping)
  450.         {
  451.             if (mapping is SerializableMapping)
  452.                 return ((SerializableMapping)mapping).IsAny;
  453.             return mapping.TypeDesc.CanBeElementValue;
  454.         }
  455.     }
  456. }

Developer Fusion