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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Types.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.    
  19.     using System;
  20.     using System.IO;
  21.     using System.Reflection;
  22.     using System.Collections;
  23.     using System.Xml.Schema;
  24.     using System.Xml;
  25.     using System.Text;
  26.     using System.ComponentModel;
  27.     using System.CodeDom;
  28.     using System.CodeDom.Compiler;
  29.     using System.Xml.Serialization.Advanced;
  30.     using System.Globalization;
  31.     using System.Security.Cryptography;
  32.    
  33.     // These classes provide a higher level view on reflection specific to
  34.     // Xml serialization, for example:
  35.     // - allowing one to talk about types w/o having them compiled yet
  36.     // - abstracting collections & arrays
  37.     // - abstracting classes, structs, interfaces
  38.     // - knowing about XSD primitives
  39.     // - dealing with Serializable and xmlelement
  40.     // and lots of other little details
  41.    
  42.     internal enum TypeKind
  43.     {
  44.         Root,
  45.         Primitive,
  46.         Enum,
  47.         Struct,
  48.         Class,
  49.         Array,
  50.         Collection,
  51.         Enumerable,
  52.         Void,
  53.         Node,
  54.         Attribute,
  55.         Serializable
  56.     }
  57.    
  58.     internal enum TypeFlags
  59.     {
  60.         None = 0,
  61.         Abstract = 1,
  62.         Reference = 2,
  63.         Special = 4,
  64.         CanBeAttributeValue = 8,
  65.         CanBeTextValue = 16,
  66.         CanBeElementValue = 32,
  67.         HasCustomFormatter = 64,
  68.         AmbiguousDataType = 128,
  69.         IgnoreDefault = 512,
  70.         HasIsEmpty = 1024,
  71.         HasDefaultConstructor = 2048,
  72.         XmlEncodingNotRequired = 4096,
  73.         UseReflection = 16384,
  74.         CollapseWhitespace = 32768,
  75.         OptionalValue = 65536,
  76.         CtorInaccessible = 131072,
  77.         UsePrivateImplementation = 262144,
  78.         GenericInterface = 524288,
  79.         Unsupported = 1048576
  80.     }
  81.    
  82.     internal class TypeDesc
  83.     {
  84.         string name;
  85.         string fullName;
  86.         string cSharpName;
  87.         TypeDesc arrayElementTypeDesc;
  88.         TypeDesc arrayTypeDesc;
  89.         TypeKind kind;
  90.         XmlSchemaType dataType;
  91.         Type type;
  92.         TypeDesc baseTypeDesc;
  93.         TypeFlags flags;
  94.         string formatterName;
  95.         bool isXsdType;
  96.         bool isMixed;
  97.         MappedTypeDesc extendedType;
  98.         int weight;
  99.         Exception exception;
  100.        
  101.         internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, string formatterName)
  102.         {
  103.             this.name = name.Replace('+', '.');
  104.             this.fullName = fullName.Replace('+', '.');
  105.             this.kind = kind;
  106.             this.baseTypeDesc = baseTypeDesc;
  107.             this.flags = flags;
  108.             this.isXsdType = kind == TypeKind.Primitive;
  109.             if (this.isXsdType)
  110.                 this.weight = 1;
  111.             else if (kind == TypeKind.Enum)
  112.                 this.weight = 2;
  113.             else
  114.                 this.weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1;
  115.             this.dataType = dataType;
  116.             this.formatterName = formatterName;
  117.         }
  118.        
  119.         internal TypeDesc(string name, string fullName, XmlSchemaType dataType, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, dataType, kind, baseTypeDesc, flags, null)
  120.         {
  121.         }
  122.        
  123.         internal TypeDesc(string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags) : this(name, fullName, (XmlSchemaType)null, kind, baseTypeDesc, flags, null)
  124.         {
  125.         }
  126.        
  127.         internal TypeDesc(Type type, bool isXsdType, XmlSchemaType dataType, string formatterName, TypeFlags flags) : this(type.Name, type.FullName, dataType, TypeKind.Primitive, (TypeDesc)null, flags, formatterName)
  128.         {
  129.             this.isXsdType = isXsdType;
  130.             this.type = type;
  131.         }
  132.         internal TypeDesc(Type type, string name, string fullName, TypeKind kind, TypeDesc baseTypeDesc, TypeFlags flags, TypeDesc arrayElementTypeDesc) : this(name, fullName, null, kind, baseTypeDesc, flags, null)
  133.         {
  134.            
  135.             this.arrayElementTypeDesc = arrayElementTypeDesc;
  136.             this.type = type;
  137.         }
  138.        
  139.         public override string ToString()
  140.         {
  141.             return fullName;
  142.         }
  143.        
  144.         internal TypeFlags Flags {
  145.             get { return flags; }
  146.         }
  147.        
  148.         internal bool IsXsdType {
  149.             get { return isXsdType; }
  150.         }
  151.        
  152.         internal bool IsMappedType {
  153.             get { return extendedType != null; }
  154.         }
  155.        
  156.         internal MappedTypeDesc ExtendedType {
  157.             get { return extendedType; }
  158.         }
  159.        
  160.         internal string Name {
  161.             get { return name; }
  162.         }
  163.        
  164.         internal string FullName {
  165.             get { return fullName; }
  166.         }
  167.        
  168.         internal string CSharpName {
  169.             get {
  170.                 if (cSharpName == null) {
  171.                     cSharpName = type == null ? CodeIdentifier.GetCSharpName(fullName) : CodeIdentifier.GetCSharpName(type);
  172.                 }
  173.                 return cSharpName;
  174.             }
  175.         }
  176.        
  177.         internal XmlSchemaType DataType {
  178.             get { return dataType; }
  179.         }
  180.        
  181.         internal Type Type {
  182.             get { return type; }
  183.         }
  184.        
  185.         internal string FormatterName {
  186.             get { return formatterName; }
  187.         }
  188.        
  189.         internal TypeKind Kind {
  190.             get { return kind; }
  191.         }
  192.        
  193.         internal bool IsValueType {
  194.             get { return (flags & TypeFlags.Reference) == 0; }
  195.         }
  196.        
  197.         internal bool CanBeAttributeValue {
  198.             get { return (flags & TypeFlags.CanBeAttributeValue) != 0; }
  199.         }
  200.        
  201.         internal bool XmlEncodingNotRequired {
  202.             get { return (flags & TypeFlags.XmlEncodingNotRequired) != 0; }
  203.         }
  204.        
  205.         internal bool CanBeElementValue {
  206.             get { return (flags & TypeFlags.CanBeElementValue) != 0; }
  207.         }
  208.        
  209.         internal bool CanBeTextValue {
  210.             get { return (flags & TypeFlags.CanBeTextValue) != 0; }
  211.         }
  212.        
  213.         internal bool IsMixed {
  214.             get { return isMixed || CanBeTextValue; }
  215.             set { isMixed = value; }
  216.         }
  217.        
  218.         internal bool IsSpecial {
  219.             get { return (flags & TypeFlags.Special) != 0; }
  220.         }
  221.        
  222.         internal bool IsAmbiguousDataType {
  223.             get { return (flags & TypeFlags.AmbiguousDataType) != 0; }
  224.         }
  225.        
  226.         internal bool HasCustomFormatter {
  227.             get { return (flags & TypeFlags.HasCustomFormatter) != 0; }
  228.         }
  229.        
  230.         internal bool HasDefaultSupport {
  231.             get { return (flags & TypeFlags.IgnoreDefault) == 0; }
  232.         }
  233.        
  234.         internal bool HasIsEmpty {
  235.             get { return (flags & TypeFlags.HasIsEmpty) != 0; }
  236.         }
  237.        
  238.         internal bool CollapseWhitespace {
  239.             get { return (flags & TypeFlags.CollapseWhitespace) != 0; }
  240.         }
  241.        
  242.         internal bool HasDefaultConstructor {
  243.             get { return (flags & TypeFlags.HasDefaultConstructor) != 0; }
  244.         }
  245.        
  246.         internal bool IsUnsupported {
  247.             get { return (flags & TypeFlags.Unsupported) != 0; }
  248.         }
  249.        
  250.         internal bool IsGenericInterface {
  251.             get { return (flags & TypeFlags.GenericInterface) != 0; }
  252.         }
  253.        
  254.         internal bool IsPrivateImplementation {
  255.             get { return (flags & TypeFlags.UsePrivateImplementation) != 0; }
  256.         }
  257.        
  258.         internal bool CannotNew {
  259.             get { return !HasDefaultConstructor || ConstructorInaccessible; }
  260.         }
  261.        
  262.         internal bool IsAbstract {
  263.             get { return (flags & TypeFlags.Abstract) != 0; }
  264.         }
  265.        
  266.         internal bool IsOptionalValue {
  267.             get { return (flags & TypeFlags.OptionalValue) != 0; }
  268.         }
  269.        
  270.         internal bool UseReflection {
  271.             get { return (flags & TypeFlags.UseReflection) != 0; }
  272.         }
  273.        
  274.         internal bool IsVoid {
  275.             get { return kind == TypeKind.Void; }
  276.         }
  277.        
  278.         internal bool IsClass {
  279.             get { return kind == TypeKind.Class; }
  280.         }
  281.        
  282.         internal bool IsStructLike {
  283.             get { return kind == TypeKind.Struct || kind == TypeKind.Class; }
  284.         }
  285.        
  286.         internal bool IsArrayLike {
  287.             get { return kind == TypeKind.Array || kind == TypeKind.Collection || kind == TypeKind.Enumerable; }
  288.         }
  289.        
  290.         internal bool IsCollection {
  291.             get { return kind == TypeKind.Collection; }
  292.         }
  293.        
  294.         internal bool IsEnumerable {
  295.             get { return kind == TypeKind.Enumerable; }
  296.         }
  297.        
  298.         internal bool IsArray {
  299.             get { return kind == TypeKind.Array; }
  300.         }
  301.        
  302.         internal bool IsPrimitive {
  303.             get { return kind == TypeKind.Primitive; }
  304.         }
  305.        
  306.         internal bool IsEnum {
  307.             get { return kind == TypeKind.Enum; }
  308.         }
  309.        
  310.         internal bool IsNullable {
  311.             get { return !IsValueType; }
  312.         }
  313.        
  314.         internal bool IsRoot {
  315.             get { return kind == TypeKind.Root; }
  316.         }
  317.        
  318.         internal bool ConstructorInaccessible {
  319.             get { return (flags & TypeFlags.CtorInaccessible) != 0; }
  320.         }
  321.        
  322.         internal Exception Exception {
  323.             get { return exception; }
  324.             set { exception = value; }
  325.         }
  326.        
  327.         internal void CheckSupported()
  328.         {
  329.             if (IsUnsupported) {
  330.                 if (Exception != null) {
  331.                     throw Exception;
  332.                 }
  333.                 else {
  334.                     throw new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, FullName));
  335.                 }
  336.             }
  337.             if (baseTypeDesc != null)
  338.                 baseTypeDesc.CheckSupported();
  339.             if (arrayElementTypeDesc != null)
  340.                 arrayElementTypeDesc.CheckSupported();
  341.         }
  342.        
  343.         internal void CheckNeedConstructor()
  344.         {
  345.             if (!IsValueType && !IsAbstract && !HasDefaultConstructor) {
  346.                 flags |= TypeFlags.Unsupported;
  347.                 this.exception = new InvalidOperationException(Res.GetString(Res.XmlConstructorInaccessible, FullName));
  348.             }
  349.         }
  350.        
  351.         internal string ArrayLengthName {
  352.             get { return kind == TypeKind.Array ? "Length" : "Count"; }
  353.         }
  354.        
  355.         internal TypeDesc ArrayElementTypeDesc {
  356.             get { return arrayElementTypeDesc; }
  357.             set { arrayElementTypeDesc = value; }
  358.         }
  359.        
  360.         internal int Weight {
  361.             get { return weight; }
  362.         }
  363.        
  364.         internal TypeDesc CreateArrayTypeDesc()
  365.         {
  366.             if (arrayTypeDesc == null)
  367.                 arrayTypeDesc = new TypeDesc(null, name + "[]", fullName + "[]", TypeKind.Array, null, TypeFlags.Reference | (flags & TypeFlags.UseReflection), this);
  368.             return arrayTypeDesc;
  369.         }
  370.        
  371.         internal TypeDesc CreateMappedTypeDesc(MappedTypeDesc extension)
  372.         {
  373.             TypeDesc newTypeDesc = new TypeDesc(extension.Name, extension.Name, null, this.kind, this.baseTypeDesc, this.flags, null);
  374.             newTypeDesc.isXsdType = this.isXsdType;
  375.             newTypeDesc.isMixed = this.isMixed;
  376.             newTypeDesc.extendedType = extension;
  377.             newTypeDesc.dataType = this.dataType;
  378.             return newTypeDesc;
  379.         }
  380.        
  381.         internal TypeDesc BaseTypeDesc {
  382.             get { return baseTypeDesc; }
  383.             set {
  384.                 baseTypeDesc = value;
  385.                 weight = baseTypeDesc == null ? 0 : baseTypeDesc.Weight + 1;
  386.             }
  387.         }
  388.        
  389.         internal bool IsDerivedFrom(TypeDesc baseTypeDesc)
  390.         {
  391.             TypeDesc typeDesc = this;
  392.             while (typeDesc != null) {
  393.                 if (typeDesc == baseTypeDesc)
  394.                     return true;
  395.                 typeDesc = typeDesc.BaseTypeDesc;
  396.             }
  397.             return baseTypeDesc.IsRoot;
  398.         }
  399.        
  400.         static internal TypeDesc FindCommonBaseTypeDesc(TypeDesc[] typeDescs)
  401.         {
  402.             if (typeDescs.Length == 0)
  403.                 return null;
  404.             TypeDesc leastDerivedTypeDesc = null;
  405.             int leastDerivedLevel = int.MaxValue;
  406.            
  407.             for (int i = 0; i < typeDescs.Length; i++) {
  408.                 int derivationLevel = typeDescs[i].Weight;
  409.                 if (derivationLevel < leastDerivedLevel) {
  410.                     leastDerivedLevel = derivationLevel;
  411.                     leastDerivedTypeDesc = typeDescs[i];
  412.                 }
  413.             }
  414.             while (leastDerivedTypeDesc != null) {
  415.                 int i;
  416.                 for (i = 0; i < typeDescs.Length; i++) {
  417.                     if (!typeDescs[i].IsDerivedFrom(leastDerivedTypeDesc))
  418.                         break;
  419.                 }
  420.                 if (i == typeDescs.Length)
  421.                     break;
  422.                 leastDerivedTypeDesc = leastDerivedTypeDesc.BaseTypeDesc;
  423.             }
  424.             return leastDerivedTypeDesc;
  425.         }
  426.     }
  427.    
  428.     internal class TypeScope
  429.     {
  430.         Hashtable typeDescs = new Hashtable();
  431.         Hashtable arrayTypeDescs = new Hashtable();
  432.         ArrayList typeMappings = new ArrayList();
  433.        
  434.         static Hashtable primitiveTypes = new Hashtable();
  435.         static Hashtable primitiveDataTypes = new Hashtable();
  436.         static NameTable primitiveNames = new NameTable();
  437.        
  438.         static string[] unsupportedTypes = new string[] {"anyURI", "duration", "ENTITY", "ENTITIES", "gDay", "gMonth", "gMonthDay", "gYear", "gYearMonth", "ID",
  439.         "IDREF", "IDREFS", "integer", "language", "negativeInteger", "nonNegativeInteger", "nonPositiveInteger", "NOTATION", "positiveInteger", "token"
  440.             //"normalizedString",
  441.         };
  442.        
  443.         static TypeScope()
  444.         {
  445.             AddPrimitive(typeof(string), "string", "String", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor);
  446.             AddPrimitive(typeof(int), "int", "Int32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  447.             AddPrimitive(typeof(bool), "boolean", "Boolean", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  448.             AddPrimitive(typeof(short), "short", "Int16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  449.             AddPrimitive(typeof(long), "long", "Int64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  450.             AddPrimitive(typeof(float), "float", "Single", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  451.             AddPrimitive(typeof(double), "double", "Double", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  452.             AddPrimitive(typeof(decimal), "decimal", "Decimal", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  453.             AddPrimitive(typeof(DateTime), "dateTime", "DateTime", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  454.             AddPrimitive(typeof(XmlQualifiedName), "QName", "XmlQualifiedName", TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference);
  455.             AddPrimitive(typeof(byte), "unsignedByte", "Byte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  456.             AddPrimitive(typeof(sbyte), "byte", "SByte", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  457.             AddPrimitive(typeof(UInt16), "unsignedShort", "UInt16", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  458.             AddPrimitive(typeof(UInt32), "unsignedInt", "UInt32", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  459.             AddPrimitive(typeof(UInt64), "unsignedLong", "UInt64", TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  460.            
  461.             // Types without direct mapping (ambigous)
  462.             AddPrimitive(typeof(DateTime), "date", "Date", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  463.             AddPrimitive(typeof(DateTime), "time", "Time", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  464.            
  465.             AddPrimitive(typeof(string), "Name", "XmlName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  466.             AddPrimitive(typeof(string), "NCName", "XmlNCName", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  467.             AddPrimitive(typeof(string), "NMTOKEN", "XmlNmToken", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  468.             AddPrimitive(typeof(string), "NMTOKENS", "XmlNmTokens", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  469.            
  470.             AddPrimitive(typeof(byte[]), "base64Binary", "ByteArrayBase64", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor);
  471.             AddPrimitive(typeof(byte[]), "hexBinary", "ByteArrayHex", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired | TypeFlags.HasDefaultConstructor);
  472.             // NOTE, stefanph: byte[] can also be used to mean array of bytes. That datatype is not a primitive, so we
  473.             // can't use the AmbiguousDataType mechanism. To get an array of bytes in literal XML, apply [XmlArray] or
  474.             // [XmlArrayItem].
  475.            
  476.             XmlSchemaPatternFacet guidPattern = new XmlSchemaPatternFacet();
  477.             guidPattern.Value = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
  478.            
  479.             AddNonXsdPrimitive(typeof(Guid), "guid", UrtTypes.Namespace, "Guid", new XmlQualifiedName("string", XmlSchema.Namespace), new XmlSchemaFacet[] {guidPattern}, TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.IgnoreDefault);
  480.             AddNonXsdPrimitive(typeof(char), "char", UrtTypes.Namespace, "Char", new XmlQualifiedName("unsignedShort", XmlSchema.Namespace), new XmlSchemaFacet[0], TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.IgnoreDefault);
  481.            
  482.             AddSoapEncodedTypes(Soap.Encoding);
  483.            
  484.             // Unsuppoted types that we map to string, if in the future we decide
  485.             // to add support for them we would need to create custom formatters for them
  486.             // normalizedString is the only one unsuported type that suppose to preserve whitesapce
  487.             AddPrimitive(typeof(string), "normalizedString", "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor);
  488.             for (int i = 0; i < unsupportedTypes.Length; i++) {
  489.                 AddPrimitive(typeof(string), unsupportedTypes[i], "String", TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace);
  490.             }
  491.         }
  492.        
  493.         static internal bool IsKnownType(Type type)
  494.         {
  495.             if (type == typeof(object))
  496.                 return true;
  497.             if (type.IsEnum)
  498.                 return false;
  499.             switch (Type.GetTypeCode(type)) {
  500.                 case TypeCode.String:
  501.                     return true;
  502.                 case TypeCode.Int32:
  503.                     return true;
  504.                 case TypeCode.Boolean:
  505.                     return true;
  506.                 case TypeCode.Int16:
  507.                     return true;
  508.                 case TypeCode.Int64:
  509.                     return true;
  510.                 case TypeCode.Single:
  511.                     return true;
  512.                 case TypeCode.Double:
  513.                     return true;
  514.                 case TypeCode.Decimal:
  515.                     return true;
  516.                 case TypeCode.DateTime:
  517.                     return true;
  518.                 case TypeCode.Byte:
  519.                     return true;
  520.                 case TypeCode.SByte:
  521.                     return true;
  522.                 case TypeCode.UInt16:
  523.                     return true;
  524.                 case TypeCode.UInt32:
  525.                     return true;
  526.                 case TypeCode.UInt64:
  527.                     return true;
  528.                 case TypeCode.Char:
  529.                     return true;
  530.                 default:
  531.                     if (type == typeof(XmlQualifiedName))
  532.                         return true;
  533.                     else if (type == typeof(byte[]))
  534.                         return true;
  535.                     else if (type == typeof(Guid))
  536.                         return true;
  537.                     else if (type == typeof(XmlNode[])) {
  538.                         return true;
  539.                     }
  540.                     break;
  541.             }
  542.             return false;
  543.         }
  544.        
  545.         static void AddSoapEncodedTypes(string ns)
  546.         {
  547.             AddSoapEncodedPrimitive(typeof(string), "normalizedString", ns, "String", new XmlQualifiedName("normalizedString", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.HasDefaultConstructor);
  548.             for (int i = 0; i < unsupportedTypes.Length; i++) {
  549.                 AddSoapEncodedPrimitive(typeof(string), unsupportedTypes[i], ns, "String", new XmlQualifiedName(unsupportedTypes[i], XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.Reference | TypeFlags.CollapseWhitespace);
  550.             }
  551.            
  552.             AddSoapEncodedPrimitive(typeof(string), "string", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.Reference);
  553.             AddSoapEncodedPrimitive(typeof(int), "int", ns, "Int32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  554.             AddSoapEncodedPrimitive(typeof(bool), "boolean", ns, "Boolean", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  555.             AddSoapEncodedPrimitive(typeof(short), "short", ns, "Int16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  556.             AddSoapEncodedPrimitive(typeof(long), "long", ns, "Int64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  557.             AddSoapEncodedPrimitive(typeof(float), "float", ns, "Single", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  558.             AddSoapEncodedPrimitive(typeof(double), "double", ns, "Double", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  559.             AddSoapEncodedPrimitive(typeof(decimal), "decimal", ns, "Decimal", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  560.             AddSoapEncodedPrimitive(typeof(DateTime), "dateTime", ns, "DateTime", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  561.             AddSoapEncodedPrimitive(typeof(XmlQualifiedName), "QName", ns, "XmlQualifiedName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.HasCustomFormatter | TypeFlags.HasIsEmpty | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired | TypeFlags.Reference);
  562.             AddSoapEncodedPrimitive(typeof(byte), "unsignedByte", ns, "Byte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  563.             AddSoapEncodedPrimitive(typeof(sbyte), "byte", ns, "SByte", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  564.             AddSoapEncodedPrimitive(typeof(UInt16), "unsignedShort", ns, "UInt16", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  565.             AddSoapEncodedPrimitive(typeof(UInt32), "unsignedInt", ns, "UInt32", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  566.             AddSoapEncodedPrimitive(typeof(UInt64), "unsignedLong", ns, "UInt64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.XmlEncodingNotRequired);
  567.            
  568.             // Types without direct mapping (ambigous)
  569.             AddSoapEncodedPrimitive(typeof(DateTime), "date", ns, "Date", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  570.             AddSoapEncodedPrimitive(typeof(DateTime), "time", ns, "Time", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.XmlEncodingNotRequired);
  571.            
  572.             AddSoapEncodedPrimitive(typeof(string), "Name", ns, "XmlName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  573.             AddSoapEncodedPrimitive(typeof(string), "NCName", ns, "XmlNCName", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  574.             AddSoapEncodedPrimitive(typeof(string), "NMTOKEN", ns, "XmlNmToken", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  575.             AddSoapEncodedPrimitive(typeof(string), "NMTOKENS", ns, "XmlNmTokens", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference);
  576.            
  577.             AddSoapEncodedPrimitive(typeof(byte[]), "base64Binary", ns, "ByteArrayBase64", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired);
  578.             AddSoapEncodedPrimitive(typeof(byte[]), "hexBinary", ns, "ByteArrayHex", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.AmbiguousDataType | TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.HasCustomFormatter | TypeFlags.Reference | TypeFlags.IgnoreDefault | TypeFlags.XmlEncodingNotRequired);
  579.            
  580.             AddSoapEncodedPrimitive(typeof(string), "arrayCoordinate", ns, "String", new XmlQualifiedName("string", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue);
  581.             AddSoapEncodedPrimitive(typeof(byte[]), "base64", ns, "ByteArrayBase64", new XmlQualifiedName("base64Binary", XmlSchema.Namespace), TypeFlags.CanBeAttributeValue | TypeFlags.CanBeElementValue | TypeFlags.IgnoreDefault | TypeFlags.Reference);
  582.         }
  583.        
  584.         static void AddPrimitive(Type type, string dataTypeName, string formatterName, TypeFlags flags)
  585.         {
  586.             XmlSchemaSimpleType dataType = new XmlSchemaSimpleType();
  587.             dataType.Name = dataTypeName;
  588.             TypeDesc typeDesc = new TypeDesc(type, true, dataType, formatterName, flags);
  589.             if (primitiveTypes[type] == null)
  590.                 primitiveTypes.Add(type, typeDesc);
  591.             primitiveDataTypes.Add(dataType, typeDesc);
  592.             primitiveNames.Add(dataTypeName, XmlSchema.Namespace, typeDesc);
  593.         }
  594.        
  595.         static void AddNonXsdPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, XmlSchemaFacet[] facets, TypeFlags flags)
  596.         {
  597.             XmlSchemaSimpleType dataType = new XmlSchemaSimpleType();
  598.             dataType.Name = dataTypeName;
  599.             XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
  600.             restriction.BaseTypeName = baseTypeName;
  601.             foreach (XmlSchemaFacet facet in facets) {
  602.                 restriction.Facets.Add(facet);
  603.             }
  604.             dataType.Content = restriction;
  605.             TypeDesc typeDesc = new TypeDesc(type, false, dataType, formatterName, flags);
  606.             if (primitiveTypes[type] == null)
  607.                 primitiveTypes.Add(type, typeDesc);
  608.             primitiveDataTypes.Add(dataType, typeDesc);
  609.             primitiveNames.Add(dataTypeName, ns, typeDesc);
  610.         }
  611.        
  612.         static void AddSoapEncodedPrimitive(Type type, string dataTypeName, string ns, string formatterName, XmlQualifiedName baseTypeName, TypeFlags flags)
  613.         {
  614.             AddNonXsdPrimitive(type, dataTypeName, ns, formatterName, baseTypeName, new XmlSchemaFacet[0], flags);
  615.         }
  616.        
  617.         internal TypeDesc GetTypeDesc(string name, string ns)
  618.         {
  619.             return GetTypeDesc(name, ns, TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue | TypeFlags.CanBeAttributeValue);
  620.         }
  621.        
  622.         internal TypeDesc GetTypeDesc(string name, string ns, TypeFlags flags)
  623.         {
  624.             TypeDesc typeDesc = (TypeDesc)primitiveNames[name, ns];
  625.             if (typeDesc != null) {
  626.                 if ((typeDesc.Flags & flags) != 0) {
  627.                     return typeDesc;
  628.                 }
  629.             }
  630.             return null;
  631.         }
  632.        
  633.         internal TypeDesc GetTypeDesc(XmlSchemaSimpleType dataType)
  634.         {
  635.             return (TypeDesc)primitiveDataTypes[dataType];
  636.         }
  637.        
  638.         internal TypeDesc GetTypeDesc(Type type)
  639.         {
  640.             return GetTypeDesc(type, null, true, true);
  641.         }
  642.        
  643.         internal TypeDesc GetTypeDesc(Type type, MemberInfo source)
  644.         {
  645.             return GetTypeDesc(type, source, true, true);
  646.         }
  647.        
  648.         internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference)
  649.         {
  650.             return GetTypeDesc(type, source, directReference, true);
  651.         }
  652.        
  653.         internal TypeDesc GetTypeDesc(Type type, MemberInfo source, bool directReference, bool throwOnError)
  654.         {
  655.             if (type.ContainsGenericParameters) {
  656.                 throw new InvalidOperationException(Res.GetString(Res.XmlUnsupportedOpenGenericType, type.ToString()));
  657.             }
  658.             TypeDesc typeDesc = (TypeDesc)primitiveTypes[type];
  659.             if (typeDesc == null) {
  660.                 typeDesc = (TypeDesc)typeDescs[type];
  661.                 if (typeDesc == null) {
  662.                     typeDesc = ImportTypeDesc(type, source, directReference);
  663.                 }
  664.             }
  665.             if (throwOnError)
  666.                 typeDesc.CheckSupported();
  667.             return typeDesc;
  668.         }
  669.        
  670.         internal TypeDesc GetArrayTypeDesc(Type type)
  671.         {
  672.             TypeDesc typeDesc = (TypeDesc)arrayTypeDescs[type];
  673.             if (typeDesc == null) {
  674.                 typeDesc = GetTypeDesc(type);
  675.                 if (!typeDesc.IsArrayLike)
  676.                     typeDesc = ImportTypeDesc(type, null, false);
  677.                 typeDesc.CheckSupported();
  678.                 arrayTypeDescs.Add(type, typeDesc);
  679.             }
  680.             return typeDesc;
  681.         }
  682.        
  683.         internal TypeMapping GetTypeMappingFromTypeDesc(TypeDesc typeDesc)
  684.         {
  685.             foreach (TypeMapping typeMapping in TypeMappings) {
  686.                 if (typeMapping.TypeDesc == typeDesc)
  687.                     return typeMapping;
  688.             }
  689.             return null;
  690.         }
  691.        
  692.         internal Type GetTypeFromTypeDesc(TypeDesc typeDesc)
  693.         {
  694.             if (typeDesc.Type != null)
  695.                 return typeDesc.Type;
  696.             foreach (DictionaryEntry de in typeDescs) {
  697.                 if (de.Value == typeDesc)
  698.                     return de.Key as Type;
  699.             }
  700.             return null;
  701.         }
  702.        
  703.         TypeDesc ImportTypeDesc(Type type, MemberInfo memberInfo, bool directReference)
  704.         {
  705.             TypeDesc typeDesc = null;
  706.             TypeKind kind;
  707.             Type arrayElementType = null;
  708.             Type baseType = null;
  709.             TypeFlags flags = 0;
  710.             Exception exception = null;
  711.            
  712.             if (!type.IsPublic && !type.IsNestedPublic) {
  713.                 flags |= TypeFlags.Unsupported;
  714.                 exception = new InvalidOperationException(Res.GetString(Res.XmlTypeInaccessible, type.FullName));
  715.             }
  716.             else if (type.IsAbstract && type.IsSealed) {
  717.                 flags |= TypeFlags.Unsupported;
  718.                 exception = new InvalidOperationException(Res.GetString(Res.XmlTypeStatic, type.FullName));
  719.             }
  720.            
  721.             if (DynamicAssemblies.IsTypeDynamic(type)) {
  722.                 flags |= TypeFlags.UseReflection;
  723.             }
  724.             if (!type.IsValueType)
  725.                 flags |= TypeFlags.Reference;
  726.            
  727.             if (type == typeof(object)) {
  728.                 kind = TypeKind.Root;
  729.                 flags |= TypeFlags.HasDefaultConstructor;
  730.             }
  731.             else if (type == typeof(ValueType)) {
  732.                 kind = TypeKind.Enum;
  733.                 flags |= TypeFlags.Unsupported;
  734.                 if (exception == null) {
  735.                     exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName));
  736.                 }
  737.             }
  738.             else if (type == typeof(void)) {
  739.                 kind = TypeKind.Void;
  740.             }
  741.             else if (typeof(IXmlSerializable).IsAssignableFrom(type)) {
  742.                 kind = TypeKind.Serializable;
  743.                 flags |= TypeFlags.Special | TypeFlags.CanBeElementValue;
  744.                 flags |= GetConstructorFlags(type, ref exception);
  745.             }
  746.             else if (type.IsArray) {
  747.                 kind = TypeKind.Array;
  748.                 if (type.GetArrayRank() > 1) {
  749.                     flags |= TypeFlags.Unsupported;
  750.                     if (exception == null) {
  751.                         exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedRank, type.FullName));
  752.                     }
  753.                 }
  754.                 arrayElementType = type.GetElementType();
  755.                 flags |= TypeFlags.HasDefaultConstructor;
  756.             }
  757.             else if (typeof(ICollection).IsAssignableFrom(type)) {
  758.                 kind = TypeKind.Collection;
  759.                 arrayElementType = GetCollectionElementType(type, memberInfo == null ? null : memberInfo.DeclaringType.FullName + "." + memberInfo.Name);
  760.                 flags |= GetConstructorFlags(type, ref exception);
  761.             }
  762.             else if (type == typeof(XmlQualifiedName)) {
  763.                 kind = TypeKind.Primitive;
  764.             }
  765.             else if (type.IsPrimitive) {
  766.                 kind = TypeKind.Primitive;
  767.                 flags |= TypeFlags.Unsupported;
  768.                 if (exception == null) {
  769.                     exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName));
  770.                 }
  771.             }
  772.             else if (type.IsEnum) {
  773.                 kind = TypeKind.Enum;
  774.             }
  775.             else if (type.IsValueType) {
  776.                 kind = TypeKind.Struct;
  777.                 if (IsOptionalValue(type)) {
  778.                     baseType = type.GetGenericArguments()[0];
  779.                     flags |= TypeFlags.OptionalValue;
  780.                 }
  781.                 else {
  782.                     baseType = type.BaseType;
  783.                 }
  784.                 if (type.IsAbstract)
  785.                     flags |= TypeFlags.Abstract;
  786.             }
  787.             else if (type.IsClass) {
  788.                 if (type == typeof(XmlAttribute)) {
  789.                     kind = TypeKind.Attribute;
  790.                     flags |= TypeFlags.Special | TypeFlags.CanBeAttributeValue;
  791.                 }
  792.                 else if (typeof(XmlNode).IsAssignableFrom(type)) {
  793.                     kind = TypeKind.Node;
  794.                     baseType = type.BaseType;
  795.                     flags |= TypeFlags.Special | TypeFlags.CanBeElementValue | TypeFlags.CanBeTextValue;
  796.                     if (typeof(XmlText).IsAssignableFrom(type))
  797.                         flags &= ~TypeFlags.CanBeElementValue;
  798.                     else if (typeof(XmlElement).IsAssignableFrom(type))
  799.                         flags &= ~TypeFlags.CanBeTextValue;
  800.                     else if (type.IsAssignableFrom(typeof(XmlAttribute)))
  801.                         flags |= TypeFlags.CanBeAttributeValue;
  802.                 }
  803.                 else {
  804.                     kind = TypeKind.Class;
  805.                     baseType = type.BaseType;
  806.                     if (type.IsAbstract)
  807.                         flags |= TypeFlags.Abstract;
  808.                 }
  809.             }
  810.             else if (type.IsInterface) {
  811.                 kind = TypeKind.Void;
  812.                 flags |= TypeFlags.Unsupported;
  813.                 if (exception == null) {
  814.                     if (memberInfo == null) {
  815.                         exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterface, type.FullName));
  816.                     }
  817.                     else {
  818.                         exception = new NotSupportedException(Res.GetString(Res.XmlUnsupportedInterfaceDetails, memberInfo.DeclaringType.FullName + "." + memberInfo.Name, type.FullName));
  819.                     }
  820.                 }
  821.             }
  822.             else {
  823.                 kind = TypeKind.Void;
  824.                 flags |= TypeFlags.Unsupported;
  825.                 if (exception == null) {
  826.                     exception = new NotSupportedException(Res.GetString(Res.XmlSerializerUnsupportedType, type.FullName));
  827.                 }
  828.             }
  829.            
  830.             // check to see if the type has public default constructor for classes
  831.             if (kind == TypeKind.Class && !type.IsAbstract) {
  832.                 flags |= GetConstructorFlags(type, ref exception);
  833.             }
  834.             // check if a struct-like type is enumerable
  835.             if (kind == TypeKind.Struct || kind == TypeKind.Class) {
  836.                 if (typeof(IEnumerable).IsAssignableFrom(type)) {
  837.                     arrayElementType = GetEnumeratorElementType(type, ref flags);
  838.                     kind = TypeKind.Enumerable;
  839.                    
  840.                     // GetEnumeratorElementType checks for the security attributes on the GetEnumerator(), Add() methods and Current property,
  841.                     // we need to check the MoveNext() and ctor methods for the security attribues
  842.                     flags |= GetConstructorFlags(type, ref exception);
  843.                 }
  844.             }
  845.             typeDesc = new TypeDesc(type, CodeIdentifier.MakeValid(TypeName(type)), type.ToString(), kind, null, flags, null);
  846.             typeDesc.Exception = exception;
  847.            
  848.             if (directReference && (typeDesc.IsClass || kind == TypeKind.Serializable))
  849.                 typeDesc.CheckNeedConstructor();
  850.            
  851.             if (typeDesc.IsUnsupported) {
  852.                 // return right away, do not check anything else
  853.                 return typeDesc;
  854.             }
  855.             typeDescs.Add(type, typeDesc);
  856.            
  857.             if (arrayElementType != null) {
  858.                 TypeDesc td = GetTypeDesc(arrayElementType, memberInfo, true, false);
  859.                 // explicitly disallow read-only elements, even if they are collections
  860.                 if (directReference && (td.IsCollection || td.IsEnumerable) && !td.IsPrimitive) {
  861.                     td.CheckNeedConstructor();
  862.                 }
  863.                 typeDesc.ArrayElementTypeDesc = td;
  864.             }
  865.             if (baseType != null && baseType != typeof(object) && baseType != typeof(ValueType)) {
  866.                 typeDesc.BaseTypeDesc = GetTypeDesc(baseType, memberInfo, false, false);
  867.             }
  868.             if (type.IsNestedPublic) {
  869.                 for (Type t = type.DeclaringType; t != null && !t.ContainsGenericParameters; t = t.DeclaringType)
  870.                     GetTypeDesc(t, null, false);
  871.             }
  872.             return typeDesc;
  873.         }
  874.        
  875.         static internal bool IsOptionalValue(Type type)
  876.         {
  877.             if (type.IsGenericType) {
  878.                 if (type.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())
  879.                     return true;
  880.             }
  881.             return false;
  882.         }
  883. /*
  884.         static string GetHash(string str) {
  885.             MD5 md5 = MD5.Create();
  886.             string hash = Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(str)), 0, 6).Replace("+", "_P").Replace("/", "_S");
  887.             return hash;
  888.         }
  889.         */       
  890.        
  891.         static internal string TypeName(Type t)
  892.         {
  893.             if (t.IsArray) {
  894.                 return "ArrayOf" + TypeName(t.GetElementType());
  895.             }
  896.             else if (t.IsGenericType) {
  897.                 StringBuilder typeName = new StringBuilder();
  898.                 StringBuilder ns = new StringBuilder();
  899.                 string name = t.Name;
  900.                 int arity = name.IndexOf("`", StringComparison.Ordinal);
  901.                 if (arity >= 0) {
  902.                     name = name.Substring(0, arity);
  903.                 }
  904.                 typeName.Append(name);
  905.                 typeName.Append("Of");
  906.                 Type[] arguments = t.GetGenericArguments();
  907.                 for (int i = 0; i < arguments.Length; i++) {
  908.                     typeName.Append(TypeName(arguments[i]));
  909.                     ns.Append(arguments[i].Namespace);
  910.                 }
  911.                 /*
  912.                 if (ns.Length > 0) {
  913.                     typeName.Append("_");
  914.                     typeName.Append(GetHash(ns.ToString()));
  915.                 }
  916.                 */               
  917. return typeName.ToString();
  918.             }
  919.             return t.Name;
  920.         }
  921.        
  922.         static internal Type GetArrayElementType(Type type, string memberInfo)
  923.         {
  924.             if (type.IsArray)
  925.                 return type.GetElementType();
  926.             else if (typeof(ICollection).IsAssignableFrom(type))
  927.                 return GetCollectionElementType(type, memberInfo);
  928.             else if (typeof(IEnumerable).IsAssignableFrom(type)) {
  929.                 TypeFlags flags = TypeFlags.None;
  930.                 return GetEnumeratorElementType(type, ref flags);
  931.             }
  932.             else
  933.                 return null;
  934.         }
  935.        
  936.         static internal MemberMapping[] GetAllMembers(StructMapping mapping)
  937.         {
  938.             if (mapping.BaseMapping == null)
  939.                 return mapping.Members;
  940.             ArrayList list = new ArrayList();
  941.             GetAllMembers(mapping, list);
  942.             return (MemberMapping[])list.ToArray(typeof(MemberMapping));
  943.         }
  944.        
  945.         static internal void GetAllMembers(StructMapping mapping, ArrayList list)
  946.         {
  947.             if (mapping.BaseMapping != null) {
  948.                 GetAllMembers(mapping.BaseMapping, list);
  949.             }
  950.             for (int i = 0; i < mapping.Members.Length; i++) {
  951.                 list.Add(mapping.Members[i]);
  952.             }
  953.         }
  954.        
  955.         static TypeFlags GetConstructorFlags(Type type, ref Exception exception)
  956.         {
  957.             ConstructorInfo ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null);
  958.             if (ctor != null) {
  959.                 TypeFlags flags = TypeFlags.HasDefaultConstructor;
  960.                 if (!ctor.IsPublic)
  961.                     flags |= TypeFlags.CtorInaccessible;
  962.                 else {
  963.                     object[] attrs = ctor.GetCustomAttributes(typeof(ObsoleteAttribute), false);
  964.                     if (attrs != null && attrs.Length > 0) {
  965.                         ObsoleteAttribute obsolete = (ObsoleteAttribute)attrs[0];
  966.                         if (obsolete.IsError) {
  967.                             flags |= TypeFlags.CtorInaccessible;
  968.                         }
  969.                     }
  970.                 }
  971.                 return flags;
  972.             }
  973.             return 0;
  974.         }
  975.        
  976.         static Type GetEnumeratorElementType(Type type, ref TypeFlags flags)
  977.         {
  978.             if (typeof(IEnumerable).IsAssignableFrom(type)) {
  979.                 MethodInfo enumerator = type.GetMethod("GetEnumerator", new Type[0]);
  980.                
  981.                 if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) {
  982.                     // try generic implementation
  983.                     enumerator = null;
  984.                     foreach (MemberInfo member in type.GetMember("System.Collections.Generic.IEnumerable<*", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)) {
  985.                         enumerator = member as MethodInfo;
  986.                         if (enumerator != null && typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) {
  987.                             // use the first one we find
  988.                             flags |= TypeFlags.GenericInterface;
  989.                             break;
  990.                         }
  991.                         else {
  992.                             enumerator = null;
  993.                         }
  994.                     }
  995.                     if (enumerator == null) {
  996.                         // and finally private interface implementation
  997.                         flags |= TypeFlags.UsePrivateImplementation;
  998.                         enumerator = type.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null);
  999.                     }
  1000.                 }
  1001.                 if (enumerator == null || !typeof(IEnumerator).IsAssignableFrom(enumerator.ReturnType)) {
  1002.                     return null;
  1003.                 }
  1004.                 XmlAttributes methodAttrs = new XmlAttributes(enumerator);
  1005.                 if (methodAttrs.XmlIgnore)
  1006.                     return null;
  1007.                
  1008.                 PropertyInfo p = enumerator.ReturnType.GetProperty("Current");
  1009.                 Type currentType = (p == null ? typeof(object) : p.PropertyType);
  1010.                
  1011.                 MethodInfo addMethod = type.GetMethod("Add", new Type[] {currentType});
  1012.                
  1013.                 if (addMethod == null && currentType != typeof(object)) {
  1014.                     currentType = typeof(object);
  1015.                     addMethod = type.GetMethod("Add", new Type[] {currentType});
  1016.                 }
  1017.                 if (addMethod == null) {
  1018.                     throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, currentType, "IEnumerable"));
  1019.                 }
  1020.                 return currentType;
  1021.             }
  1022.             else {
  1023.                 return null;
  1024.             }
  1025.         }
  1026.        
  1027.         static internal PropertyInfo GetDefaultIndexer(Type type, string memberInfo)
  1028.         {
  1029.             if (typeof(IDictionary).IsAssignableFrom(type)) {
  1030.                 if (memberInfo == null) {
  1031.                     throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionary, type.FullName));
  1032.                 }
  1033.                 else {
  1034.                     throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedIDictionaryDetails, memberInfo, type.FullName));
  1035.                 }
  1036.             }
  1037.            
  1038.             MemberInfo[] defaultMembers = type.GetDefaultMembers();
  1039.             PropertyInfo indexer = null;
  1040.             if (defaultMembers != null && defaultMembers.Length > 0) {
  1041.                 for (Type t = type; t != null; t = t.BaseType) {
  1042.                     for (int i = 0; i < defaultMembers.Length; i++) {
  1043.                         if (defaultMembers[i] is PropertyInfo) {
  1044.                             PropertyInfo defaultProp = (PropertyInfo)defaultMembers[i];
  1045.                             if (defaultProp.DeclaringType != t)
  1046.                                 continue;
  1047.                             if (!defaultProp.CanRead)
  1048.                                 continue;
  1049.                             MethodInfo getMethod = defaultProp.GetGetMethod();
  1050.                             ParameterInfo[] parameters = getMethod.GetParameters();
  1051.                             if (parameters.Length == 1 && parameters[0].ParameterType == typeof(int)) {
  1052.                                 indexer = defaultProp;
  1053.                                 break;
  1054.                             }
  1055.                         }
  1056.                     }
  1057.                     if (indexer != null)
  1058.                         break;
  1059.                 }
  1060.             }
  1061.             if (indexer == null) {
  1062.                 throw new InvalidOperationException(Res.GetString(Res.XmlNoDefaultAccessors, type.FullName));
  1063.             }
  1064.             MethodInfo addMethod = type.GetMethod("Add", new Type[] {indexer.PropertyType});
  1065.             if (addMethod == null) {
  1066.                 throw new InvalidOperationException(Res.GetString(Res.XmlNoAddMethod, type.FullName, indexer.PropertyType, "ICollection"));
  1067.             }
  1068.             return indexer;
  1069.         }
  1070.         static Type GetCollectionElementType(Type type, string memberInfo)
  1071.         {
  1072.             return GetDefaultIndexer(type, memberInfo).PropertyType;
  1073.         }
  1074.        
  1075.         static internal XmlQualifiedName ParseWsdlArrayType(string type, out string dims, XmlSchemaObject parent)
  1076.         {
  1077.             string ns;
  1078.             string name;
  1079.            
  1080.             int nsLen = type.LastIndexOf(':');
  1081.            
  1082.             if (nsLen <= 0) {
  1083.                 ns = "";
  1084.             }
  1085.             else {
  1086.                 ns = type.Substring(0, nsLen);
  1087.             }
  1088.             int nameLen = type.IndexOf('[', nsLen + 1);
  1089.            
  1090.             if (nameLen <= nsLen) {
  1091.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidArrayTypeSyntax, type));
  1092.             }
  1093.             name = type.Substring(nsLen + 1, nameLen - nsLen - 1);
  1094.             dims = type.Substring(nameLen);
  1095.            
  1096.             // parent is not null only in the case when we used XmlSchema.Read(),
  1097.             // in which case we need to fixup the wsdl:arayType attribute value
  1098.             while (parent != null) {
  1099.                 if (parent.Namespaces != null) {
  1100.                     string wsdlNs = (string)parent.Namespaces.Namespaces[ns];
  1101.                     if (wsdlNs != null) {
  1102.                         ns = wsdlNs;
  1103.                         break;
  1104.                     }
  1105.                 }
  1106.                 parent = parent.Parent;
  1107.             }
  1108.             return new XmlQualifiedName(name, ns);
  1109.         }
  1110.        
  1111.         internal ICollection Types {
  1112.             get { return this.typeDescs.Keys; }
  1113.         }
  1114.        
  1115.         internal void AddTypeMapping(TypeMapping typeMapping)
  1116.         {
  1117.             typeMappings.Add(typeMapping);
  1118.         }
  1119.        
  1120.         internal ICollection TypeMappings {
  1121.             get { return typeMappings; }
  1122.         }
  1123.         static internal Hashtable PrimtiveTypes {
  1124.             get { return primitiveTypes; }
  1125.         }
  1126.     }
  1127.    
  1128.     internal class Soap
  1129.     {
  1130.         private Soap()
  1131.         {
  1132.         }
  1133.         internal const string Encoding = "http://schemas.xmlsoap.org/soap/encoding/";
  1134.         internal const string UrType = "anyType";
  1135.         internal const string Array = "Array";
  1136.         internal const string ArrayType = "arrayType";
  1137.     }
  1138.    
  1139.     internal class Soap12
  1140.     {
  1141.         private Soap12()
  1142.         {
  1143.         }
  1144.         internal const string Encoding = "http://www.w3.org/2003/05/soap-encoding";
  1145.         internal const string RpcNamespace = "http://www.w3.org/2003/05/soap-rpc";
  1146.         internal const string RpcResult = "result";
  1147.     }
  1148.    
  1149.     internal class Wsdl
  1150.     {
  1151.         private Wsdl()
  1152.         {
  1153.         }
  1154.         internal const string Namespace = "http://schemas.xmlsoap.org/wsdl/";
  1155.         internal const string ArrayType = "arrayType";
  1156.     }
  1157.    
  1158.     internal class UrtTypes
  1159.     {
  1160.         private UrtTypes()
  1161.         {
  1162.         }
  1163.         internal const string Namespace = "http://microsoft.com/wsdl/types/";
  1164.     }
  1165. }

Developer Fusion