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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlReflectionImporter.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.Reflection;
  20.     using System;
  21.     using System.Xml.Schema;
  22.     using System.Collections;
  23.     using System.ComponentModel;
  24.     using System.Globalization;
  25.     using System.CodeDom.Compiler;
  26.     using System.Threading;
  27.    
  28.     /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter"]/*' />
  29.     ///<internalonly/>
  30.     /// <devdoc>
  31.     /// <para>[To be supplied.]</para>
  32.     /// </devdoc>
  33.     public class XmlReflectionImporter
  34.     {
  35.         TypeScope typeScope;
  36.         XmlAttributeOverrides attributeOverrides;
  37.         XmlAttributes defaultAttributes = new XmlAttributes();
  38.         NameTable types = new NameTable();
  39.         // xmltypename + xmlns -> Mapping
  40.         NameTable elements = new NameTable();
  41.         // xmlelementname + xmlns -> ElementAccessor
  42.         NameTable xsdAttributes;
  43.         // xmlattributetname + xmlns -> AttributeAccessor
  44.         Hashtable specials;
  45.         // type -> SpecialMapping
  46.         Hashtable anonymous = new Hashtable();
  47.         // type -> AnonymousMapping
  48.         NameTable serializables;
  49.         // type name --> new SerializableMapping
  50.         StructMapping root;
  51.         string defaultNs;
  52.         ModelScope modelScope;
  53.         int arrayNestingLevel;
  54.         XmlArrayItemAttributes savedArrayItemAttributes;
  55.         string savedArrayNamespace;
  56.         int choiceNum = 1;
  57.        
  58.         enum ImportContext
  59.         {
  60.             Text,
  61.             Attribute,
  62.             Element
  63.         }
  64.        
  65.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.XmlReflectionImporter"]/*' />
  66.         /// <devdoc>
  67.         /// <para>[To be supplied.]</para>
  68.         /// </devdoc>
  69.         public XmlReflectionImporter() : this(null, null)
  70.         {
  71.         }
  72.        
  73.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.XmlReflectionImporter1"]/*' />
  74.         /// <devdoc>
  75.         /// <para>[To be supplied.]</para>
  76.         /// </devdoc>
  77.         public XmlReflectionImporter(string defaultNamespace) : this(null, defaultNamespace)
  78.         {
  79.         }
  80.        
  81.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.XmlReflectionImporter2"]/*' />
  82.         /// <devdoc>
  83.         /// <para>[To be supplied.]</para>
  84.         /// </devdoc>
  85.         public XmlReflectionImporter(XmlAttributeOverrides attributeOverrides) : this(attributeOverrides, null)
  86.         {
  87.         }
  88.        
  89.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.XmlReflectionImporter3"]/*' />
  90.         /// <devdoc>
  91.         /// <para>[To be supplied.]</para>
  92.         /// </devdoc>
  93.         public XmlReflectionImporter(XmlAttributeOverrides attributeOverrides, string defaultNamespace)
  94.         {
  95.             if (defaultNamespace == null)
  96.                 defaultNamespace = String.Empty;
  97.             if (attributeOverrides == null)
  98.                 attributeOverrides = new XmlAttributeOverrides();
  99.             this.attributeOverrides = attributeOverrides;
  100.             this.defaultNs = defaultNamespace;
  101.             this.typeScope = new TypeScope();
  102.             this.modelScope = new ModelScope(this.typeScope);
  103.         }
  104.        
  105.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.IncludeTypes"]/*' />
  106.         /// <devdoc>
  107.         /// <para>[To be supplied.]</para>
  108.         /// </devdoc>
  109.         public void IncludeTypes(ICustomAttributeProvider provider)
  110.         {
  111.             object[] attrs = provider.GetCustomAttributes(typeof(XmlIncludeAttribute), false);
  112.             for (int i = 0; i < attrs.Length; i++) {
  113.                 Type type = ((XmlIncludeAttribute)attrs[i]).Type;
  114.                 IncludeType(type);
  115.             }
  116.         }
  117.        
  118.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.IncludeType"]/*' />
  119.         /// <devdoc>
  120.         /// <para>[To be supplied.]</para>
  121.         /// </devdoc>
  122.         public void IncludeType(Type type)
  123.         {
  124.             int previousNestingLevel = arrayNestingLevel;
  125.             XmlArrayItemAttributes previousArrayItemAttributes = savedArrayItemAttributes;
  126.             string previousArrayNamespace = savedArrayNamespace;
  127.             arrayNestingLevel = 0;
  128.             savedArrayItemAttributes = null;
  129.             savedArrayNamespace = null;
  130.            
  131.             TypeMapping mapping = ImportTypeMapping(modelScope.GetTypeModel(type), defaultNs, ImportContext.Element, string.Empty, null);
  132.             if (mapping.IsAnonymousType && !mapping.TypeDesc.IsSpecial) {
  133.                 //XmlAnonymousInclude=Cannot include anonymous type '{0}'.
  134.                 throw new InvalidOperationException(Res.GetString(Res.XmlAnonymousInclude, type.FullName));
  135.             }
  136.             arrayNestingLevel = previousNestingLevel;
  137.             savedArrayItemAttributes = previousArrayItemAttributes;
  138.             savedArrayNamespace = previousArrayNamespace;
  139.         }
  140.        
  141.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportTypeMapping"]/*' />
  142.         /// <devdoc>
  143.         /// <para>[To be supplied.]</para>
  144.         /// </devdoc>
  145.         public XmlTypeMapping ImportTypeMapping(Type type)
  146.         {
  147.             return ImportTypeMapping(type, null, null);
  148.         }
  149.        
  150.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportTypeMapping1"]/*' />
  151.         /// <devdoc>
  152.         /// <para>[To be supplied.]</para>
  153.         /// </devdoc>
  154.         public XmlTypeMapping ImportTypeMapping(Type type, string defaultNamespace)
  155.         {
  156.             return ImportTypeMapping(type, null, defaultNamespace);
  157.         }
  158.        
  159.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportTypeMapping2"]/*' />
  160.         /// <devdoc>
  161.         /// <para>[To be supplied.]</para>
  162.         /// </devdoc>
  163.         public XmlTypeMapping ImportTypeMapping(Type type, XmlRootAttribute root)
  164.         {
  165.             return ImportTypeMapping(type, root, null);
  166.         }
  167.        
  168.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportTypeMapping3"]/*' />
  169.         /// <devdoc>
  170.         /// <para>[To be supplied.]</para>
  171.         /// </devdoc>
  172.         public XmlTypeMapping ImportTypeMapping(Type type, XmlRootAttribute root, string defaultNamespace)
  173.         {
  174.             if (type == null)
  175.                 throw new ArgumentNullException("type");
  176.             XmlTypeMapping xmlMapping = new XmlTypeMapping(typeScope, ImportElement(modelScope.GetTypeModel(type), root, defaultNamespace));
  177.             xmlMapping.SetKeyInternal(XmlMapping.GenerateKey(type, root, defaultNamespace));
  178.             xmlMapping.GenerateSerializer = true;
  179.             return xmlMapping;
  180.         }
  181.        
  182.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportMembersMapping"]/*' />
  183.         /// <devdoc>
  184.         /// <para>[To be supplied.]</para>
  185.         /// </devdoc>
  186.         public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement)
  187.         {
  188.             return ImportMembersMapping(elementName, ns, members, hasWrapperElement, false);
  189.         }
  190.        
  191.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportMembersMapping1"]/*' />
  192.         /// <devdoc>
  193.         /// <para>[To be supplied.]</para>
  194.         /// </devdoc>
  195.         public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc)
  196.         {
  197.             return ImportMembersMapping(elementName, ns, members, hasWrapperElement, rpc, false);
  198.         }
  199.        
  200.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportMembersMapping2"]/*' />
  201.         /// <devdoc>
  202.         /// <para>[To be supplied.]</para>
  203.         /// </devdoc>
  204.         ///
  205.         public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, bool openModel)
  206.         {
  207.             return ImportMembersMapping(elementName, ns, members, hasWrapperElement, rpc, openModel, XmlMappingAccess.Read | XmlMappingAccess.Write);
  208.         }
  209.        
  210.         /// <include file='doc\XmlReflectionImporter.uex' path='docs/doc[@for="XmlReflectionImporter.ImportMembersMapping3"]/*' />
  211.         /// <devdoc>
  212.         /// <para>[To be supplied.]</para>
  213.         /// </devdoc>
  214.         ///
  215.         public XmlMembersMapping ImportMembersMapping(string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool rpc, bool openModel, XmlMappingAccess access)
  216.         {
  217.             ElementAccessor element = new ElementAccessor();
  218.             element.Name = elementName == null || elementName.Length == 0 ? elementName : XmlConvert.EncodeLocalName(elementName);
  219.             element.Namespace = ns;
  220.             MembersMapping membersMapping = ImportMembersMapping(members, ns, hasWrapperElement, rpc, openModel);
  221.             element.Mapping = membersMapping;
  222.             element.Form = XmlSchemaForm.Qualified;
  223.             // elements within soap:body are always qualified
  224.             if (!rpc) {
  225.                 if (hasWrapperElement)
  226.                     element = (ElementAccessor)ReconcileAccessor(element, this.elements);
  227.                 else {
  228.                     foreach (MemberMapping mapping in membersMapping.Members) {
  229.                         if (mapping.Elements != null && mapping.Elements.Length > 0) {
  230.                             mapping.Elements[0] = (ElementAccessor)ReconcileAccessor(mapping.Elements[0], this.elements);
  231.                         }
  232.                     }
  233.                 }
  234.             }
  235.             XmlMembersMapping xmlMapping = new XmlMembersMapping(typeScope, element, access);
  236.             xmlMapping.GenerateSerializer = true;
  237.             return xmlMapping;
  238.         }
  239.        
  240.         XmlAttributes GetAttributes(Type type, bool canBeSimpleType)
  241.         {
  242.             XmlAttributes attrs = attributeOverrides[type];
  243.             if (attrs != null)
  244.                 return attrs;
  245.             if (canBeSimpleType && TypeScope.IsKnownType(type)) {
  246.                 return defaultAttributes;
  247.             }
  248.             return new XmlAttributes(type);
  249.         }
  250.        
  251.         XmlAttributes GetAttributes(MemberInfo memberInfo)
  252.         {
  253.             XmlAttributes attrs = attributeOverrides[memberInfo.DeclaringType, memberInfo.Name];
  254.             if (attrs != null)
  255.                 return attrs;
  256.             return new XmlAttributes(memberInfo);
  257.         }
  258.        
  259.         ElementAccessor ImportElement(TypeModel model, XmlRootAttribute root, string defaultNamespace)
  260.         {
  261.             XmlAttributes a = GetAttributes(model.Type, true);
  262.            
  263.             if (root == null)
  264.                 root = a.XmlRoot;
  265.             string ns = root == null ? null : root.Namespace;
  266.             if (ns == null && a.XmlRoot == null && a.XmlType != null && a.XmlType.AnonymousType) {
  267.                 ns = a.XmlType.Namespace;
  268.             }
  269.             if (ns == null)
  270.                 ns = defaultNamespace;
  271.             if (ns == null)
  272.                 ns = this.defaultNs;
  273.            
  274.             arrayNestingLevel = -1;
  275.             savedArrayItemAttributes = null;
  276.             savedArrayNamespace = null;
  277.             ElementAccessor element = CreateElementAccessor(ImportTypeMapping(model, ns, ImportContext.Element, string.Empty, a), ns);
  278.            
  279.             if (root != null) {
  280.                 if (root.ElementName.Length > 0)
  281.                     element.Name = XmlConvert.EncodeLocalName(root.ElementName);
  282.                 if (root.IsNullableSpecified && !root.IsNullable && model.TypeDesc.IsOptionalValue)
  283.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, model.TypeDesc.BaseTypeDesc.FullName, "XmlRoot"));
  284.                 element.IsNullable = root.IsNullableSpecified ? root.IsNullable : model.TypeDesc.IsNullable || model.TypeDesc.IsOptionalValue;
  285.                 CheckNullable(element.IsNullable, model.TypeDesc, element.Mapping);
  286.             }
  287.             else
  288.                 element.IsNullable = model.TypeDesc.IsNullable || model.TypeDesc.IsOptionalValue;
  289.             element.Form = XmlSchemaForm.Qualified;
  290.             return (ElementAccessor)ReconcileAccessor(element, this.elements);
  291.         }
  292.        
  293.         static string GetMappingName(Mapping mapping)
  294.         {
  295.             if (mapping is MembersMapping)
  296.                 return "(method)";
  297.             else if (mapping is TypeMapping)
  298.                 return ((TypeMapping)mapping).TypeDesc.FullName;
  299.             else
  300.                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "mapping");
  301.         }
  302.        
  303.         ElementAccessor ReconcileLocalAccessor(ElementAccessor accessor, string ns)
  304.         {
  305.             if (accessor.Namespace == ns)
  306.                 return accessor;
  307.             return (ElementAccessor)ReconcileAccessor(accessor, this.elements);
  308.         }
  309.        
  310.         Accessor ReconcileAccessor(Accessor accessor, NameTable accessors)
  311.         {
  312.             if (accessor.Any && accessor.Name.Length == 0)
  313.                 return accessor;
  314.            
  315.             Accessor existing = (Accessor)accessors[accessor.Name, accessor.Namespace];
  316.             if (existing == null) {
  317.                 accessor.IsTopLevelInSchema = true;
  318.                 accessors.Add(accessor.Name, accessor.Namespace, accessor);
  319.                 return accessor;
  320.             }
  321.            
  322.             if (existing.Mapping == accessor.Mapping)
  323.                 return existing;
  324.            
  325.             if (!(accessor.Mapping is MembersMapping) && !(existing.Mapping is MembersMapping)) {
  326.                 if (accessor.Mapping.TypeDesc == existing.Mapping.TypeDesc || (existing.Mapping is NullableMapping && accessor.Mapping.TypeDesc == ((NullableMapping)existing.Mapping).BaseMapping.TypeDesc) || (accessor.Mapping is NullableMapping && ((NullableMapping)accessor.Mapping).BaseMapping.TypeDesc == existing.Mapping.TypeDesc)) {
  327.                     // need to compare default values
  328.                     string value1 = Convert.ToString(accessor.Default, CultureInfo.InvariantCulture);
  329.                     string value2 = Convert.ToString(existing.Default, CultureInfo.InvariantCulture);
  330.                     if (value1 == value2) {
  331.                         return existing;
  332.                     }
  333.                     throw new InvalidOperationException(Res.GetString(Res.XmlCannotReconcileAccessorDefault, accessor.Name, accessor.Namespace, value1, value2));
  334.                 }
  335.             }
  336.            
  337.             if (accessor.Mapping is MembersMapping || existing.Mapping is MembersMapping)
  338.                 throw new InvalidOperationException(Res.GetString(Res.XmlMethodTypeNameConflict, accessor.Name, accessor.Namespace));
  339.            
  340.             if (accessor.Mapping is ArrayMapping) {
  341.                 if (!(existing.Mapping is ArrayMapping)) {
  342.                     throw new InvalidOperationException(Res.GetString(Res.XmlCannotReconcileAccessor, accessor.Name, accessor.Namespace, GetMappingName(existing.Mapping), GetMappingName(accessor.Mapping)));
  343.                 }
  344.                 ArrayMapping mapping = (ArrayMapping)accessor.Mapping;
  345.                 ArrayMapping existingMapping = mapping.IsAnonymousType ? null : (ArrayMapping)types[existing.Mapping.TypeName, existing.Mapping.Namespace];
  346.                 ArrayMapping first = existingMapping;
  347.                 while (existingMapping != null) {
  348.                     if (existingMapping == accessor.Mapping)
  349.                         return existing;
  350.                     existingMapping = existingMapping.Next;
  351.                 }
  352.                 mapping.Next = first;
  353.                 if (!mapping.IsAnonymousType)
  354.                     types[existing.Mapping.TypeName, existing.Mapping.Namespace] = mapping;
  355.                 return existing;
  356.             }
  357.             if (accessor is AttributeAccessor)
  358.                 throw new InvalidOperationException(Res.GetString(Res.XmlCannotReconcileAttributeAccessor, accessor.Name, accessor.Namespace, GetMappingName(existing.Mapping), GetMappingName(accessor.Mapping)));
  359.             else
  360.                 throw new InvalidOperationException(Res.GetString(Res.XmlCannotReconcileAccessor, accessor.Name, accessor.Namespace, GetMappingName(existing.Mapping), GetMappingName(accessor.Mapping)));
  361.         }
  362.        
  363.         Exception CreateReflectionException(string context, Exception e)
  364.         {
  365.             return new InvalidOperationException(Res.GetString(Res.XmlReflectionError, context), e);
  366.         }
  367.        
  368.         Exception CreateTypeReflectionException(string context, Exception e)
  369.         {
  370.             return new InvalidOperationException(Res.GetString(Res.XmlTypeReflectionError, context), e);
  371.         }
  372.        
  373.         Exception CreateMemberReflectionException(FieldModel model, Exception e)
  374.         {
  375.             return new InvalidOperationException(Res.GetString(model.IsProperty ? Res.XmlPropertyReflectionError : Res.XmlFieldReflectionError, model.Name), e);
  376.         }
  377.        
  378.         TypeMapping ImportTypeMapping(TypeModel model, string ns, ImportContext context, string dataType, XmlAttributes a)
  379.         {
  380.             return ImportTypeMapping(model, ns, context, dataType, a, false, false);
  381.         }
  382.        
  383.         TypeMapping ImportTypeMapping(TypeModel model, string ns, ImportContext context, string dataType, XmlAttributes a, bool repeats, bool openModel)
  384.         {
  385.             try {
  386.                 if (dataType.Length > 0) {
  387.                     TypeDesc modelTypeDesc = TypeScope.IsOptionalValue(model.Type) ? model.TypeDesc.BaseTypeDesc : model.TypeDesc;
  388.                     if (!modelTypeDesc.IsPrimitive) {
  389.                         throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDataTypeUsage, dataType, "XmlElementAttribute.DataType"));
  390.                     }
  391.                     TypeDesc td = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace);
  392.                     if (td == null) {
  393.                         throw new InvalidOperationException(Res.GetString(Res.XmlInvalidXsdDataType, dataType, "XmlElementAttribute.DataType", new XmlQualifiedName(dataType, XmlSchema.Namespace).ToString()));
  394.                     }
  395.                     if (modelTypeDesc.FullName != td.FullName) {
  396.                         throw new InvalidOperationException(Res.GetString(Res.XmlDataTypeMismatch, dataType, "XmlElementAttribute.DataType", modelTypeDesc.FullName));
  397.                     }
  398.                 }
  399.                
  400.                 if (a == null)
  401.                     a = GetAttributes(model.Type, false);
  402.                
  403.                 if ((a.XmlFlags & ~(XmlAttributeFlags.Type | XmlAttributeFlags.Root)) != 0)
  404.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidTypeAttributes, model.Type.FullName));
  405.                
  406.                 switch (model.TypeDesc.Kind) {
  407.                     case TypeKind.Enum:
  408.                         return ImportEnumMapping((EnumModel)model, ns, repeats);
  409.                     case TypeKind.Primitive:
  410.                         if (a.XmlFlags != 0)
  411.                             throw InvalidAttributeUseException(model.Type);
  412.                         return ImportPrimitiveMapping((PrimitiveModel)model, context, dataType, repeats);
  413.                     case TypeKind.Array:
  414.                     case TypeKind.Collection:
  415.                     case TypeKind.Enumerable:
  416.                         //if (a.XmlFlags != 0) throw InvalidAttributeUseException(model.Type);
  417.                         if (context != ImportContext.Element)
  418.                             throw UnsupportedException(model.TypeDesc, context);
  419.                         arrayNestingLevel++;
  420.                         ArrayMapping arrayMapping = ImportArrayLikeMapping((ArrayModel)model, ns);
  421.                         arrayNestingLevel--;
  422.                         return arrayMapping;
  423.                     case TypeKind.Root:
  424.                     case TypeKind.Class:
  425.                     case TypeKind.Struct:
  426.                         if (context != ImportContext.Element)
  427.                             throw UnsupportedException(model.TypeDesc, context);
  428.                         if (model.TypeDesc.IsOptionalValue) {
  429.                             TypeMapping baseMapping = GetTypeMapping(model.TypeDesc.BaseTypeDesc.Name, ns, model.TypeDesc.BaseTypeDesc, types, null);
  430.                             if (baseMapping == null)
  431.                                 baseMapping = ImportTypeMapping(modelScope.GetTypeModel(model.TypeDesc.BaseTypeDesc.Type, true), ns, context, dataType, null, repeats, openModel);
  432.                             return CreateNullableMapping(baseMapping, model.TypeDesc);
  433.                         }
  434.                         else {
  435.                             return ImportStructLikeMapping((StructModel)model, ns, openModel, a);
  436.                         }
  437.                         break;
  438.                     default:
  439.                         if (model.TypeDesc.Kind == TypeKind.Serializable) {
  440.                             // We allow XmlRoot attribute on IXmlSerializable, but not others
  441.                             if ((a.XmlFlags & ~XmlAttributeFlags.Root) != 0) {
  442.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSerializableAttributes, model.TypeDesc.FullName, typeof(XmlSchemaProviderAttribute).Name));
  443.                             }
  444.                         }
  445.                         else {
  446.                             if (a.XmlFlags != 0)
  447.                                 throw InvalidAttributeUseException(model.Type);
  448.                         }
  449.                         if (model.TypeDesc.IsSpecial)
  450.                             return ImportSpecialMapping(model.Type, model.TypeDesc, ns, context);
  451.                         throw UnsupportedException(model.TypeDesc, context);
  452.                         break;
  453.                 }
  454.             }
  455.             catch (Exception e) {
  456.                 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  457.                     throw;
  458.                 }
  459.                 throw CreateTypeReflectionException(model.TypeDesc.FullName, e);
  460.             }
  461.             catch {
  462.                 throw CreateTypeReflectionException(model.TypeDesc.FullName, null);
  463.             }
  464.         }
  465.        
  466.         static internal MethodInfo GetMethodFromSchemaProvider(XmlSchemaProviderAttribute provider, Type type)
  467.         {
  468.             if (provider.IsAny) {
  469.                 // do not validate the schema provider method for wildcard types.
  470.                 return null;
  471.             }
  472.             else if (provider.MethodName == null) {
  473.                 throw new ArgumentNullException("MethodName");
  474.             }
  475.             if (!CodeGenerator.IsValidLanguageIndependentIdentifier(provider.MethodName))
  476.                 throw new ArgumentException(Res.GetString(Res.XmlGetSchemaMethodName, provider.MethodName), "MethodName");
  477.            
  478.                 /* BindingFlags.DeclaredOnly | */            MethodInfo getMethod = getMethod = type.GetMethod(provider.MethodName, BindingFlags.Static | BindingFlags.Public, null, new Type[] {typeof(XmlSchemaSet)}, null);
  479.             if (getMethod == null)
  480.                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaMethodMissing, provider.MethodName, typeof(XmlSchemaSet).Name, type.FullName));
  481.            
  482.             if (!(typeof(XmlQualifiedName).IsAssignableFrom(getMethod.ReturnType)) && !(typeof(XmlSchemaType).IsAssignableFrom(getMethod.ReturnType)))
  483.                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaMethodReturnType, type.Name, provider.MethodName, typeof(XmlSchemaProviderAttribute).Name, typeof(XmlQualifiedName).FullName, typeof(XmlSchemaType).FullName));
  484.            
  485.             return getMethod;
  486.         }
  487.        
  488.         SpecialMapping ImportSpecialMapping(Type type, TypeDesc typeDesc, string ns, ImportContext context)
  489.         {
  490.             if (specials == null)
  491.                 specials = new Hashtable();
  492.             SpecialMapping mapping = (SpecialMapping)specials[type];
  493.             if (mapping != null) {
  494.                 CheckContext(mapping.TypeDesc, context);
  495.                 return mapping;
  496.             }
  497.             if (typeDesc.Kind == TypeKind.Serializable) {
  498.                 SerializableMapping serializableMapping = null;
  499.                
  500.                 // get the schema method info
  501.                 object[] attrs = type.GetCustomAttributes(typeof(XmlSchemaProviderAttribute), false);
  502.                
  503.                 if (attrs.Length > 0) {
  504.                     // new IXmlSerializable
  505.                     XmlSchemaProviderAttribute provider = (XmlSchemaProviderAttribute)attrs[0];
  506.                     MethodInfo method = GetMethodFromSchemaProvider(provider, type);
  507.                     serializableMapping = new SerializableMapping(method, provider.IsAny, ns);
  508.                     XmlQualifiedName qname = serializableMapping.XsiType;
  509.                     if (qname != null && !qname.IsEmpty) {
  510.                         if (serializables == null)
  511.                             serializables = new NameTable();
  512.                         SerializableMapping existingMapping = (SerializableMapping)serializables[qname];
  513.                         if (existingMapping != null) {
  514.                             if (existingMapping.Type == null) {
  515.                                 serializableMapping = existingMapping;
  516.                             }
  517.                             else if (existingMapping.Type != type) {
  518.                                 SerializableMapping next = existingMapping.Next;
  519.                                 existingMapping.Next = serializableMapping;
  520.                                 serializableMapping.Next = next;
  521.                             }
  522.                         }
  523.                         else {
  524.                             XmlSchemaType xsdType = serializableMapping.XsdType;
  525.                             if (xsdType != null)
  526.                                 SetBase(serializableMapping, xsdType.DerivedFrom);
  527.                             serializables[qname] = serializableMapping;
  528.                         }
  529.                         serializableMapping.TypeName = qname.Name;
  530.                         serializableMapping.Namespace = qname.Namespace;
  531.                     }
  532.                     serializableMapping.TypeDesc = typeDesc;
  533.                     serializableMapping.Type = type;
  534.                     IncludeTypes(type);
  535.                 }
  536.                 else {
  537.                     // old IXmlSerializable
  538.                     serializableMapping = new SerializableMapping();
  539.                     serializableMapping.TypeDesc = typeDesc;
  540.                     serializableMapping.Type = type;
  541.                 }
  542.                 mapping = serializableMapping;
  543.             }
  544.             else {
  545.                 mapping = new SpecialMapping();
  546.                 mapping.TypeDesc = typeDesc;
  547.             }
  548.             CheckContext(typeDesc, context);
  549.             specials.Add(type, mapping);
  550.             typeScope.AddTypeMapping(mapping);
  551.             return mapping;
  552.         }
  553.        
  554.         static internal void ValidationCallbackWithErrorCode(object sender, ValidationEventArgs args)
  555.         {
  556.             if (args.Severity == XmlSeverityType.Error)
  557.                 throw new InvalidOperationException(Res.GetString(Res.XmlSerializableSchemaError, typeof(IXmlSerializable).Name, args.Message));
  558.         }
  559.        
  560.         internal void SetBase(SerializableMapping mapping, XmlQualifiedName baseQname)
  561.         {
  562.            
  563.             if (baseQname.IsEmpty)
  564.                 return;
  565.             if (baseQname.Namespace == XmlSchema.Namespace)
  566.                 return;
  567.             XmlSchemaSet schemas = mapping.Schemas;
  568.             ArrayList srcSchemas = (ArrayList)schemas.Schemas(baseQname.Namespace);
  569.            
  570.             if (srcSchemas.Count == 0) {
  571.                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingSchema, baseQname.Namespace));
  572.             }
  573.             if (srcSchemas.Count > 1) {
  574.                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaInclude, baseQname.Namespace, typeof(IXmlSerializable).Name, "GetSchema"));
  575.             }
  576.             XmlSchema s = (XmlSchema)srcSchemas[0];
  577.            
  578.             XmlSchemaType t = (XmlSchemaType)s.SchemaTypes[baseQname];
  579.             t = t.Redefined != null ? t.Redefined : t;
  580.            
  581.             if (serializables[baseQname] == null) {
  582.                 SerializableMapping baseMapping = new SerializableMapping(baseQname, schemas);
  583.                 SetBase(baseMapping, t.DerivedFrom);
  584.                 serializables.Add(baseQname, baseMapping);
  585.             }
  586.             mapping.SetBaseMapping((SerializableMapping)serializables[baseQname]);
  587.         }
  588.        
  589.         static string GetContextName(ImportContext context)
  590.         {
  591.             switch (context) {
  592.                 case ImportContext.Element:
  593.                     return "element";
  594.                 case ImportContext.Attribute:
  595.                     return "attribute";
  596.                 case ImportContext.Text:
  597.                     return "text";
  598.                 default:
  599.                     throw new ArgumentException(Res.GetString(Res.XmlInternalError), "context");
  600.                     break;
  601.             }
  602.         }
  603.        
  604.         static Exception InvalidAttributeUseException(Type type)
  605.         {
  606.             return new InvalidOperationException(Res.GetString(Res.XmlInvalidAttributeUse, type.FullName));
  607.         }
  608.        
  609.         static Exception UnsupportedException(TypeDesc typeDesc, ImportContext context)
  610.         {
  611.             return new InvalidOperationException(Res.GetString(Res.XmlIllegalTypeContext, typeDesc.FullName, GetContextName(context)));
  612.         }
  613.        
  614.         StructMapping CreateRootMapping()
  615.         {
  616.             TypeDesc typeDesc = typeScope.GetTypeDesc(typeof(object));
  617.             StructMapping mapping = new StructMapping();
  618.             mapping.TypeDesc = typeDesc;
  619.             mapping.TypeName = Soap.UrType;
  620.             mapping.Namespace = XmlSchema.Namespace;
  621.             mapping.Members = new MemberMapping[0];
  622.             mapping.IncludeInSchema = false;
  623.             return mapping;
  624.         }
  625.        
  626.         NullableMapping CreateNullableMapping(TypeMapping baseMapping, TypeDesc typeDesc)
  627.         {
  628.             TypeMapping existingMapping = (TypeMapping)types[typeDesc.Name, baseMapping.Namespace];
  629.             NullableMapping mapping;
  630.             if (existingMapping != null) {
  631.                 if (existingMapping is NullableMapping) {
  632.                     mapping = (NullableMapping)existingMapping;
  633.                     if (mapping.BaseMapping is PrimitiveMapping && baseMapping is PrimitiveMapping)
  634.                         return mapping;
  635.                     else if (mapping.BaseMapping == baseMapping) {
  636.                         return mapping;
  637.                     }
  638.                     else {
  639.                         throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace));
  640.                     }
  641.                 }
  642.                 else {
  643.                     throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, existingMapping.TypeDesc.FullName, typeDesc.Name, existingMapping.Namespace));
  644.                 }
  645.             }
  646.             mapping = new NullableMapping();
  647.             mapping.BaseMapping = baseMapping;
  648.             mapping.TypeDesc = typeDesc;
  649.             mapping.TypeName = baseMapping.TypeName;
  650.             mapping.Namespace = baseMapping.Namespace;
  651.             mapping.IncludeInSchema = baseMapping.IncludeInSchema;
  652.             types.Add(typeDesc.Name, baseMapping.Namespace, mapping);
  653.             typeScope.AddTypeMapping(mapping);
  654.             return mapping;
  655.         }
  656.        
  657.         StructMapping GetRootMapping()
  658.         {
  659.             if (root == null) {
  660.                 root = CreateRootMapping();
  661.                 typeScope.AddTypeMapping(root);
  662.             }
  663.             return root;
  664.         }
  665.        
  666.         TypeMapping GetTypeMapping(string typeName, string ns, TypeDesc typeDesc, NameTable typeLib, Type type)
  667.         {
  668.             TypeMapping mapping;
  669.             if (typeName == null || typeName.Length == 0)
  670.                 mapping = type == null ? null : (TypeMapping)anonymous[type];
  671.             else
  672.                 mapping = (TypeMapping)typeLib[typeName, ns];
  673.            
  674.             if (mapping == null)
  675.                 return null;
  676.             if (!mapping.IsAnonymousType && mapping.TypeDesc != typeDesc)
  677.                 throw new InvalidOperationException(Res.GetString(Res.XmlTypesDuplicate, typeDesc.FullName, mapping.TypeDesc.FullName, typeName, ns));
  678.             return mapping;
  679.         }
  680.        
  681.         StructMapping ImportStructLikeMapping(StructModel model, string ns, bool openModel, XmlAttributes a)
  682.         {
  683.             if (model.TypeDesc.Kind == TypeKind.Root)
  684.                 return GetRootMapping();
  685.             if (a == null)
  686.                 a = GetAttributes(model.Type, false);
  687.            
  688.             string typeNs = ns;
  689.             if (a.XmlType != null && a.XmlType.Namespace != null)
  690.                 typeNs = a.XmlType.Namespace;
  691.             else if (a.XmlRoot != null && a.XmlRoot.Namespace != null)
  692.                 typeNs = a.XmlRoot.Namespace;
  693.            
  694.             string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name);
  695.             typeName = XmlConvert.EncodeLocalName(typeName);
  696.            
  697.             StructMapping mapping = (StructMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc, types, model.Type);
  698.             if (mapping == null) {
  699.                 mapping = new StructMapping();
  700.                 mapping.TypeDesc = model.TypeDesc;
  701.                 mapping.Namespace = typeNs;
  702.                 mapping.TypeName = typeName;
  703.                 if (!mapping.IsAnonymousType)
  704.                     types.Add(typeName, typeNs, mapping);
  705.                 else
  706.                     anonymous[model.Type] = mapping;
  707.                 if (a.XmlType != null) {
  708.                     mapping.IncludeInSchema = a.XmlType.IncludeInSchema;
  709.                 }
  710.                
  711.                 if (model.TypeDesc.BaseTypeDesc != null) {
  712.                     TypeModel baseModel = modelScope.GetTypeModel(model.Type.BaseType, false);
  713.                     if (!(baseModel is StructModel)) {
  714.                         //XmlUnsupportedInheritance=Using '{0}' as a base type for a class is not supported by XmlSerializer.
  715.                         throw new NotSupportedException(Res.GetString(Res.XmlUnsupportedInheritance, model.Type.BaseType.FullName));
  716.                     }
  717.                     mapping.BaseMapping = ImportStructLikeMapping((StructModel)baseModel, mapping.Namespace, openModel, null);
  718.                     ICollection values = mapping.BaseMapping.LocalAttributes.Values;
  719.                     foreach (AttributeAccessor attribute in values) {
  720.                         AddUniqueAccessor(mapping.LocalAttributes, attribute);
  721.                     }
  722.                     if (!mapping.BaseMapping.HasExplicitSequence()) {
  723.                         values = mapping.BaseMapping.LocalElements.Values;
  724.                         foreach (ElementAccessor e in values) {
  725.                             AddUniqueAccessor(mapping.LocalElements, e);
  726.                         }
  727.                     }
  728.                 }
  729.                 ArrayList members = new ArrayList();
  730.                 TextAccessor textAccesor = null;
  731.                 bool hasElements = false;
  732.                 bool isSequence = false;
  733.                
  734.                 foreach (MemberInfo memberInfo in model.GetMemberInfos()) {
  735.                     if ((memberInfo.MemberType & (MemberTypes.Field | MemberTypes.Property)) == 0)
  736.                         continue;
  737.                     XmlAttributes memberAttrs = GetAttributes(memberInfo);
  738.                     if (memberAttrs.XmlIgnore)
  739.                         continue;
  740.                     FieldModel fieldModel = model.GetFieldModel(memberInfo);
  741.                     if (fieldModel == null)
  742.                         continue;
  743.                     try {
  744.                         MemberMapping member = ImportFieldMapping(model, fieldModel, memberAttrs, mapping.Namespace);
  745.                         if (member == null)
  746.                             continue;
  747.                         if (mapping.BaseMapping != null) {
  748.                             if (mapping.BaseMapping.Declares(member, mapping.TypeName))
  749.                                 continue;
  750.                         }
  751.                         isSequence |= member.IsSequence;
  752.                         // add All memeber accessors to the scope accessors
  753.                         AddUniqueAccessor(member, mapping.LocalElements, mapping.LocalAttributes, isSequence);
  754.                        
  755.                         if (member.Text != null) {
  756.                             if (!member.Text.Mapping.TypeDesc.CanBeTextValue && member.Text.Mapping.IsList)
  757.                                 throw new InvalidOperationException(Res.GetString(Res.XmlIllegalTypedTextAttribute, typeName, member.Text.Name, member.Text.Mapping.TypeDesc.FullName));
  758.                             if (textAccesor != null) {
  759.                                 throw new InvalidOperationException(Res.GetString(Res.XmlIllegalMultipleText, model.Type.FullName));
  760.                             }
  761.                             textAccesor = member.Text;
  762.                         }
  763.                         if (member.Xmlns != null) {
  764.                             if (mapping.XmlnsMember != null)
  765.                                 throw new InvalidOperationException(Res.GetString(Res.XmlMultipleXmlns, model.Type.FullName));
  766.                             mapping.XmlnsMember = member;
  767.                         }
  768.                         if (member.Elements != null && member.Elements.Length != 0) {
  769.                             hasElements = true;
  770.                         }
  771.                         members.Add(member);
  772.                     }
  773.                     catch (Exception e) {
  774.                         if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  775.                             throw;
  776.                         }
  777.                         throw CreateMemberReflectionException(fieldModel, e);
  778.                     }
  779.                     catch {
  780.                         throw CreateMemberReflectionException(fieldModel, null);
  781.                     }
  782.                 }
  783.                 mapping.SetContentModel(textAccesor, hasElements);
  784.                 if (isSequence) {
  785.                     Hashtable ids = new Hashtable();
  786.                     for (int i = 0; i < members.Count; i++) {
  787.                         MemberMapping member = (MemberMapping)members[i];
  788.                         if (!member.IsParticle)
  789.                             continue;
  790.                         if (member.IsSequence) {
  791.                             if (ids[member.SequenceId] != null) {
  792.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceUnique, member.SequenceId.ToString(CultureInfo.InvariantCulture), "Order", member.Name));
  793.                             }
  794.                             ids[member.SequenceId] = member;
  795.                         }
  796.                         else {
  797.                             throw new InvalidOperationException(Res.GetString(Res.XmlSequenceInconsistent, "Order", member.Name));
  798.                         }
  799.                     }
  800.                     members.Sort(new MemberMappingComparer());
  801.                 }
  802.                 mapping.Members = (MemberMapping[])members.ToArray(typeof(MemberMapping));
  803.                
  804.                 if (mapping.BaseMapping == null)
  805.                     mapping.BaseMapping = GetRootMapping();
  806.                
  807.                 if (mapping.XmlnsMember != null && mapping.BaseMapping.HasXmlnsMember)
  808.                     throw new InvalidOperationException(Res.GetString(Res.XmlMultipleXmlns, model.Type.FullName));
  809.                
  810.                 IncludeTypes(model.Type);
  811.                 typeScope.AddTypeMapping(mapping);
  812.             }
  813.             if (openModel)
  814.                 mapping.IsOpenModel = true;
  815.             return mapping;
  816.         }
  817.        
  818.         internal string XsdTypeName(Type type)
  819.         {
  820.             if (type == typeof(object))
  821.                 return Soap.UrType;
  822.             TypeDesc typeDesc = typeScope.GetTypeDesc(type);
  823.             if (typeDesc.IsPrimitive && typeDesc.DataType != null && typeDesc.DataType.Name != null && typeDesc.DataType.Name.Length > 0)
  824.                 return typeDesc.DataType.Name;
  825.             return XsdTypeName(type, GetAttributes(type, false), typeDesc.Name);
  826.         }
  827.         internal string XsdTypeName(Type type, XmlAttributes a, string name)
  828.         {
  829.             if (a.XmlType != null && a.XmlType.AnonymousType)
  830.                 return null;
  831.             string typeName = name;
  832.             if (a.XmlType != null && a.XmlType.TypeName.Length > 0)
  833.                 typeName = a.XmlType.TypeName;
  834.            
  835.             if (type.IsGenericType && typeName.IndexOf('{') >= 0) {
  836.                 Type genType = type.GetGenericTypeDefinition();
  837.                 Type[] names = genType.GetGenericArguments();
  838.                 Type[] types = type.GetGenericArguments();
  839.                
  840.                 for (int i = 0; i < names.Length; i++) {
  841.                     string argument = "{" + names[i] + "}";
  842.                     if (typeName.Contains(argument)) {
  843.                         typeName = typeName.Replace(argument, XsdTypeName(types[i]));
  844.                         if (typeName.IndexOf('{') < 0) {
  845.                             break;
  846.                         }
  847.                     }
  848.                 }
  849.             }
  850.             return typeName;
  851.         }
  852.        
  853.         private static int CountAtLevel(XmlArrayItemAttributes attributes, int level)
  854.         {
  855.             int sum = 0;
  856.             for (int i = 0; i < attributes.Count; i++)
  857.                 if (attributes[i].NestingLevel == level)
  858.                     sum++;
  859.             return sum;
  860.         }
  861.        
  862.         void SetArrayMappingType(ArrayMapping mapping, string defaultNs, Type type)
  863.         {
  864.             XmlAttributes a = GetAttributes(type, false);
  865.             bool isAnonymous = a.XmlType == null ? false : a.XmlType.AnonymousType;
  866.             if (isAnonymous) {
  867.                 mapping.TypeName = null;
  868.                 mapping.Namespace = defaultNs;
  869.                 return;
  870.             }
  871.             string name;
  872.             string ns;
  873.             TypeMapping itemTypeMapping;
  874.             ElementAccessor element = null;
  875.            
  876.             if (mapping.Elements.Length == 1) {
  877.                 element = mapping.Elements[0];
  878.                 itemTypeMapping = element.Mapping;
  879.             }
  880.             else {
  881.                 itemTypeMapping = null;
  882.             }
  883.            
  884.             bool generateTypeName = true;
  885.             if (a.XmlType != null) {
  886.                 ns = a.XmlType.Namespace;
  887.                 name = XsdTypeName(type, a, a.XmlType.TypeName);
  888.                 name = XmlConvert.EncodeLocalName(name);
  889.                 generateTypeName = name == null;
  890.             }
  891.             else if (itemTypeMapping is EnumMapping) {
  892.                 ns = itemTypeMapping.Namespace;
  893.                 name = itemTypeMapping.DefaultElementName;
  894.             }
  895.             else if (itemTypeMapping is PrimitiveMapping) {
  896.                 ns = defaultNs;
  897.                 name = itemTypeMapping.TypeDesc.DataType.Name;
  898.             }
  899.             else if (itemTypeMapping is StructMapping && itemTypeMapping.TypeDesc.IsRoot) {
  900.                 ns = defaultNs;
  901.                 name = Soap.UrType;
  902.             }
  903.             else if (itemTypeMapping != null) {
  904.                 ns = itemTypeMapping.Namespace == XmlSchema.Namespace ? defaultNs : itemTypeMapping.Namespace;
  905.                 name = itemTypeMapping.DefaultElementName;
  906.             }
  907.             else {
  908.                 ns = defaultNs;
  909.                 name = "Choice" + (choiceNum++);
  910.             }
  911.            
  912.             if (name == null)
  913.                 name = "Any";
  914.            
  915.             if (element != null)
  916.                 ns = element.Namespace;
  917.            
  918.             if (ns == null)
  919.                 ns = defaultNs;
  920.            
  921.             string uniqueName = name = generateTypeName ? "ArrayOf" + CodeIdentifier.MakePascal(name) : name;
  922.             int i = 1;
  923.             TypeMapping existingMapping = (TypeMapping)types[uniqueName, ns];
  924.             while (existingMapping != null) {
  925.                 if (existingMapping is ArrayMapping) {
  926.                     ArrayMapping arrayMapping = (ArrayMapping)existingMapping;
  927.                     if (AccessorMapping.ElementsMatch(arrayMapping.Elements, mapping.Elements)) {
  928.                         break;
  929.                     }
  930.                 }
  931.                 // need to re-name the mapping
  932.                 uniqueName = name + i.ToString(CultureInfo.InvariantCulture);
  933.                 existingMapping = (TypeMapping)types[uniqueName, ns];
  934.                 i++;
  935.             }
  936.             mapping.TypeName = uniqueName;
  937.             mapping.Namespace = ns;
  938.         }
  939.        
  940.         ArrayMapping ImportArrayLikeMapping(ArrayModel model, string ns)
  941.         {
  942.             ArrayMapping mapping = new ArrayMapping();
  943.             mapping.TypeDesc = model.TypeDesc;
  944.            
  945.             if (savedArrayItemAttributes == null)
  946.                 savedArrayItemAttributes = new XmlArrayItemAttributes();
  947.             if (CountAtLevel(savedArrayItemAttributes, arrayNestingLevel) == 0)
  948.                 savedArrayItemAttributes.Add(CreateArrayItemAttribute(typeScope.GetTypeDesc(model.Element.Type), arrayNestingLevel));
  949.             CreateArrayElementsFromAttributes(mapping, savedArrayItemAttributes, model.Element.Type, savedArrayNamespace == null ? ns : savedArrayNamespace);
  950.             SetArrayMappingType(mapping, ns, model.Type);
  951.            
  952.             // reconcile accessors now that we have the ArrayMapping namespace
  953.             for (int i = 0; i < mapping.Elements.Length; i++) {
  954.                 mapping.Elements[i] = ReconcileLocalAccessor(mapping.Elements[i], mapping.Namespace);
  955.             }
  956.            
  957.             IncludeTypes(model.Type);
  958.            
  959.             // in the case of an ArrayMapping we can have more that one mapping correspond to a type
  960.             // examples of that are ArrayList and object[] both will map tp ArrayOfur-type
  961.             // so we create a link list for all mappings of the same XSD type
  962.             ArrayMapping existingMapping = (ArrayMapping)types[mapping.TypeName, mapping.Namespace];
  963.             if (existingMapping != null) {
  964.                 ArrayMapping first = existingMapping;
  965.                 while (existingMapping != null) {
  966.                     if (existingMapping.TypeDesc == model.TypeDesc)
  967.                         return existingMapping;
  968.                     existingMapping = existingMapping.Next;
  969.                 }
  970.                 mapping.Next = first;
  971.                 if (!mapping.IsAnonymousType)
  972.                     types[mapping.TypeName, mapping.Namespace] = mapping;
  973.                 else
  974.                     anonymous[model.Type] = mapping;
  975.                 return mapping;
  976.             }
  977.             typeScope.AddTypeMapping(mapping);
  978.             if (!mapping.IsAnonymousType)
  979.                 types.Add(mapping.TypeName, mapping.Namespace, mapping);
  980.             else
  981.                 anonymous[model.Type] = mapping;
  982.             return mapping;
  983.         }
  984.        
  985.         void CheckContext(TypeDesc typeDesc, ImportContext context)
  986.         {
  987.             switch (context) {
  988.                 case ImportContext.Element:
  989.                     if (typeDesc.CanBeElementValue)
  990.                         return;
  991.                     break;
  992.                 case ImportContext.Attribute:
  993.                     if (typeDesc.CanBeAttributeValue)
  994.                         return;
  995.                     break;
  996.                 case ImportContext.Text:
  997.                     if (typeDesc.CanBeTextValue || typeDesc.IsEnum || typeDesc.IsPrimitive)
  998.                         return;
  999.                     break;
  1000.                 default:
  1001.                     throw new ArgumentException(Res.GetString(Res.XmlInternalError), "context");
  1002.                     break;
  1003.             }
  1004.             throw UnsupportedException(typeDesc, context);
  1005.         }
  1006.        
  1007.         PrimitiveMapping ImportPrimitiveMapping(PrimitiveModel model, ImportContext context, string dataType, bool repeats)
  1008.         {
  1009.             PrimitiveMapping mapping = new PrimitiveMapping();
  1010.             if (dataType.Length > 0) {
  1011.                 mapping.TypeDesc = typeScope.GetTypeDesc(dataType, XmlSchema.Namespace);
  1012.                 if (mapping.TypeDesc == null) {
  1013.                     // try it as a non-Xsd type
  1014.                     mapping.TypeDesc = typeScope.GetTypeDesc(dataType, UrtTypes.Namespace);
  1015.                     if (mapping.TypeDesc == null) {
  1016.                         throw new InvalidOperationException(Res.GetString(Res.XmlUdeclaredXsdType, dataType));
  1017.                     }
  1018.                 }
  1019.             }
  1020.             else {
  1021.                 mapping.TypeDesc = model.TypeDesc;
  1022.             }
  1023.             mapping.TypeName = mapping.TypeDesc.DataType.Name;
  1024.             mapping.Namespace = mapping.TypeDesc.IsXsdType ? XmlSchema.Namespace : UrtTypes.Namespace;
  1025.             mapping.IsList = repeats;
  1026.             CheckContext(mapping.TypeDesc, context);
  1027.             return mapping;
  1028.         }
  1029.        
  1030.         EnumMapping ImportEnumMapping(EnumModel model, string ns, bool repeats)
  1031.         {
  1032.             XmlAttributes a = GetAttributes(model.Type, false);
  1033.             string typeNs = ns;
  1034.             if (a.XmlType != null && a.XmlType.Namespace != null)
  1035.                 typeNs = a.XmlType.Namespace;
  1036.            
  1037.             string typeName = XsdTypeName(model.Type, a, model.TypeDesc.Name);
  1038.             typeName = XmlConvert.EncodeLocalName(typeName);
  1039.            
  1040.             EnumMapping mapping = (EnumMapping)GetTypeMapping(typeName, typeNs, model.TypeDesc, types, model.Type);
  1041.             if (mapping == null) {
  1042.                 mapping = new EnumMapping();
  1043.                 mapping.TypeDesc = model.TypeDesc;
  1044.                 mapping.TypeName = typeName;
  1045.                 mapping.Namespace = typeNs;
  1046.                 mapping.IsFlags = model.Type.IsDefined(typeof(FlagsAttribute), false);
  1047.                 if (mapping.IsFlags && repeats)
  1048.                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttributeFlagsArray, model.TypeDesc.FullName));
  1049.                 mapping.IsList = repeats;
  1050.                 mapping.IncludeInSchema = a.XmlType == null ? true : a.XmlType.IncludeInSchema;
  1051.                 if (!mapping.IsAnonymousType)
  1052.                     types.Add(typeName, typeNs, mapping);
  1053.                 else
  1054.                     anonymous[model.Type] = mapping;
  1055.                 ArrayList constants = new ArrayList();
  1056.                 for (int i = 0; i < model.Constants.Length; i++) {
  1057.                     ConstantMapping constant = ImportConstantMapping(model.Constants[i]);
  1058.                     if (constant != null)
  1059.                         constants.Add(constant);
  1060.                 }
  1061.                 if (constants.Count == 0) {
  1062.                     throw new InvalidOperationException(Res.GetString(Res.XmlNoSerializableMembers, model.TypeDesc.FullName));
  1063.                 }
  1064.                 mapping.Constants = (ConstantMapping[])constants.ToArray(typeof(ConstantMapping));
  1065.                 typeScope.AddTypeMapping(mapping);
  1066.             }
  1067.             return mapping;
  1068.         }
  1069.        
  1070.         ConstantMapping ImportConstantMapping(ConstantModel model)
  1071.         {
  1072.             XmlAttributes a = GetAttributes(model.FieldInfo);
  1073.             if (a.XmlIgnore)
  1074.                 return null;
  1075.             if ((a.XmlFlags & ~XmlAttributeFlags.Enum) != 0)
  1076.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidConstantAttribute));
  1077.             if (a.XmlEnum == null)
  1078.                 a.XmlEnum = new XmlEnumAttribute();
  1079.            
  1080.             ConstantMapping constant = new ConstantMapping();
  1081.             constant.XmlName = a.XmlEnum.Name == null ? model.Name : a.XmlEnum.Name;
  1082.             constant.Name = model.Name;
  1083.             constant.Value = model.Value;
  1084.             return constant;
  1085.         }
  1086.        
  1087.         MembersMapping ImportMembersMapping(XmlReflectionMember[] xmlReflectionMembers, string ns, bool hasWrapperElement, bool rpc, bool openModel)
  1088.         {
  1089.             MembersMapping members = new MembersMapping();
  1090.             members.TypeDesc = typeScope.GetTypeDesc(typeof(object[]));
  1091.             MemberMapping[] mappings = new MemberMapping[xmlReflectionMembers.Length];
  1092.             NameTable elements = new NameTable();
  1093.             NameTable attributes = new NameTable();
  1094.             TextAccessor textAccessor = null;
  1095.             bool isSequence = false;
  1096.            
  1097.             for (int i = 0; i < mappings.Length; i++) {
  1098.                 try {
  1099.                     MemberMapping mapping = ImportMemberMapping(xmlReflectionMembers[i], ns, xmlReflectionMembers, rpc, openModel);
  1100.                     if (!hasWrapperElement) {
  1101.                         if (mapping.Attribute != null) {
  1102.                             if (rpc) {
  1103.                                 throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitAttributeAttributes));
  1104.                             }
  1105.                             else {
  1106.                                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidAttributeType, "XmlAttribute"));
  1107.                             }
  1108.                         }
  1109.                     }
  1110.                     if (rpc && xmlReflectionMembers[i].IsReturnValue) {
  1111.                         if (i > 0)
  1112.                             throw new InvalidOperationException(Res.GetString(Res.XmlInvalidReturnPosition));
  1113.                         mapping.IsReturnValue = true;
  1114.                     }
  1115.                     mappings[i] = mapping;
  1116.                     isSequence |= mapping.IsSequence;
  1117.                     if (!xmlReflectionMembers[i].XmlAttributes.XmlIgnore) {
  1118.                         // add All memeber accessors to the scope accessors
  1119.                         AddUniqueAccessor(mapping, elements, attributes, isSequence);
  1120.                     }
  1121.                    
  1122.                     mappings[i] = mapping;
  1123.                     if (mapping.Text != null) {
  1124.                         if (textAccessor != null) {
  1125.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalMultipleTextMembers));
  1126.                         }
  1127.                         textAccessor = mapping.Text;
  1128.                     }
  1129.                    
  1130.                     if (mapping.Xmlns != null) {
  1131.                         if (members.XmlnsMember != null)
  1132.                             throw new InvalidOperationException(Res.GetString(Res.XmlMultipleXmlnsMembers));
  1133.                         members.XmlnsMember = mapping;
  1134.                     }
  1135.                 }
  1136.                 catch (Exception e) {
  1137.                     if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  1138.                         throw;
  1139.                     }
  1140.                     throw CreateReflectionException(xmlReflectionMembers[i].MemberName, e);
  1141.                 }
  1142.                 catch {
  1143.                     throw CreateReflectionException(xmlReflectionMembers[i].MemberName, null);
  1144.                 }
  1145.             }
  1146.             if (isSequence) {
  1147.                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMembers, "Order"));
  1148.             }
  1149.             members.Members = mappings;
  1150.             members.HasWrapperElement = hasWrapperElement;
  1151.             return members;
  1152.         }
  1153.        
  1154.         MemberMapping ImportMemberMapping(XmlReflectionMember xmlReflectionMember, string ns, XmlReflectionMember[] xmlReflectionMembers, bool rpc, bool openModel)
  1155.         {
  1156.             XmlSchemaForm form = rpc ? XmlSchemaForm.Unqualified : XmlSchemaForm.Qualified;
  1157.             XmlAttributes a = xmlReflectionMember.XmlAttributes;
  1158.             TypeDesc typeDesc = typeScope.GetTypeDesc(xmlReflectionMember.MemberType);
  1159.            
  1160.             if (a.XmlFlags == 0) {
  1161.                 if (typeDesc.IsArrayLike) {
  1162.                     XmlArrayAttribute xmlArray = CreateArrayAttribute(typeDesc);
  1163.                     xmlArray.ElementName = xmlReflectionMember.MemberName;
  1164.                     xmlArray.Namespace = rpc ? null : ns;
  1165.                     xmlArray.Form = form;
  1166.                     a.XmlArray = xmlArray;
  1167.                 }
  1168.                 else {
  1169.                     XmlElementAttribute xmlElement = CreateElementAttribute(typeDesc);
  1170.                     // If there is no metadata specified on a parameter, then see if someone used
  1171.                     // an XmlRoot attribute on the struct or class.
  1172.                     if (typeDesc.IsStructLike) {
  1173.                         XmlAttributes structAttrs = new XmlAttributes(xmlReflectionMember.MemberType);
  1174.                         if (structAttrs.XmlRoot != null) {
  1175.                             if (structAttrs.XmlRoot.ElementName.Length > 0)
  1176.                                 xmlElement.ElementName = structAttrs.XmlRoot.ElementName;
  1177.                             if (rpc) {
  1178.                                 xmlElement.Namespace = null;
  1179.                                 if (structAttrs.XmlRoot.IsNullableSpecified)
  1180.                                     xmlElement.IsNullable = structAttrs.XmlRoot.IsNullable;
  1181.                             }
  1182.                             else {
  1183.                                 xmlElement.Namespace = structAttrs.XmlRoot.Namespace;
  1184.                                 xmlElement.IsNullable = structAttrs.XmlRoot.IsNullable;
  1185.                             }
  1186.                         }
  1187.                     }
  1188.                     if (xmlElement.ElementName.Length == 0)
  1189.                         xmlElement.ElementName = xmlReflectionMember.MemberName;
  1190.                     if (xmlElement.Namespace == null && !rpc)
  1191.                         xmlElement.Namespace = ns;
  1192.                     xmlElement.Form = form;
  1193.                     a.XmlElements.Add(xmlElement);
  1194.                 }
  1195.             }
  1196.             else if (a.XmlRoot != null) {
  1197.                 CheckNullable(a.XmlRoot.IsNullable, typeDesc, null);
  1198.             }
  1199.             MemberMapping member = new MemberMapping();
  1200.             member.Name = xmlReflectionMember.MemberName;
  1201.             bool checkSpecified = FindSpecifiedMember(xmlReflectionMember.MemberName, xmlReflectionMembers) != null;
  1202.             FieldModel model = new FieldModel(xmlReflectionMember.MemberName, xmlReflectionMember.MemberType, typeScope.GetTypeDesc(xmlReflectionMember.MemberType), checkSpecified, false);
  1203.             member.CheckShouldPersist = model.CheckShouldPersist;
  1204.             member.CheckSpecified = model.CheckSpecified;
  1205.             member.ReadOnly = model.ReadOnly;
  1206.             // || !model.FieldTypeDesc.HasDefaultConstructor;
  1207.             Type choiceIdentifierType = null;
  1208.             if (a.XmlChoiceIdentifier != null) {
  1209.                 choiceIdentifierType = GetChoiceIdentifierType(a.XmlChoiceIdentifier, xmlReflectionMembers, typeDesc.IsArrayLike, model.Name);
  1210.             }
  1211.             ImportAccessorMapping(member, model, a, ns, choiceIdentifierType, rpc, openModel);
  1212.             if (xmlReflectionMember.OverrideIsNullable && member.Elements.Length > 0)
  1213.                 member.Elements[0].IsNullable = false;
  1214.             return member;
  1215.         }
  1216.        
  1217.         static internal XmlReflectionMember FindSpecifiedMember(string memberName, XmlReflectionMember[] reflectionMembers)
  1218.         {
  1219.             for (int i = 0; i < reflectionMembers.Length; i++)
  1220.                 if (string.Compare(reflectionMembers[i].MemberName, memberName + "Specified", StringComparison.Ordinal) == 0)
  1221.                     return reflectionMembers[i];
  1222.             return null;
  1223.         }
  1224.        
  1225.         MemberMapping ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, string ns)
  1226.         {
  1227.             MemberMapping member = new MemberMapping();
  1228.             member.Name = model.Name;
  1229.             member.CheckShouldPersist = model.CheckShouldPersist;
  1230.             member.CheckSpecified = model.CheckSpecified;
  1231.             member.ReadOnly = model.ReadOnly;
  1232.             // || !model.FieldTypeDesc.HasDefaultConstructor;
  1233.             Type choiceIdentifierType = null;
  1234.             if (a.XmlChoiceIdentifier != null) {
  1235.                 choiceIdentifierType = GetChoiceIdentifierType(a.XmlChoiceIdentifier, parent, model.FieldTypeDesc.IsArrayLike, model.Name);
  1236.             }
  1237.             ImportAccessorMapping(member, model, a, ns, choiceIdentifierType, false, false);
  1238.             return member;
  1239.         }
  1240.        
  1241.         Type CheckChoiceIdentifierType(Type type, bool isArrayLike, string identifierName, string memberName)
  1242.         {
  1243.             if (type.IsArray) {
  1244.                 if (!isArrayLike) {
  1245.                     // Inconsistent type of the choice identifier '{0}'. Please use {1}.
  1246.                     throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentifierType, identifierName, memberName, type.GetElementType().FullName));
  1247.                 }
  1248.                 type = type.GetElementType();
  1249.             }
  1250.             else if (isArrayLike) {
  1251.                 // Inconsistent type of the choice identifier '{0}'. Please use {1}.
  1252.                 throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentifierArrayType, identifierName, memberName, type.FullName));
  1253.             }
  1254.            
  1255.             if (!type.IsEnum) {
  1256.                 // Choice identifier '{0}' must be an enum.
  1257.                 throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentifierTypeEnum, identifierName));
  1258.             }
  1259.             return type;
  1260.         }
  1261.        
  1262.         Type GetChoiceIdentifierType(XmlChoiceIdentifierAttribute choice, XmlReflectionMember[] xmlReflectionMembers, bool isArrayLike, string accessorName)
  1263.         {
  1264.             for (int i = 0; i < xmlReflectionMembers.Length; i++) {
  1265.                 if (choice.MemberName == xmlReflectionMembers[i].MemberName) {
  1266.                     return CheckChoiceIdentifierType(xmlReflectionMembers[i].MemberType, isArrayLike, choice.MemberName, accessorName);
  1267.                 }
  1268.             }
  1269.             // Missing '{0}' needed for serialization of choice '{1}'.
  1270.             throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferMemberMissing, choice.MemberName, accessorName));
  1271.         }
  1272.        
  1273.         Type GetChoiceIdentifierType(XmlChoiceIdentifierAttribute choice, StructModel structModel, bool isArrayLike, string accessorName)
  1274.         {
  1275.             // check that the choice field exists
  1276.            
  1277.             MemberInfo[] infos = structModel.Type.GetMember(choice.MemberName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  1278.             if (infos == null || infos.Length == 0) {
  1279.                 // if we can not find the choice identifier between fields, check proerties
  1280.                 PropertyInfo info = structModel.Type.GetProperty(choice.MemberName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  1281.                
  1282.                 if (info == null) {
  1283.                     // Missing '{0}' needed for serialization of choice '{1}'.
  1284.                     throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferMemberMissing, choice.MemberName, accessorName));
  1285.                 }
  1286.                 infos = new MemberInfo[] {info};
  1287.             }
  1288.             else if (infos.Length > 1) {
  1289.                 // Ambiguous choice identifer: there are several members named '{0}'.
  1290.                 throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferAmbiguous, choice.MemberName));
  1291.             }
  1292.            
  1293.             FieldModel member = structModel.GetFieldModel(infos[0]);
  1294.             if (member == null) {
  1295.                 // Missing '{0}' needed for serialization of choice '{1}'.
  1296.                 throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferMemberMissing, choice.MemberName, accessorName));
  1297.             }
  1298.             Type enumType = member.FieldType;
  1299.             enumType = CheckChoiceIdentifierType(enumType, isArrayLike, choice.MemberName, accessorName);
  1300.             return enumType;
  1301.         }
  1302.        
  1303.         void CreateArrayElementsFromAttributes(ArrayMapping arrayMapping, XmlArrayItemAttributes attributes, Type arrayElementType, string arrayElementNs)
  1304.         {
  1305.             NameTable arrayItemElements = new NameTable();
  1306.             // xmlelementname + xmlns -> ElementAccessor
  1307.             for (int i = 0; attributes != null && i < attributes.Count; i++) {
  1308.                 XmlArrayItemAttribute xmlArrayItem = attributes[i];
  1309.                 if (xmlArrayItem.NestingLevel != arrayNestingLevel)
  1310.                     continue;
  1311.                 Type targetType = xmlArrayItem.Type != null ? xmlArrayItem.Type : arrayElementType;
  1312.                 TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1313.                 ElementAccessor arrayItemElement = new ElementAccessor();
  1314.                 arrayItemElement.Namespace = xmlArrayItem.Namespace == null ? arrayElementNs : xmlArrayItem.Namespace;
  1315.                 arrayItemElement.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), arrayItemElement.Namespace, ImportContext.Element, xmlArrayItem.DataType, null);
  1316.                 arrayItemElement.Name = xmlArrayItem.ElementName.Length == 0 ? arrayItemElement.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(xmlArrayItem.ElementName);
  1317.                 arrayItemElement.IsNullable = xmlArrayItem.IsNullableSpecified ? xmlArrayItem.IsNullable : targetTypeDesc.IsNullable || targetTypeDesc.IsOptionalValue;
  1318.                 arrayItemElement.Form = xmlArrayItem.Form == XmlSchemaForm.None ? XmlSchemaForm.Qualified : xmlArrayItem.Form;
  1319.                 CheckForm(arrayItemElement.Form, arrayElementNs != arrayItemElement.Namespace);
  1320.                 CheckNullable(arrayItemElement.IsNullable, targetTypeDesc, arrayItemElement.Mapping);
  1321.                 AddUniqueAccessor(arrayItemElements, arrayItemElement);
  1322.             }
  1323.             arrayMapping.Elements = (ElementAccessor[])arrayItemElements.ToArray(typeof(ElementAccessor));
  1324.         }
  1325.        
  1326.         void ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, string ns, Type choiceIdentifierType, bool rpc, bool openModel)
  1327.         {
  1328.             XmlSchemaForm elementFormDefault = XmlSchemaForm.Qualified;
  1329.             int previousNestingLevel = arrayNestingLevel;
  1330.             int sequenceId = -1;
  1331.             XmlArrayItemAttributes previousArrayItemAttributes = savedArrayItemAttributes;
  1332.             string previousArrayNamespace = savedArrayNamespace;
  1333.             arrayNestingLevel = 0;
  1334.             savedArrayItemAttributes = null;
  1335.             savedArrayNamespace = null;
  1336.             Type accessorType = model.FieldType;
  1337.             string accessorName = model.Name;
  1338.             ArrayList elementList = new ArrayList();
  1339.             NameTable elements = new NameTable();
  1340.             accessor.TypeDesc = typeScope.GetTypeDesc(accessorType);
  1341.             XmlAttributeFlags flags = a.XmlFlags;
  1342.             accessor.Ignore = a.XmlIgnore;
  1343.             if (rpc)
  1344.                 CheckTopLevelAttributes(a, accessorName);
  1345.             else
  1346.                 CheckAmbiguousChoice(a, accessorType, accessorName);
  1347.            
  1348.             XmlAttributeFlags elemFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier;
  1349.             XmlAttributeFlags attrFlags = XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyAttribute;
  1350.             XmlAttributeFlags arrayFlags = XmlAttributeFlags.Array | XmlAttributeFlags.ArrayItems;
  1351.            
  1352.             // special case for byte[]. It can be a primitive (base64Binary or hexBinary), or it can
  1353.             // be an array of bytes. Our default is primitive; specify [XmlArray] to get array behavior.
  1354.             if ((flags & arrayFlags) != 0 && accessorType == typeof(byte[]))
  1355.                 accessor.TypeDesc = typeScope.GetArrayTypeDesc(accessorType);
  1356.            
  1357.             if (a.XmlChoiceIdentifier != null) {
  1358.                 accessor.ChoiceIdentifier = new ChoiceIdentifierAccessor();
  1359.                 accessor.ChoiceIdentifier.MemberName = a.XmlChoiceIdentifier.MemberName;
  1360.                 accessor.ChoiceIdentifier.Mapping = ImportTypeMapping(modelScope.GetTypeModel(choiceIdentifierType), ns, ImportContext.Element, String.Empty, null);
  1361.                 CheckChoiceIdentifierMapping((EnumMapping)accessor.ChoiceIdentifier.Mapping);
  1362.             }
  1363.            
  1364.             if (accessor.TypeDesc.IsArrayLike) {
  1365.                 Type arrayElementType = TypeScope.GetArrayElementType(accessorType, model.FieldTypeDesc.FullName + "." + model.Name);
  1366.                
  1367.                 if ((flags & attrFlags) != 0) {
  1368.                     if ((flags & attrFlags) != flags)
  1369.                         throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttributesArrayAttribute));
  1370.                    
  1371.                     if (a.XmlAttribute != null && !accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive && !accessor.TypeDesc.ArrayElementTypeDesc.IsEnum) {
  1372.                        
  1373.                         if (accessor.TypeDesc.ArrayElementTypeDesc.Kind == TypeKind.Serializable) {
  1374.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrTextInterface, accessorName, accessor.TypeDesc.ArrayElementTypeDesc.FullName, typeof(IXmlSerializable).Name));
  1375.                         }
  1376.                         else {
  1377.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName, accessor.TypeDesc.ArrayElementTypeDesc.FullName));
  1378.                         }
  1379.                     }
  1380.                    
  1381.                     bool isList = a.XmlAttribute != null && (accessor.TypeDesc.ArrayElementTypeDesc.IsPrimitive || accessor.TypeDesc.ArrayElementTypeDesc.IsEnum);
  1382.                    
  1383.                     if (a.XmlAnyAttribute != null) {
  1384.                         a.XmlAttribute = new XmlAttributeAttribute();
  1385.                     }
  1386.                    
  1387.                     AttributeAccessor attribute = new AttributeAccessor();
  1388.                     Type targetType = a.XmlAttribute.Type == null ? arrayElementType : a.XmlAttribute.Type;
  1389.                     TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1390.                     attribute.Name = Accessor.EscapeQName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName);
  1391.                     attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace;
  1392.                     attribute.Form = a.XmlAttribute.Form;
  1393.                     if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) {
  1394.                         attribute.Form = XmlSchemaForm.Qualified;
  1395.                     }
  1396.                     attribute.CheckSpecial();
  1397.                     CheckForm(attribute.Form, ns != attribute.Namespace);
  1398.                     attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null, isList, false);
  1399.                     attribute.IsList = isList;
  1400.                     attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1401.                     attribute.Any = (a.XmlAnyAttribute != null);
  1402.                     if (attribute.Form == XmlSchemaForm.Qualified && attribute.Namespace != ns) {
  1403.                         if (xsdAttributes == null)
  1404.                             xsdAttributes = new NameTable();
  1405.                         attribute = (AttributeAccessor)ReconcileAccessor(attribute, xsdAttributes);
  1406.                     }
  1407.                     accessor.Attribute = attribute;
  1408.                    
  1409.                 }
  1410.                 else if ((flags & elemFlags) != 0) {
  1411.                     if ((flags & elemFlags) != flags)
  1412.                         throw new InvalidOperationException(Res.GetString(Res.XmlIllegalElementsArrayAttribute));
  1413.                    
  1414.                     if (a.XmlText != null) {
  1415.                         TextAccessor text = new TextAccessor();
  1416.                         Type targetType = a.XmlText.Type == null ? arrayElementType : a.XmlText.Type;
  1417.                         TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1418.                         text.Name = accessorName;
  1419.                         // unused except to make more helpful error messages
  1420.                         text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(targetType), ns, ImportContext.Text, a.XmlText.DataType, null, true, false);
  1421.                         if (!(text.Mapping is SpecialMapping) && targetTypeDesc != typeScope.GetTypeDesc(typeof(string)))
  1422.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayTextAttribute, accessorName));
  1423.                        
  1424.                         accessor.Text = text;
  1425.                     }
  1426.                     if (a.XmlText == null && a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0)
  1427.                         a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc));
  1428.                    
  1429.                     for (int i = 0; i < a.XmlElements.Count; i++) {
  1430.                         XmlElementAttribute xmlElement = a.XmlElements[i];
  1431.                         Type targetType = xmlElement.Type == null ? arrayElementType : xmlElement.Type;
  1432.                         TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1433.                         TypeModel typeModel = modelScope.GetTypeModel(targetType);
  1434.                         ElementAccessor element = new ElementAccessor();
  1435.                         element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace;
  1436.                         element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null);
  1437.                         if (a.XmlElements.Count == 1) {
  1438.                             element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName);
  1439.                             //element.IsUnbounded = element.Mapping is ArrayMapping;
  1440.                         }
  1441.                         else {
  1442.                             element.Name = xmlElement.ElementName.Length == 0 ? element.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(xmlElement.ElementName);
  1443.                         }
  1444.                         element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1445.                         if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue)
  1446.                             throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement"));
  1447.                         element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue;
  1448.                         element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form;
  1449.                        
  1450.                         CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping);
  1451.                         if (!rpc) {
  1452.                             CheckForm(element.Form, ns != element.Namespace);
  1453.                             element = ReconcileLocalAccessor(element, ns);
  1454.                         }
  1455.                         if (xmlElement.Order != -1) {
  1456.                             if (xmlElement.Order != sequenceId && sequenceId != -1)
  1457.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order"));
  1458.                             sequenceId = xmlElement.Order;
  1459.                         }
  1460.                         AddUniqueAccessor(elements, element);
  1461.                         elementList.Add(element);
  1462.                     }
  1463.                     NameTable anys = new NameTable();
  1464.                     for (int i = 0; i < a.XmlAnyElements.Count; i++) {
  1465.                         XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i];
  1466.                         Type targetType = typeof(IXmlSerializable).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlNode).IsAssignableFrom(arrayElementType) ? arrayElementType : typeof(XmlElement);
  1467.                         if (!arrayElementType.IsAssignableFrom(targetType))
  1468.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, arrayElementType.FullName));
  1469.                         string anyName = xmlAnyElement.Name.Length == 0 ? xmlAnyElement.Name : XmlConvert.EncodeLocalName(xmlAnyElement.Name);
  1470.                         string anyNs = xmlAnyElement.NamespaceSpecified ? xmlAnyElement.Namespace : null;
  1471.                         if (anys[anyName, anyNs] != null) {
  1472.                             // ignore duplicate anys
  1473.                             continue;
  1474.                         }
  1475.                         anys[anyName, anyNs] = xmlAnyElement;
  1476.                         if (elements[anyName, (anyNs == null ? ns : anyNs)] != null) {
  1477.                             throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementDuplicate, accessorName, xmlAnyElement.Name, xmlAnyElement.Namespace == null ? "null" : xmlAnyElement.Namespace));
  1478.                         }
  1479.                         ElementAccessor element = new ElementAccessor();
  1480.                         element.Name = anyName;
  1481.                         element.Namespace = anyNs == null ? ns : anyNs;
  1482.                         element.Any = true;
  1483.                         element.AnyNamespaces = anyNs;
  1484.                         TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1485.                         TypeModel typeModel = modelScope.GetTypeModel(targetType);
  1486.                         if (element.Name.Length > 0)
  1487.                             typeModel.TypeDesc.IsMixed = true;
  1488.                         element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty, null);
  1489.                         element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1490.                         element.IsNullable = false;
  1491.                         element.Form = elementFormDefault;
  1492.                        
  1493.                         CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping);
  1494.                         if (!rpc) {
  1495.                             CheckForm(element.Form, ns != element.Namespace);
  1496.                             element = ReconcileLocalAccessor(element, ns);
  1497.                         }
  1498.                         elements.Add(element.Name, element.Namespace, element);
  1499.                         elementList.Add(element);
  1500.                         if (xmlAnyElement.Order != -1) {
  1501.                             if (xmlAnyElement.Order != sequenceId && sequenceId != -1)
  1502.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order"));
  1503.                             sequenceId = xmlAnyElement.Order;
  1504.                         }
  1505.                     }
  1506.                 }
  1507.                 else {
  1508.                     if ((flags & arrayFlags) != 0) {
  1509.                         if ((flags & arrayFlags) != flags)
  1510.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayArrayAttribute));
  1511.                     }
  1512.                    
  1513.                     TypeDesc arrayElementTypeDesc = typeScope.GetTypeDesc(arrayElementType);
  1514.                     if (a.XmlArray == null)
  1515.                         a.XmlArray = CreateArrayAttribute(accessor.TypeDesc);
  1516.                     if (CountAtLevel(a.XmlArrayItems, arrayNestingLevel) == 0)
  1517.                         a.XmlArrayItems.Add(CreateArrayItemAttribute(arrayElementTypeDesc, arrayNestingLevel));
  1518.                     ElementAccessor arrayElement = new ElementAccessor();
  1519.                     arrayElement.Name = XmlConvert.EncodeLocalName(a.XmlArray.ElementName.Length == 0 ? accessorName : a.XmlArray.ElementName);
  1520.                     arrayElement.Namespace = rpc ? null : a.XmlArray.Namespace == null ? ns : a.XmlArray.Namespace;
  1521.                     savedArrayItemAttributes = a.XmlArrayItems;
  1522.                     savedArrayNamespace = arrayElement.Namespace;
  1523.                     ArrayMapping arrayMapping = ImportArrayLikeMapping(modelScope.GetArrayModel(accessorType), ns);
  1524.                     arrayElement.Mapping = arrayMapping;
  1525.                     arrayElement.IsNullable = a.XmlArray.IsNullable;
  1526.                     arrayElement.Form = rpc ? XmlSchemaForm.Unqualified : a.XmlArray.Form == XmlSchemaForm.None ? elementFormDefault : a.XmlArray.Form;
  1527.                     sequenceId = a.XmlArray.Order;
  1528.                     CheckNullable(arrayElement.IsNullable, accessor.TypeDesc, arrayElement.Mapping);
  1529.                     if (!rpc) {
  1530.                         CheckForm(arrayElement.Form, ns != arrayElement.Namespace);
  1531.                         arrayElement = ReconcileLocalAccessor(arrayElement, ns);
  1532.                     }
  1533.                     savedArrayItemAttributes = null;
  1534.                     savedArrayNamespace = null;
  1535.                    
  1536.                     AddUniqueAccessor(elements, arrayElement);
  1537.                     elementList.Add(arrayElement);
  1538.                 }
  1539.             }
  1540.             else if (!accessor.TypeDesc.IsVoid) {
  1541.                 XmlAttributeFlags allFlags = XmlAttributeFlags.Elements | XmlAttributeFlags.Text | XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier | XmlAttributeFlags.XmlnsDeclarations;
  1542.                 if ((flags & allFlags) != flags)
  1543.                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute));
  1544.                
  1545.                 if (accessor.TypeDesc.IsPrimitive || accessor.TypeDesc.IsEnum) {
  1546.                     if (a.XmlAnyElements.Count > 0)
  1547.                         throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, accessor.TypeDesc.FullName));
  1548.                    
  1549.                     if (a.XmlAttribute != null) {
  1550.                         if (a.XmlElements.Count > 0)
  1551.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttribute));
  1552.                         if (a.XmlAttribute.Type != null)
  1553.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlAttribute"));
  1554.                         AttributeAccessor attribute = new AttributeAccessor();
  1555.                         attribute.Name = Accessor.EscapeQName(a.XmlAttribute.AttributeName.Length == 0 ? accessorName : a.XmlAttribute.AttributeName);
  1556.                         attribute.Namespace = a.XmlAttribute.Namespace == null ? ns : a.XmlAttribute.Namespace;
  1557.                         attribute.Form = a.XmlAttribute.Form;
  1558.                         if (attribute.Form == XmlSchemaForm.None && ns != attribute.Namespace) {
  1559.                             attribute.Form = XmlSchemaForm.Qualified;
  1560.                         }
  1561.                         attribute.CheckSpecial();
  1562.                         CheckForm(attribute.Form, ns != attribute.Namespace);
  1563.                         attribute.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Attribute, a.XmlAttribute.DataType, null);
  1564.                         attribute.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1565.                         attribute.Any = a.XmlAnyAttribute != null;
  1566.                         if (attribute.Form == XmlSchemaForm.Qualified && attribute.Namespace != ns) {
  1567.                             if (xsdAttributes == null)
  1568.                                 xsdAttributes = new NameTable();
  1569.                             attribute = (AttributeAccessor)ReconcileAccessor(attribute, xsdAttributes);
  1570.                         }
  1571.                         accessor.Attribute = attribute;
  1572.                     }
  1573.                     else {
  1574.                         if (a.XmlText != null) {
  1575.                             if (a.XmlText.Type != null && a.XmlText.Type != accessorType)
  1576.                                 throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlText"));
  1577.                             TextAccessor text = new TextAccessor();
  1578.                             text.Name = accessorName;
  1579.                             // unused except to make more helpful error messages
  1580.                             text.Mapping = ImportTypeMapping(modelScope.GetTypeModel(accessorType), ns, ImportContext.Text, a.XmlText.DataType, null);
  1581.                             accessor.Text = text;
  1582.                         }
  1583.                         else if (a.XmlElements.Count == 0) {
  1584.                             a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc));
  1585.                         }
  1586.                        
  1587.                         for (int i = 0; i < a.XmlElements.Count; i++) {
  1588.                             XmlElementAttribute xmlElement = a.XmlElements[i];
  1589.                             if (xmlElement.Type != null) {
  1590.                                 if (typeScope.GetTypeDesc(xmlElement.Type) != accessor.TypeDesc)
  1591.                                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalType, "XmlElement"));
  1592.                             }
  1593.                             ElementAccessor element = new ElementAccessor();
  1594.                             element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName);
  1595.                             element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace;
  1596.                             TypeModel typeModel = modelScope.GetTypeModel(accessorType);
  1597.                             element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null);
  1598.                             if (element.Mapping.TypeDesc.Kind == TypeKind.Node) {
  1599.                                 element.Any = true;
  1600.                             }
  1601.                             element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1602.                             if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue)
  1603.                                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement"));
  1604.                             element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue;
  1605.                             element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form;
  1606.                            
  1607.                             CheckNullable(element.IsNullable, accessor.TypeDesc, element.Mapping);
  1608.                             if (!rpc) {
  1609.                                 CheckForm(element.Form, ns != element.Namespace);
  1610.                                 element = ReconcileLocalAccessor(element, ns);
  1611.                             }
  1612.                             if (xmlElement.Order != -1) {
  1613.                                 if (xmlElement.Order != sequenceId && sequenceId != -1)
  1614.                                     throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order"));
  1615.                                 sequenceId = xmlElement.Order;
  1616.                             }
  1617.                             AddUniqueAccessor(elements, element);
  1618.                             elementList.Add(element);
  1619.                         }
  1620.                     }
  1621.                 }
  1622.                 else if (a.Xmlns) {
  1623.                     if (flags != XmlAttributeFlags.XmlnsDeclarations)
  1624.                         throw new InvalidOperationException(Res.GetString(Res.XmlSoleXmlnsAttribute));
  1625.                    
  1626.                     if (accessorType != typeof(XmlSerializerNamespaces)) {
  1627.                         throw new InvalidOperationException(Res.GetString(Res.XmlXmlnsInvalidType, accessorName, accessorType.FullName, typeof(XmlSerializerNamespaces).FullName));
  1628.                     }
  1629.                     accessor.Xmlns = new XmlnsAccessor();
  1630.                     accessor.Ignore = true;
  1631.                 }
  1632.                 else {
  1633.                     if (a.XmlAttribute != null || a.XmlText != null) {
  1634.                         if (accessor.TypeDesc.Kind == TypeKind.Serializable) {
  1635.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrTextInterface, accessorName, accessor.TypeDesc.FullName, typeof(IXmlSerializable).Name));
  1636.                         }
  1637.                         else {
  1638.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAttrOrText, accessorName, accessor.TypeDesc));
  1639.                         }
  1640.                     }
  1641.                     if (a.XmlElements.Count == 0 && a.XmlAnyElements.Count == 0)
  1642.                         a.XmlElements.Add(CreateElementAttribute(accessor.TypeDesc));
  1643.                     for (int i = 0; i < a.XmlElements.Count; i++) {
  1644.                         XmlElementAttribute xmlElement = a.XmlElements[i];
  1645.                         Type targetType = xmlElement.Type == null ? accessorType : xmlElement.Type;
  1646.                         TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1647.                         ElementAccessor element = new ElementAccessor();
  1648.                         TypeModel typeModel = modelScope.GetTypeModel(targetType);
  1649.                         element.Namespace = rpc ? null : xmlElement.Namespace == null ? ns : xmlElement.Namespace;
  1650.                         element.Mapping = ImportTypeMapping(typeModel, rpc ? ns : element.Namespace, ImportContext.Element, xmlElement.DataType, null, false, openModel);
  1651.                         if (a.XmlElements.Count == 1) {
  1652.                             element.Name = XmlConvert.EncodeLocalName(xmlElement.ElementName.Length == 0 ? accessorName : xmlElement.ElementName);
  1653.                         }
  1654.                         else {
  1655.                             element.Name = xmlElement.ElementName.Length == 0 ? element.Mapping.DefaultElementName : XmlConvert.EncodeLocalName(xmlElement.ElementName);
  1656.                         }
  1657.                         element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1658.                         if (xmlElement.IsNullableSpecified && !xmlElement.IsNullable && typeModel.TypeDesc.IsOptionalValue)
  1659.                             throw new InvalidOperationException(Res.GetString(Res.XmlInvalidNotNullable, typeModel.TypeDesc.BaseTypeDesc.FullName, "XmlElement"));
  1660.                         element.IsNullable = xmlElement.IsNullableSpecified ? xmlElement.IsNullable : typeModel.TypeDesc.IsOptionalValue;
  1661.                         element.Form = rpc ? XmlSchemaForm.Unqualified : xmlElement.Form == XmlSchemaForm.None ? elementFormDefault : xmlElement.Form;
  1662.                         CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping);
  1663.                        
  1664.                         if (!rpc) {
  1665.                             CheckForm(element.Form, ns != element.Namespace);
  1666.                             element = ReconcileLocalAccessor(element, ns);
  1667.                         }
  1668.                         if (xmlElement.Order != -1) {
  1669.                             if (xmlElement.Order != sequenceId && sequenceId != -1)
  1670.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order"));
  1671.                             sequenceId = xmlElement.Order;
  1672.                         }
  1673.                         AddUniqueAccessor(elements, element);
  1674.                         elementList.Add(element);
  1675.                     }
  1676.                     NameTable anys = new NameTable();
  1677.                     for (int i = 0; i < a.XmlAnyElements.Count; i++) {
  1678.                         XmlAnyElementAttribute xmlAnyElement = a.XmlAnyElements[i];
  1679.                         Type targetType = typeof(IXmlSerializable).IsAssignableFrom(accessorType) ? accessorType : typeof(XmlNode).IsAssignableFrom(accessorType) ? accessorType : typeof(XmlElement);
  1680.                         if (!accessorType.IsAssignableFrom(targetType))
  1681.                             throw new InvalidOperationException(Res.GetString(Res.XmlIllegalAnyElement, accessorType.FullName));
  1682.                        
  1683.                         string anyName = xmlAnyElement.Name.Length == 0 ? xmlAnyElement.Name : XmlConvert.EncodeLocalName(xmlAnyElement.Name);
  1684.                         string anyNs = xmlAnyElement.NamespaceSpecified ? xmlAnyElement.Namespace : null;
  1685.                         if (anys[anyName, anyNs] != null) {
  1686.                             // ignore duplicate anys
  1687.                             continue;
  1688.                         }
  1689.                         anys[anyName, anyNs] = xmlAnyElement;
  1690.                         if (elements[anyName, (anyNs == null ? ns : anyNs)] != null) {
  1691.                             throw new InvalidOperationException(Res.GetString(Res.XmlAnyElementDuplicate, accessorName, xmlAnyElement.Name, xmlAnyElement.Namespace == null ? "null" : xmlAnyElement.Namespace));
  1692.                         }
  1693.                         ElementAccessor element = new ElementAccessor();
  1694.                         element.Name = anyName;
  1695.                         element.Namespace = anyNs == null ? ns : anyNs;
  1696.                         element.Any = true;
  1697.                         element.AnyNamespaces = anyNs;
  1698.                         TypeDesc targetTypeDesc = typeScope.GetTypeDesc(targetType);
  1699.                         TypeModel typeModel = modelScope.GetTypeModel(targetType);
  1700.                        
  1701.                         if (element.Name.Length > 0)
  1702.                             typeModel.TypeDesc.IsMixed = true;
  1703.                         element.Mapping = ImportTypeMapping(typeModel, element.Namespace, ImportContext.Element, String.Empty, null, false, openModel);
  1704.                         element.Default = GetDefaultValue(model.FieldTypeDesc, model.FieldType, a);
  1705.                         element.IsNullable = false;
  1706.                         element.Form = elementFormDefault;
  1707.                         CheckNullable(element.IsNullable, targetTypeDesc, element.Mapping);
  1708.                         if (!rpc) {
  1709.                             CheckForm(element.Form, ns != element.Namespace);
  1710.                             element = ReconcileLocalAccessor(element, ns);
  1711.                         }
  1712.                         if (xmlAnyElement.Order != -1) {
  1713.                             if (xmlAnyElement.Order != sequenceId && sequenceId != -1)
  1714.                                 throw new InvalidOperationException(Res.GetString(Res.XmlSequenceMatch, "Order"));
  1715.                             sequenceId = xmlAnyElement.Order;
  1716.                         }
  1717.                         elements.Add(element.Name, element.Namespace, element);
  1718.                         elementList.Add(element);
  1719.                     }
  1720.                 }
  1721.             }
  1722.             accessor.Elements = (ElementAccessor[])elementList.ToArray(typeof(ElementAccessor));
  1723.             accessor.SequenceId = sequenceId;
  1724.            
  1725.             if (rpc) {
  1726.                 if (accessor.TypeDesc.IsArrayLike && accessor.Elements.Length > 0 && !(accessor.Elements[0].Mapping is ArrayMapping))
  1727.                     throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitArrayElement, accessor.Elements[0].Name));
  1728.                
  1729.                 if (accessor.Xmlns != null)
  1730.                     throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitXmlns, accessor.Name));
  1731.             }
  1732.            
  1733.             if (accessor.ChoiceIdentifier != null) {
  1734.                 // find the enum value corresponding to each element
  1735.                 accessor.ChoiceIdentifier.MemberIds = new string[accessor.Elements.Length];
  1736.                 for (int i = 0; i < accessor.Elements.Length; i++) {
  1737.                     bool found = false;
  1738.                     ElementAccessor element = accessor.Elements[i];
  1739.                     EnumMapping choiceMapping = (EnumMapping)accessor.ChoiceIdentifier.Mapping;
  1740.                     for (int j = 0; j < choiceMapping.Constants.Length; j++) {
  1741.                         string xmlName = choiceMapping.Constants[j].XmlName;
  1742.                        
  1743.                         if (element.Any && element.Name.Length == 0) {
  1744.                             string anyNs = element.AnyNamespaces == null ? "##any" : element.AnyNamespaces;
  1745.                             if (xmlName.Substring(0, xmlName.Length - 1) == anyNs) {
  1746.                                 accessor.ChoiceIdentifier.MemberIds[i] = choiceMapping.Constants[j].Name;
  1747.                                 found = true;
  1748.                                 break;
  1749.                             }
  1750.                             continue;
  1751.                         }
  1752.                         int colon = xmlName.LastIndexOf(':');
  1753.                         string choiceNs = colon < 0 ? choiceMapping.Namespace : xmlName.Substring(0, colon);
  1754.                         string choiceName = colon < 0 ? xmlName : xmlName.Substring(colon + 1);
  1755.                        
  1756.                         if (element.Name == choiceName) {
  1757.                             if ((element.Form == XmlSchemaForm.Unqualified && string.IsNullOrEmpty(choiceNs)) || element.Namespace == choiceNs) {
  1758.                                 accessor.ChoiceIdentifier.MemberIds[i] = choiceMapping.Constants[j].Name;
  1759.                                 found = true;
  1760.                                 break;
  1761.                             }
  1762.                         }
  1763.                     }
  1764.                     if (!found) {
  1765.                         if (element.Any && element.Name.Length == 0) {
  1766.                             // Type {0} is missing enumeration value '##any' for XmlAnyElementAttribute.
  1767.                             throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingAnyValue, accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName));
  1768.                         }
  1769.                         else {
  1770.                             string id = element.Namespace != null && element.Namespace.Length > 0 ? element.Namespace + ":" + element.Name : element.Name;
  1771.                             // Type {0} is missing value for '{1}'.
  1772.                             throw new InvalidOperationException(Res.GetString(Res.XmlChoiceMissingValue, accessor.ChoiceIdentifier.Mapping.TypeDesc.FullName, id, element.Name, element.Namespace));
  1773.                         }
  1774.                     }
  1775.                 }
  1776.             }
  1777.             arrayNestingLevel = previousNestingLevel;
  1778.             savedArrayItemAttributes = previousArrayItemAttributes;
  1779.             savedArrayNamespace = previousArrayNamespace;
  1780.         }
  1781.        
  1782.        
  1783.         void CheckTopLevelAttributes(XmlAttributes a, string accessorName)
  1784.         {
  1785.             XmlAttributeFlags flags = a.XmlFlags;
  1786.            
  1787.             if ((flags & (XmlAttributeFlags.Attribute | XmlAttributeFlags.AnyAttribute)) != 0)
  1788.                 throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitAttributeAttributes));
  1789.            
  1790.             if ((flags & (XmlAttributeFlags.Text | XmlAttributeFlags.AnyElements | XmlAttributeFlags.ChoiceIdentifier)) != 0)
  1791.                 throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitAttributes));
  1792.            
  1793.             if (a.XmlElements != null && a.XmlElements.Count > 0) {
  1794.                 if (a.XmlElements.Count > 1) {
  1795.                     throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitElements));
  1796.                 }
  1797.                 XmlElementAttribute xmlElement = a.XmlElements[0];
  1798.                 if (xmlElement.Namespace != null) {
  1799.                     throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitElementNamespace, "Namespace", xmlElement.Namespace));
  1800.                 }
  1801.                 if (xmlElement.IsNullable) {
  1802.                     throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitElementNullable, "IsNullable", "true"));
  1803.                 }
  1804.             }
  1805.             if (a.XmlArray != null && a.XmlArray.Namespace != null) {
  1806.                 throw new InvalidOperationException(Res.GetString(Res.XmlRpcLitElementNamespace, "Namespace", a.XmlArray.Namespace));
  1807.             }
  1808.         }
  1809.        
  1810.         void CheckAmbiguousChoice(XmlAttributes a, Type accessorType, string accessorName)
  1811.         {
  1812.             Hashtable choiceTypes = new Hashtable();
  1813.            
  1814.             XmlElementAttributes elements = a.XmlElements;
  1815.             if (elements != null && elements.Count >= 2 && a.XmlChoiceIdentifier == null) {
  1816.                 for (int i = 0; i < elements.Count; i++) {
  1817.                     Type type = elements[i].Type == null ? accessorType : elements[i].Type;
  1818.                     if (choiceTypes.Contains(type)) {
  1819.                         // You need to add {0} to the '{1}'.
  1820.                         throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferMissing, typeof(XmlChoiceIdentifierAttribute).Name, accessorName));
  1821.                     }
  1822.                     else {
  1823.                         choiceTypes.Add(type, false);
  1824.                     }
  1825.                 }
  1826.             }
  1827.             if (choiceTypes.Contains(typeof(XmlElement)) && a.XmlAnyElements.Count > 0) {
  1828.                 // You need to add {0} to the '{1}'.
  1829.                 throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdentiferMissing, typeof(XmlChoiceIdentifierAttribute).Name, accessorName));
  1830.             }
  1831.            
  1832.             XmlArrayItemAttributes items = a.XmlArrayItems;
  1833.             if (items != null && items.Count >= 2) {
  1834.                 NameTable arrayTypes = new NameTable();
  1835.                
  1836.                 for (int i = 0; i < items.Count; i++) {
  1837.                     Type type = items[i].Type == null ? accessorType : items[i].Type;
  1838.                     string ns = items[i].NestingLevel.ToString(CultureInfo.InvariantCulture);
  1839.                     XmlArrayItemAttribute item = (XmlArrayItemAttribute)arrayTypes[type.FullName, ns];
  1840.                     if (item != null) {
  1841.                         throw new InvalidOperationException(Res.GetString(Res.XmlArrayItemAmbiguousTypes, accessorName, item.ElementName, items[i].ElementName, typeof(XmlElementAttribute).Name, typeof(XmlChoiceIdentifierAttribute).Name, accessorName));
  1842.                     }
  1843.                     else {
  1844.                         arrayTypes[type.FullName, ns] = items[i];
  1845.                     }
  1846.                 }
  1847.             }
  1848.         }
  1849.        
  1850.         void CheckChoiceIdentifierMapping(EnumMapping choiceMapping)
  1851.         {
  1852.             NameTable ids = new NameTable();
  1853.             for (int i = 0; i < choiceMapping.Constants.Length; i++) {
  1854.                 string choiceId = choiceMapping.Constants[i].XmlName;
  1855.                 int colon = choiceId.LastIndexOf(':');
  1856.                 string choiceName = colon < 0 ? choiceId : choiceId.Substring(colon + 1);
  1857.                 string choiceNs = colon < 0 ? "" : choiceId.Substring(0, colon);
  1858.                
  1859.                 if (ids[choiceName, choiceNs] != null) {
  1860.                     // Enum values in the XmlChoiceIdentifier '{0}' have to be unique. Value '{1}' already present.
  1861.                     throw new InvalidOperationException(Res.GetString(Res.XmlChoiceIdDuplicate, choiceMapping.TypeName, choiceId));
  1862.                 }
  1863.                 ids.Add(choiceName, choiceNs, choiceMapping.Constants[i]);
  1864.             }
  1865.         }
  1866.        
  1867.         object GetDefaultValue(TypeDesc fieldTypeDesc, Type t, XmlAttributes a)
  1868.         {
  1869.             if (a.XmlDefaultValue == null || a.XmlDefaultValue == DBNull.Value)
  1870.                 return null;
  1871.             if (!(fieldTypeDesc.Kind == TypeKind.Primitive || fieldTypeDesc.Kind == TypeKind.Enum)) {
  1872.                 //throw new InvalidOperationException(Res.GetString(Res.XmlIllegalDefault));
  1873.                 a.XmlDefaultValue = null;
  1874.                 return a.XmlDefaultValue;
  1875.             }
  1876.             // for enums validate and return a string representation
  1877.             if (fieldTypeDesc.Kind == TypeKind.Enum) {
  1878.                 string strValue = Enum.Format(t, a.XmlDefaultValue, "G").Replace(",", " ");
  1879.                 string numValue = Enum.Format(t, a.XmlDefaultValue, "D");
  1880.                 if (strValue == numValue)
  1881.                     // means enum value wasn't recognized
  1882.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultValue, strValue, a.XmlDefaultValue.GetType().FullName));
  1883.                 return strValue;
  1884.             }
  1885.             return a.XmlDefaultValue;
  1886.         }
  1887.        
  1888.         static XmlArrayItemAttribute CreateArrayItemAttribute(TypeDesc typeDesc, int nestingLevel)
  1889.         {
  1890.             XmlArrayItemAttribute xmlArrayItem = new XmlArrayItemAttribute();
  1891.             xmlArrayItem.NestingLevel = nestingLevel;
  1892.             return xmlArrayItem;
  1893.         }
  1894.        
  1895.         static XmlArrayAttribute CreateArrayAttribute(TypeDesc typeDesc)
  1896.         {
  1897.             XmlArrayAttribute xmlArrayItem = new XmlArrayAttribute();
  1898.             return xmlArrayItem;
  1899.         }
  1900.        
  1901.         static XmlElementAttribute CreateElementAttribute(TypeDesc typeDesc)
  1902.         {
  1903.             XmlElementAttribute xmlElement = new XmlElementAttribute();
  1904.             xmlElement.IsNullable = typeDesc.IsOptionalValue;
  1905.             return xmlElement;
  1906.         }
  1907.        
  1908.         static void AddUniqueAccessor(INameScope scope, Accessor accessor)
  1909.         {
  1910.             Accessor existing = (Accessor)scope[accessor.Name, accessor.Namespace];
  1911.             if (existing != null) {
  1912.                 if (accessor is ElementAccessor) {
  1913.                     throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateElementName, existing.Name, existing.Namespace));
  1914.                 }
  1915.                 else {
  1916.                     #if DEBUG
  1917.                     if (!(accessor is AttributeAccessor))
  1918.                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Bad accessor type " + accessor.GetType().FullName));
  1919.                     #endif
  1920.                     throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateAttributeName, existing.Name, existing.Namespace));
  1921.                 }
  1922.             }
  1923.             else {
  1924.                 scope[accessor.Name, accessor.Namespace] = accessor;
  1925.             }
  1926.         }
  1927.        
  1928.         static void AddUniqueAccessor(MemberMapping member, INameScope elements, INameScope attributes, bool isSequence)
  1929.         {
  1930.             if (member.Attribute != null) {
  1931.                 AddUniqueAccessor(attributes, member.Attribute);
  1932.             }
  1933.             else if (!isSequence && member.Elements != null && member.Elements.Length > 0) {
  1934.                 for (int i = 0; i < member.Elements.Length; i++) {
  1935.                     AddUniqueAccessor(elements, member.Elements[i]);
  1936.                 }
  1937.             }
  1938.         }
  1939.        
  1940.         static void CheckForm(XmlSchemaForm form, bool isQualified)
  1941.         {
  1942.             if (isQualified && form == XmlSchemaForm.Unqualified)
  1943.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidFormUnqualified));
  1944.         }
  1945.        
  1946.         static void CheckNullable(bool isNullable, TypeDesc typeDesc, TypeMapping mapping)
  1947.         {
  1948.             if (mapping is NullableMapping)
  1949.                 return;
  1950.             if (mapping is SerializableMapping)
  1951.                 return;
  1952.             if (isNullable && !typeDesc.IsNullable)
  1953.                 throw new InvalidOperationException(Res.GetString(Res.XmlInvalidIsNullable, typeDesc.FullName));
  1954.         }
  1955.        
  1956.         static ElementAccessor CreateElementAccessor(TypeMapping mapping, string ns)
  1957.         {
  1958.             ElementAccessor element = new ElementAccessor();
  1959.             bool isAny = mapping.TypeDesc.Kind == TypeKind.Node;
  1960.             if (!isAny && mapping is SerializableMapping) {
  1961.                 isAny = ((SerializableMapping)mapping).IsAny;
  1962.             }
  1963.             if (isAny) {
  1964.                 element.Any = true;
  1965.             }
  1966.             else {
  1967.                 element.Name = mapping.DefaultElementName;
  1968.                 element.Namespace = ns;
  1969.             }
  1970.             element.Mapping = mapping;
  1971.             return element;
  1972.         }
  1973.        
  1974.         // will create a shallow type mapping for a top-level type
  1975.         static internal XmlTypeMapping GetTopLevelMapping(Type type, string defaultNamespace)
  1976.         {
  1977.             XmlAttributes a = new XmlAttributes(type);
  1978.             TypeDesc typeDesc = new TypeScope().GetTypeDesc(type);
  1979.             ElementAccessor element = new ElementAccessor();
  1980.            
  1981.             if (typeDesc.Kind == TypeKind.Node) {
  1982.                 element.Any = true;
  1983.             }
  1984.             else {
  1985.                 string ns = a.XmlRoot == null ? defaultNamespace : a.XmlRoot.Namespace;
  1986.                 string typeName = string.Empty;
  1987.                 if (a.XmlType != null)
  1988.                     typeName = a.XmlType.TypeName;
  1989.                 if (typeName.Length == 0)
  1990.                     typeName = type.Name;
  1991.                
  1992.                 element.Name = XmlConvert.EncodeLocalName(typeName);
  1993.                 element.Namespace = ns;
  1994.             }
  1995.             XmlTypeMapping mapping = new XmlTypeMapping(null, element);
  1996.             mapping.SetKeyInternal(XmlMapping.GenerateKey(type, a.XmlRoot, defaultNamespace));
  1997.             return mapping;
  1998.         }
  1999.     }
  2000. }

Developer Fusion