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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Mappings.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.Collections;
  21.     using System.Xml.Schema;
  22.     using System;
  23.     using System.Text;
  24.     using System.ComponentModel;
  25.     using System.Xml;
  26.     using System.CodeDom.Compiler;
  27.    
  28.     // These classes represent a mapping between classes and a particular XML format.
  29.     // There are two class of mapping information: accessors (such as elements and
  30.     // attributes), and mappings (which specify the type of an accessor).
  31.    
  32.     internal abstract class Accessor
  33.     {
  34.         string name;
  35.         object defaultValue = null;
  36.         string ns;
  37.         TypeMapping mapping;
  38.         bool any;
  39.         string anyNs;
  40.         bool topLevelInSchema;
  41.         bool isFixed;
  42.         bool isOptional;
  43.         XmlSchemaForm form = XmlSchemaForm.None;
  44.        
  45.         internal Accessor()
  46.         {
  47.         }
  48.        
  49.         internal TypeMapping Mapping {
  50.             get { return mapping; }
  51.             set { mapping = value; }
  52.         }
  53.        
  54.         internal object Default {
  55.             get { return defaultValue; }
  56.             set { defaultValue = value; }
  57.         }
  58.        
  59.         internal bool HasDefault {
  60.             get { return defaultValue != null && defaultValue != DBNull.Value; }
  61.         }
  62.        
  63.         internal virtual string Name {
  64.             get { return name == null ? string.Empty : name; }
  65.             set { name = value; }
  66.         }
  67.        
  68.         internal bool Any {
  69.             get { return any; }
  70.             set { any = value; }
  71.         }
  72.        
  73.         internal string AnyNamespaces {
  74.             get { return anyNs; }
  75.             set { anyNs = value; }
  76.         }
  77.        
  78.         internal string Namespace {
  79.             get { return ns; }
  80.             set { ns = value; }
  81.         }
  82.        
  83.         internal XmlSchemaForm Form {
  84.             get { return form; }
  85.             set { form = value; }
  86.         }
  87.        
  88.         internal bool IsFixed {
  89.             get { return isFixed; }
  90.             set { isFixed = value; }
  91.         }
  92.        
  93.         internal bool IsOptional {
  94.             get { return isOptional; }
  95.             set { isOptional = value; }
  96.         }
  97.        
  98.         internal bool IsTopLevelInSchema {
  99.             get { return topLevelInSchema; }
  100.             set { topLevelInSchema = value; }
  101.         }
  102.        
  103.         static internal string EscapeName(string name)
  104.         {
  105.             if (name == null || name.Length == 0)
  106.                 return name;
  107.             return XmlConvert.EncodeLocalName(name);
  108.         }
  109.        
  110.         static internal string EscapeQName(string name)
  111.         {
  112.             if (name == null || name.Length == 0)
  113.                 return name;
  114.             int colon = name.LastIndexOf(':');
  115.             if (colon < 0)
  116.                 return XmlConvert.EncodeLocalName(name);
  117.             else {
  118.                 if (colon == 0 || colon == name.Length - 1)
  119.                     throw new ArgumentException(Res.GetString(Res.Xml_InvalidNameChars, name), "name");
  120.                 return new XmlQualifiedName(XmlConvert.EncodeLocalName(name.Substring(colon + 1)), XmlConvert.EncodeLocalName(name.Substring(0, colon))).ToString();
  121.             }
  122.         }
  123.        
  124.         static internal string UnescapeName(string name)
  125.         {
  126.             return XmlConvert.DecodeName(name);
  127.         }
  128.        
  129.         internal string ToString(string defaultNs)
  130.         {
  131.             if (Any) {
  132.                 return (Namespace == null ? "##any" : Namespace) + ":" + Name;
  133.             }
  134.             else {
  135.                 return Namespace == defaultNs ? Name : Namespace + ":" + Name;
  136.             }
  137.         }
  138.     }
  139.    
  140.     internal class ElementAccessor : Accessor
  141.     {
  142.         bool nullable;
  143.         bool isSoap;
  144.         bool unbounded = false;
  145.        
  146.         internal bool IsSoap {
  147.             get { return isSoap; }
  148.             set { isSoap = value; }
  149.         }
  150.        
  151.         internal bool IsNullable {
  152.             get { return nullable; }
  153.             set { nullable = value; }
  154.         }
  155.        
  156.         internal bool IsUnbounded {
  157.             get { return unbounded; }
  158.             set { unbounded = value; }
  159.         }
  160.        
  161.         internal ElementAccessor Clone()
  162.         {
  163.             ElementAccessor newAccessor = new ElementAccessor();
  164.             newAccessor.nullable = this.nullable;
  165.             newAccessor.IsTopLevelInSchema = this.IsTopLevelInSchema;
  166.             newAccessor.Form = this.Form;
  167.             newAccessor.isSoap = this.isSoap;
  168.             newAccessor.Name = this.Name;
  169.             newAccessor.Default = this.Default;
  170.             newAccessor.Namespace = this.Namespace;
  171.             newAccessor.Mapping = this.Mapping;
  172.             newAccessor.Any = this.Any;
  173.            
  174.             return newAccessor;
  175.         }
  176.     }
  177.    
  178.     internal class ChoiceIdentifierAccessor : Accessor
  179.     {
  180.         string memberName;
  181.         string[] memberIds;
  182.        
  183.         internal string MemberName {
  184.             get { return memberName; }
  185.             set { memberName = value; }
  186.         }
  187.        
  188.         internal string[] MemberIds {
  189.             get { return memberIds; }
  190.             set { memberIds = value; }
  191.         }
  192.        
  193.     }
  194.    
  195.     internal class TextAccessor : Accessor
  196.     {
  197.     }
  198.    
  199.     internal class XmlnsAccessor : Accessor
  200.     {
  201.     }
  202.    
  203.     internal class AttributeAccessor : Accessor
  204.     {
  205.         bool isSpecial;
  206.         bool isList;
  207.        
  208.         internal bool IsSpecialXmlNamespace {
  209.             get { return isSpecial; }
  210.         }
  211.        
  212.         internal bool IsList {
  213.             get { return isList; }
  214.             set { isList = value; }
  215.         }
  216.        
  217.         internal void CheckSpecial()
  218.         {
  219.             int colon = Name.LastIndexOf(':');
  220.            
  221.             if (colon >= 0) {
  222.                 if (!Name.StartsWith("xml:", StringComparison.Ordinal)) {
  223.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidNameChars, Name));
  224.                 }
  225.                 Name = Name.Substring("xml:".Length);
  226.                 Namespace = XmlReservedNs.NsXml;
  227.                 isSpecial = true;
  228.             }
  229.             else {
  230.                 if (Namespace == XmlReservedNs.NsXml) {
  231.                     isSpecial = true;
  232.                 }
  233.                 else {
  234.                     isSpecial = false;
  235.                 }
  236.             }
  237.             if (isSpecial) {
  238.                 Form = XmlSchemaForm.Qualified;
  239.             }
  240.         }
  241.     }
  242.    
  243.     internal abstract class Mapping
  244.     {
  245.         bool isSoap;
  246.        
  247.         internal Mapping()
  248.         {
  249.         }
  250.        
  251.         internal bool IsSoap {
  252.             get { return isSoap; }
  253.             set { isSoap = value; }
  254.         }
  255.     }
  256.    
  257.     internal abstract class TypeMapping : Mapping
  258.     {
  259.         TypeDesc typeDesc;
  260.         string typeNs;
  261.         string typeName;
  262.         bool referencedByElement;
  263.         bool referencedByTopLevelElement;
  264.         bool includeInSchema = true;
  265.         bool reference = false;
  266.        
  267.         internal bool ReferencedByTopLevelElement {
  268.             get { return referencedByTopLevelElement; }
  269.             set { referencedByTopLevelElement = value; }
  270.         }
  271.        
  272.         internal bool ReferencedByElement {
  273.             get { return referencedByElement || referencedByTopLevelElement; }
  274.             set { referencedByElement = value; }
  275.         }
  276.         internal string Namespace {
  277.             get { return typeNs; }
  278.             set { typeNs = value; }
  279.         }
  280.        
  281.         internal string TypeName {
  282.             get { return typeName; }
  283.             set { typeName = value; }
  284.         }
  285.        
  286.         internal TypeDesc TypeDesc {
  287.             get { return typeDesc; }
  288.             set { typeDesc = value; }
  289.         }
  290.        
  291.         internal bool IncludeInSchema {
  292.             get { return includeInSchema; }
  293.             set { includeInSchema = value; }
  294.         }
  295.        
  296.         internal virtual bool IsList {
  297.             get { return false; }
  298.             set { }
  299.         }
  300.        
  301.         internal bool IsReference {
  302.             get { return reference; }
  303.             set { reference = value; }
  304.         }
  305.        
  306.         internal bool IsAnonymousType {
  307.             get { return typeName == null || typeName.Length == 0; }
  308.         }
  309.        
  310.         internal virtual string DefaultElementName {
  311.             get { return IsAnonymousType ? XmlConvert.EncodeLocalName(typeDesc.Name) : typeName; }
  312.         }
  313.     }
  314.    
  315.     internal class PrimitiveMapping : TypeMapping
  316.     {
  317.         bool isList;
  318.        
  319.         internal override bool IsList {
  320.             get { return isList; }
  321.             set { isList = value; }
  322.         }
  323.     }
  324.    
  325.     internal class NullableMapping : TypeMapping
  326.     {
  327.         TypeMapping baseMapping;
  328.        
  329.         internal TypeMapping BaseMapping {
  330.             get { return baseMapping; }
  331.             set { baseMapping = value; }
  332.         }
  333.        
  334.         internal override string DefaultElementName {
  335.             get { return BaseMapping.DefaultElementName; }
  336.         }
  337.     }
  338.    
  339.     internal class ArrayMapping : TypeMapping
  340.     {
  341.         ElementAccessor[] elements;
  342.         ElementAccessor[] sortedElements;
  343.         ArrayMapping next;
  344.         StructMapping topLevelMapping;
  345.        
  346.         internal ElementAccessor[] Elements {
  347.             get { return elements; }
  348.             set {
  349.                 elements = value;
  350.                 sortedElements = null;
  351.             }
  352.         }
  353.        
  354.         internal ElementAccessor[] ElementsSortedByDerivation {
  355.             get {
  356.                 if (sortedElements != null)
  357.                     return sortedElements;
  358.                 if (elements == null)
  359.                     return null;
  360.                 sortedElements = new ElementAccessor[elements.Length];
  361.                 Array.Copy(elements, 0, sortedElements, 0, elements.Length);
  362.                 AccessorMapping.SortMostToLeastDerived(sortedElements);
  363.                 return sortedElements;
  364.             }
  365.         }
  366.        
  367.        
  368.         internal ArrayMapping Next {
  369.             get { return next; }
  370.             set { next = value; }
  371.         }
  372.        
  373.         internal StructMapping TopLevelMapping {
  374.             get { return topLevelMapping; }
  375.             set { topLevelMapping = value; }
  376.         }
  377.     }
  378.    
  379.     internal class EnumMapping : PrimitiveMapping
  380.     {
  381.         ConstantMapping[] constants;
  382.         bool isFlags;
  383.        
  384.         internal bool IsFlags {
  385.             get { return isFlags; }
  386.             set { isFlags = value; }
  387.         }
  388.        
  389.         internal ConstantMapping[] Constants {
  390.             get { return constants; }
  391.             set { constants = value; }
  392.         }
  393.     }
  394.    
  395.     internal class ConstantMapping : Mapping
  396.     {
  397.         string xmlName;
  398.         string name;
  399.         long value;
  400.        
  401.         internal string XmlName {
  402.             get { return xmlName == null ? string.Empty : xmlName; }
  403.             set { xmlName = value; }
  404.         }
  405.        
  406.         internal string Name {
  407.             get { return name == null ? string.Empty : name; }
  408.             set { this.name = value; }
  409.         }
  410.        
  411.         internal long Value {
  412.             get { return value; }
  413.             set { this.value = value; }
  414.         }
  415.     }
  416.    
  417.     internal class StructMapping : TypeMapping, INameScope
  418.     {
  419.         MemberMapping[] members;
  420.         StructMapping baseMapping;
  421.         StructMapping derivedMappings;
  422.         StructMapping nextDerivedMapping;
  423.         MemberMapping xmlnsMember = null;
  424.         bool hasSimpleContent;
  425.         bool openModel;
  426.         NameTable elements;
  427.         NameTable attributes;
  428.         CodeIdentifiers scope;
  429.        
  430.         internal StructMapping BaseMapping {
  431.             get { return baseMapping; }
  432.             set {
  433.                 baseMapping = value;
  434.                 if (!IsAnonymousType && baseMapping != null) {
  435.                     nextDerivedMapping = baseMapping.derivedMappings;
  436.                     baseMapping.derivedMappings = this;
  437.                 }
  438.             }
  439.         }
  440.        
  441.         internal StructMapping DerivedMappings {
  442.             get { return derivedMappings; }
  443.         }
  444.        
  445.         internal NameTable LocalElements {
  446.             get {
  447.                 if (elements == null)
  448.                     elements = new NameTable();
  449.                 return elements;
  450.             }
  451.         }
  452.         internal NameTable LocalAttributes {
  453.             get {
  454.                 if (attributes == null)
  455.                     attributes = new NameTable();
  456.                 return attributes;
  457.             }
  458.         }
  459.         object INameScope.this[string name, string ns]
  460.         {
  461.             get {
  462.                 object named = LocalElements[name, ns];
  463.                 if (named != null)
  464.                     return named;
  465.                 if (baseMapping != null)
  466.                     return ((INameScope)baseMapping)[name, ns];
  467.                 return null;
  468.             }
  469.             set { LocalElements[name, ns] = value; }
  470.         }
  471.         internal StructMapping NextDerivedMapping {
  472.             get { return nextDerivedMapping; }
  473.         }
  474.        
  475.         internal bool HasSimpleContent {
  476.             get { return hasSimpleContent; }
  477.         }
  478.        
  479.         internal bool HasXmlnsMember {
  480.             get {
  481.                 StructMapping mapping = this;
  482.                 while (mapping != null) {
  483.                     if (mapping.XmlnsMember != null)
  484.                         return true;
  485.                     mapping = mapping.BaseMapping;
  486.                 }
  487.                 return false;
  488.             }
  489.         }
  490.        
  491.         internal MemberMapping[] Members {
  492.             get { return members; }
  493.             set { members = value; }
  494.         }
  495.        
  496.         internal MemberMapping XmlnsMember {
  497.             get { return xmlnsMember; }
  498.             set { xmlnsMember = value; }
  499.         }
  500.        
  501.         internal bool IsOpenModel {
  502.             get { return openModel; }
  503.             set { openModel = value; }
  504.         }
  505.        
  506.         internal CodeIdentifiers Scope {
  507.             get {
  508.                 if (scope == null)
  509.                     scope = new CodeIdentifiers();
  510.                 return scope;
  511.             }
  512.             set { scope = value; }
  513.         }
  514.        
  515.         internal MemberMapping FindDeclaringMapping(MemberMapping member, out StructMapping declaringMapping, string parent)
  516.         {
  517.             declaringMapping = null;
  518.             if (BaseMapping != null) {
  519.                 MemberMapping baseMember = BaseMapping.FindDeclaringMapping(member, out declaringMapping, parent);
  520.                 if (baseMember != null)
  521.                     return baseMember;
  522.             }
  523.             if (members == null)
  524.                 return null;
  525.            
  526.             for (int i = 0; i < members.Length; i++) {
  527.                 if (members[i].Name == member.Name) {
  528.                     if (members[i].TypeDesc != member.TypeDesc)
  529.                         throw new InvalidOperationException(Res.GetString(Res.XmlHiddenMember, parent, member.Name, member.TypeDesc.FullName, this.TypeName, members[i].Name, members[i].TypeDesc.FullName));
  530.                     else if (!members[i].Match(member)) {
  531.                         throw new InvalidOperationException(Res.GetString(Res.XmlInvalidXmlOverride, parent, member.Name, this.TypeName, members[i].Name));
  532.                     }
  533.                     declaringMapping = this;
  534.                     return members[i];
  535.                 }
  536.             }
  537.             return null;
  538.         }
  539.         internal bool Declares(MemberMapping member, string parent)
  540.         {
  541.             StructMapping m;
  542.             return (FindDeclaringMapping(member, out m, parent) != null);
  543.         }
  544.        
  545.         internal void SetContentModel(TextAccessor text, bool hasElements)
  546.         {
  547.             if (BaseMapping == null || BaseMapping.TypeDesc.IsRoot) {
  548.                 hasSimpleContent = !hasElements && text != null && !text.Mapping.IsList;
  549.             }
  550.             else if (BaseMapping.HasSimpleContent) {
  551.                 if (text != null || hasElements) {
  552.                     // we can only extent a simleContent type with attributes
  553.                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalSimpleContentExtension, TypeDesc.FullName, BaseMapping.TypeDesc.FullName));
  554.                 }
  555.                 else {
  556.                     hasSimpleContent = true;
  557.                 }
  558.             }
  559.             else {
  560.                 hasSimpleContent = false;
  561.             }
  562.             if (!hasSimpleContent && text != null && !text.Mapping.TypeDesc.CanBeTextValue) {
  563.                 throw new InvalidOperationException(Res.GetString(Res.XmlIllegalTypedTextAttribute, TypeDesc.FullName, text.Name, text.Mapping.TypeDesc.FullName));
  564.             }
  565.         }
  566.        
  567.         internal bool HasElements {
  568.             get { return elements != null && elements.Values.Count > 0; }
  569.         }
  570.        
  571.         internal bool HasExplicitSequence()
  572.         {
  573.             if (members != null) {
  574.                 for (int i = 0; i < members.Length; i++) {
  575.                     if (members[i].IsParticle && members[i].IsSequence) {
  576.                         return true;
  577.                     }
  578.                 }
  579.             }
  580.             return (baseMapping != null && baseMapping.HasExplicitSequence());
  581.         }
  582.        
  583.         internal void SetSequence()
  584.         {
  585.             for (int i = 0; i < members.Length; i++) {
  586.                 if (members[i].IsParticle) {
  587.                     members[i].SequenceId = i;
  588.                 }
  589.             }
  590.             if (baseMapping != null) {
  591.                 baseMapping.SetSequence();
  592.             }
  593.         }
  594.     }
  595.    
  596.     internal abstract class AccessorMapping : Mapping
  597.     {
  598.         TypeDesc typeDesc;
  599.         AttributeAccessor attribute;
  600.         ElementAccessor[] elements;
  601.         ElementAccessor[] sortedElements;
  602.         TextAccessor text;
  603.         ChoiceIdentifierAccessor choiceIdentifier;
  604.         XmlnsAccessor xmlns;
  605.         bool ignore;
  606.        
  607.         internal bool IsAttribute {
  608.             get { return attribute != null; }
  609.         }
  610.        
  611.         internal bool IsText {
  612.             get { return text != null && (elements == null || elements.Length == 0); }
  613.         }
  614.        
  615.         internal bool IsParticle {
  616.             get { return (elements != null && elements.Length > 0); }
  617.         }
  618.        
  619.         internal TypeDesc TypeDesc {
  620.             get { return typeDesc; }
  621.             set { typeDesc = value; }
  622.         }
  623.        
  624.         internal AttributeAccessor Attribute {
  625.             get { return attribute; }
  626.             set { attribute = value; }
  627.         }
  628.        
  629.         internal ElementAccessor[] Elements {
  630.             get { return elements; }
  631.             set {
  632.                 elements = value;
  633.                 sortedElements = null;
  634.             }
  635.         }
  636.        
  637.         static internal void SortMostToLeastDerived(ElementAccessor[] elements)
  638.         {
  639.             Array.Sort(elements, new AccessorComparer());
  640.         }
  641.        
  642.         internal class AccessorComparer : IComparer
  643.         {
  644.             public int Compare(object o1, object o2)
  645.             {
  646.                 if (o1 == o2)
  647.                     return 0;
  648.                 Accessor a1 = (Accessor)o1;
  649.                 Accessor a2 = (Accessor)o2;
  650.                 int w1 = a1.Mapping.TypeDesc.Weight;
  651.                 int w2 = a2.Mapping.TypeDesc.Weight;
  652.                 if (w1 == w2)
  653.                     return 0;
  654.                 if (w1 < w2)
  655.                     return 1;
  656.                 return -1;
  657.             }
  658.         }
  659.        
  660.         internal ElementAccessor[] ElementsSortedByDerivation {
  661.             get {
  662.                 if (sortedElements != null)
  663.                     return sortedElements;
  664.                 if (elements == null)
  665.                     return null;
  666.                 sortedElements = new ElementAccessor[elements.Length];
  667.                 Array.Copy(elements, 0, sortedElements, 0, elements.Length);
  668.                 SortMostToLeastDerived(sortedElements);
  669.                 return sortedElements;
  670.             }
  671.         }
  672.        
  673.         internal TextAccessor Text {
  674.             get { return text; }
  675.             set { text = value; }
  676.         }
  677.        
  678.         internal ChoiceIdentifierAccessor ChoiceIdentifier {
  679.             get { return choiceIdentifier; }
  680.             set { choiceIdentifier = value; }
  681.         }
  682.        
  683.         internal XmlnsAccessor Xmlns {
  684.             get { return xmlns; }
  685.             set { xmlns = value; }
  686.         }
  687.        
  688.         internal bool Ignore {
  689.             get { return ignore; }
  690.             set { ignore = value; }
  691.         }
  692.        
  693.         internal Accessor Accessor {
  694.             get {
  695.                 if (xmlns != null)
  696.                     return xmlns;
  697.                 if (attribute != null)
  698.                     return attribute;
  699.                 if (elements != null && elements.Length > 0)
  700.                     return elements[0];
  701.                 return text;
  702.             }
  703.         }
  704.        
  705.         static bool IsNeedNullableMember(ElementAccessor element)
  706.         {
  707.             if (element.Mapping is ArrayMapping) {
  708.                 ArrayMapping arrayMapping = (ArrayMapping)element.Mapping;
  709.                 if (arrayMapping.Elements != null && arrayMapping.Elements.Length == 1) {
  710.                     return IsNeedNullableMember(arrayMapping.Elements[0]);
  711.                 }
  712.                 return false;
  713.             }
  714.             else {
  715.                 return element.IsNullable && element.Mapping.TypeDesc.IsValueType;
  716.             }
  717.         }
  718.        
  719.         internal bool IsNeedNullable {
  720.             get {
  721.                 if (xmlns != null)
  722.                     return false;
  723.                 if (attribute != null)
  724.                     return false;
  725.                 if (elements != null && elements.Length == 1) {
  726.                     return IsNeedNullableMember(elements[0]);
  727.                 }
  728.                 return false;
  729.             }
  730.         }
  731.        
  732.         static internal bool ElementsMatch(ElementAccessor[] a, ElementAccessor[] b)
  733.         {
  734.             if (a == null) {
  735.                 if (b == null)
  736.                     return true;
  737.                 return false;
  738.             }
  739.             if (b == null)
  740.                 return false;
  741.             if (a.Length != b.Length)
  742.                 return false;
  743.             for (int i = 0; i < a.Length; i++) {
  744.                 if (a[i].Name != b[i].Name || a[i].Namespace != b[i].Namespace || a[i].Form != b[i].Form || a[i].IsNullable != b[i].IsNullable)
  745.                     return false;
  746.             }
  747.             return true;
  748.         }
  749.        
  750.         internal bool Match(AccessorMapping mapping)
  751.         {
  752.             if (Elements != null && Elements.Length > 0) {
  753.                 if (!ElementsMatch(Elements, mapping.Elements)) {
  754.                     return false;
  755.                 }
  756.                 if (Text == null) {
  757.                     return (mapping.Text == null);
  758.                 }
  759.             }
  760.             if (Attribute != null) {
  761.                 if (mapping.Attribute == null)
  762.                     return false;
  763.                 return (Attribute.Name == mapping.Attribute.Name && Attribute.Namespace == mapping.Attribute.Namespace && Attribute.Form == mapping.Attribute.Form);
  764.             }
  765.             if (Text != null) {
  766.                 return (mapping.Text != null);
  767.             }
  768.             return (mapping.Accessor == null);
  769.         }
  770.     }
  771.    
  772.     internal class MemberMappingComparer : IComparer
  773.     {
  774.         public int Compare(object o1, object o2)
  775.         {
  776.             MemberMapping m1 = (MemberMapping)o1;
  777.             MemberMapping m2 = (MemberMapping)o2;
  778.            
  779.             bool m1Text = m1.IsText;
  780.             if (m1Text) {
  781.                 if (m2.IsText)
  782.                     return 0;
  783.                 return 1;
  784.             }
  785.             else if (m2.IsText)
  786.                 return -1;
  787.            
  788.             if (m1.SequenceId < 0 && m2.SequenceId < 0)
  789.                 return 0;
  790.             if (m1.SequenceId < 0)
  791.                 return 1;
  792.             if (m2.SequenceId < 0)
  793.                 return -1;
  794.             if (m1.SequenceId < m2.SequenceId)
  795.                 return -1;
  796.             if (m1.SequenceId > m2.SequenceId)
  797.                 return 1;
  798.             return 0;
  799.         }
  800.     }
  801.    
  802.     internal class MemberMapping : AccessorMapping
  803.     {
  804.         string name;
  805.         bool checkShouldPersist;
  806.         bool checkSpecified;
  807.         bool isReturnValue;
  808.         bool readOnly = false;
  809.         int sequenceId = -1;
  810.        
  811.         internal bool CheckShouldPersist {
  812.             get { return checkShouldPersist; }
  813.             set { checkShouldPersist = value; }
  814.         }
  815.        
  816.         internal bool CheckSpecified {
  817.             get { return checkSpecified; }
  818.             set { checkSpecified = value; }
  819.         }
  820.        
  821.         internal string Name {
  822.             get { return name == null ? string.Empty : name; }
  823.             set { name = value; }
  824.         }
  825.        
  826.         internal bool IsReturnValue {
  827.             get { return isReturnValue; }
  828.             set { isReturnValue = value; }
  829.         }
  830.        
  831.        
  832.         internal bool ReadOnly {
  833.             get { return readOnly; }
  834.             set { readOnly = value; }
  835.         }
  836.        
  837.         internal bool IsSequence {
  838.             get { return sequenceId >= 0; }
  839.         }
  840.        
  841.         internal int SequenceId {
  842.             get { return sequenceId; }
  843.             set { sequenceId = value; }
  844.         }
  845.        
  846.         string GetNullableType(TypeDesc td)
  847.         {
  848.             // SOAP encoded arrays not mapped to Nullable<T> since they always derive from soapenc:Array
  849.             if (td.IsMappedType || (!td.IsValueType && (Elements[0].IsSoap || td.ArrayElementTypeDesc == null)))
  850.                 return td.FullName;
  851.             if (td.ArrayElementTypeDesc != null) {
  852.                 return GetNullableType(td.ArrayElementTypeDesc) + "[]";
  853.             }
  854.             return "System.Nullable`1[" + td.FullName + "]";
  855.         }
  856.        
  857.         internal string GetTypeName(CodeDomProvider codeProvider)
  858.         {
  859.             if (IsNeedNullable && codeProvider.Supports(GeneratorSupport.GenericTypeReference)) {
  860.                 return GetNullableType(TypeDesc);
  861.             }
  862.             return TypeDesc.FullName;
  863.         }
  864.     }
  865.    
  866.     internal class MembersMapping : TypeMapping
  867.     {
  868.         MemberMapping[] members;
  869.         bool hasWrapperElement = true;
  870.         bool validateRpcWrapperElement;
  871.         bool writeAccessors = true;
  872.         MemberMapping xmlnsMember = null;
  873.        
  874.         internal MemberMapping[] Members {
  875.             get { return members; }
  876.             set { members = value; }
  877.         }
  878.        
  879.         internal MemberMapping XmlnsMember {
  880.             get { return xmlnsMember; }
  881.             set { xmlnsMember = value; }
  882.         }
  883.        
  884.         internal bool HasWrapperElement {
  885.             get { return hasWrapperElement; }
  886.             set { hasWrapperElement = value; }
  887.         }
  888.        
  889.         internal bool ValidateRpcWrapperElement {
  890.             get { return validateRpcWrapperElement; }
  891.             set { validateRpcWrapperElement = value; }
  892.         }
  893.        
  894.         internal bool WriteAccessors {
  895.             get { return writeAccessors; }
  896.             set { writeAccessors = value; }
  897.         }
  898.     }
  899.    
  900.     internal class SpecialMapping : TypeMapping
  901.     {
  902.         bool namedAny;
  903.        
  904.         internal bool NamedAny {
  905.             get { return namedAny; }
  906.             set { namedAny = value; }
  907.         }
  908.     }
  909.    
  910.     internal class SerializableMapping : SpecialMapping
  911.     {
  912.         XmlSchema schema;
  913.         Type type;
  914.         bool needSchema = true;
  915.        
  916.         // new implementation of the IXmlSerializable
  917.         MethodInfo getSchemaMethod;
  918.         XmlQualifiedName xsiType;
  919.         XmlSchemaType xsdType;
  920.         XmlSchemaSet schemas;
  921.         bool any;
  922.         string namespaces;
  923.        
  924.         SerializableMapping baseMapping;
  925.         SerializableMapping derivedMappings;
  926.         SerializableMapping nextDerivedMapping;
  927.         SerializableMapping next;
  928.         // all mappings with the same qname
  929.         internal SerializableMapping()
  930.         {
  931.         }
  932.         internal SerializableMapping(MethodInfo getSchemaMethod, bool any, string ns)
  933.         {
  934.             this.getSchemaMethod = getSchemaMethod;
  935.             this.any = any;
  936.             this.Namespace = ns;
  937.         }
  938.        
  939.         internal SerializableMapping(XmlQualifiedName xsiType, XmlSchemaSet schemas)
  940.         {
  941.             this.xsiType = xsiType;
  942.             this.schemas = schemas;
  943.             this.TypeName = xsiType.Name;
  944.             this.Namespace = xsiType.Namespace;
  945.             needSchema = false;
  946.         }
  947.        
  948.         internal void SetBaseMapping(SerializableMapping mapping)
  949.         {
  950.             baseMapping = mapping;
  951.             if (baseMapping != null) {
  952.                 nextDerivedMapping = baseMapping.derivedMappings;
  953.                 baseMapping.derivedMappings = this;
  954.                 if (this == nextDerivedMapping) {
  955.                     throw new InvalidOperationException(Res.GetString(Res.XmlCircularDerivation, TypeDesc.FullName));
  956.                 }
  957.             }
  958.         }
  959.        
  960.         internal bool IsAny {
  961.             get {
  962.                 if (any)
  963.                     return true;
  964.                 if (getSchemaMethod == null)
  965.                     return false;
  966.                 if (needSchema && typeof(XmlSchemaType).IsAssignableFrom(getSchemaMethod.ReturnType))
  967.                     return false;
  968.                 RetrieveSerializableSchema();
  969.                 return any;
  970.             }
  971.         }
  972.        
  973.         internal string NamespaceList {
  974.             get {
  975.                 RetrieveSerializableSchema();
  976.                 if (namespaces == null) {
  977.                     if (schemas != null) {
  978.                         StringBuilder anyNamespaces = new StringBuilder();
  979.                         foreach (XmlSchema s in schemas.Schemas()) {
  980.                             if (s.TargetNamespace != null && s.TargetNamespace.Length > 0) {
  981.                                 if (anyNamespaces.Length > 0)
  982.                                     anyNamespaces.Append(" ");
  983.                                 anyNamespaces.Append(s.TargetNamespace);
  984.                             }
  985.                         }
  986.                         namespaces = anyNamespaces.ToString();
  987.                     }
  988.                     else {
  989.                         namespaces = string.Empty;
  990.                     }
  991.                 }
  992.                 return namespaces;
  993.             }
  994.         }
  995.        
  996.         internal SerializableMapping DerivedMappings {
  997.             get { return derivedMappings; }
  998.         }
  999.        
  1000.         internal SerializableMapping NextDerivedMapping {
  1001.             get { return nextDerivedMapping; }
  1002.         }
  1003.        
  1004.         internal SerializableMapping Next {
  1005.             get { return next; }
  1006.             set { next = value; }
  1007.         }
  1008.        
  1009.         internal Type Type {
  1010.             get { return type; }
  1011.             set { type = value; }
  1012.         }
  1013.        
  1014.         internal XmlSchemaSet Schemas {
  1015.             get {
  1016.                 RetrieveSerializableSchema();
  1017.                 return schemas;
  1018.             }
  1019.         }
  1020.        
  1021.         internal XmlSchema Schema {
  1022.             get {
  1023.                 RetrieveSerializableSchema();
  1024.                 return schema;
  1025.             }
  1026.         }
  1027.        
  1028.         internal XmlQualifiedName XsiType {
  1029.             get {
  1030.                 if (!needSchema)
  1031.                     return xsiType;
  1032.                 if (getSchemaMethod == null)
  1033.                     return null;
  1034.                 if (typeof(XmlSchemaType).IsAssignableFrom(getSchemaMethod.ReturnType))
  1035.                     return null;
  1036.                 RetrieveSerializableSchema();
  1037.                 return xsiType;
  1038.             }
  1039.         }
  1040.        
  1041.         internal XmlSchemaType XsdType {
  1042.             get {
  1043.                 RetrieveSerializableSchema();
  1044.                 return xsdType;
  1045.             }
  1046.         }
  1047.        
  1048.         static internal void ValidationCallbackWithErrorCode(object sender, ValidationEventArgs args)
  1049.         {
  1050.             if (args.Severity == XmlSeverityType.Error)
  1051.                 throw new InvalidOperationException(Res.GetString(Res.XmlSerializableSchemaError, typeof(IXmlSerializable).Name, args.Message));
  1052.         }
  1053.        
  1054.         internal void CheckDuplicateElement(XmlSchemaElement element, string elementNs)
  1055.         {
  1056.             if (element == null)
  1057.                 return;
  1058.            
  1059.             // only check duplicate definitions for top-level element
  1060.             if (element.Parent == null || !(element.Parent is XmlSchema))
  1061.                 return;
  1062.            
  1063.             XmlSchemaObjectTable elements = null;
  1064.             if (Schema != null && Schema.TargetNamespace == elementNs) {
  1065.                 XmlSchemas.Preprocess(Schema);
  1066.                 elements = Schema.Elements;
  1067.             }
  1068.             else if (Schemas != null) {
  1069.                 elements = Schemas.GlobalElements;
  1070.             }
  1071.             else {
  1072.                 return;
  1073.             }
  1074.             foreach (XmlSchemaElement e in elements.Values) {
  1075.                 if (e.Name == element.Name && e.QualifiedName.Namespace == elementNs) {
  1076.                     if (Match(e, element))
  1077.                         return;
  1078.                     // XmlSerializableRootDupName=Cannot reconcile schema for '{0}'. Please use [XmlRoot] attribute to change name or namepace of the top-level element to avoid duplicate element declarations: element name='{1} namespace='{2}'.
  1079.                     throw new InvalidOperationException(Res.GetString(Res.XmlSerializableRootDupName, getSchemaMethod.DeclaringType.FullName, e.Name, elementNs));
  1080.                 }
  1081.             }
  1082.         }
  1083.        
  1084.         bool Match(XmlSchemaElement e1, XmlSchemaElement e2)
  1085.         {
  1086.             if (e1.IsNillable != e2.IsNillable)
  1087.                 return false;
  1088.             if (e1.RefName != e2.RefName)
  1089.                 return false;
  1090.             if (e1.SchemaType != e2.SchemaType)
  1091.                 return false;
  1092.             if (e1.SchemaTypeName != e2.SchemaTypeName)
  1093.                 return false;
  1094.             if (e1.MinOccurs != e2.MinOccurs)
  1095.                 return false;
  1096.             if (e1.MaxOccurs != e2.MaxOccurs)
  1097.                 return false;
  1098.             if (e1.IsAbstract != e2.IsAbstract)
  1099.                 return false;
  1100.             if (e1.DefaultValue != e2.DefaultValue)
  1101.                 return false;
  1102.             if (e1.SubstitutionGroup != e2.SubstitutionGroup)
  1103.                 return false;
  1104.             return true;
  1105.         }
  1106.        
  1107.         void RetrieveSerializableSchema()
  1108.         {
  1109.             if (needSchema && !any) {
  1110.                 needSchema = false;
  1111.                 if (getSchemaMethod != null) {
  1112.                     // get the type info
  1113.                     if (schemas == null)
  1114.                         schemas = new XmlSchemaSet();
  1115.                     object typeInfo = getSchemaMethod.Invoke(null, new object[] {schemas});
  1116.                     xsiType = XmlQualifiedName.Empty;
  1117.                    
  1118.                     if (typeInfo != null) {
  1119.                         if (typeof(XmlSchemaType).IsAssignableFrom(getSchemaMethod.ReturnType)) {
  1120.                             xsdType = (XmlSchemaType)typeInfo;
  1121.                             // check if type is named
  1122.                             xsiType = xsdType.QualifiedName;
  1123.                         }
  1124.                         else if (typeof(XmlQualifiedName).IsAssignableFrom(getSchemaMethod.ReturnType)) {
  1125.                             xsiType = (XmlQualifiedName)typeInfo;
  1126.                             if (xsiType.IsEmpty) {
  1127.                                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaEmptyTypeName, type.FullName, getSchemaMethod.Name));
  1128.                             }
  1129.                         }
  1130.                         else {
  1131.                             throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaMethodReturnType, type.Name, getSchemaMethod.Name, typeof(XmlSchemaProviderAttribute).Name, typeof(XmlQualifiedName).FullName));
  1132.                         }
  1133.                     }
  1134.                     else {
  1135.                         any = true;
  1136.                     }
  1137.                    
  1138.                     // make sure that user-specified schemas are valid
  1139.                     schemas.ValidationEventHandler += new ValidationEventHandler(ValidationCallbackWithErrorCode);
  1140.                     schemas.Compile();
  1141.                     if (!xsiType.IsEmpty) {
  1142.                         // try to find the type in the schemas collection
  1143.                         if (xsiType.Namespace != XmlSchema.Namespace) {
  1144.                             ArrayList srcSchemas = (ArrayList)schemas.Schemas(xsiType.Namespace);
  1145.                            
  1146.                             if (srcSchemas.Count == 0) {
  1147.                                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingSchema, xsiType.Namespace));
  1148.                             }
  1149.                             if (srcSchemas.Count > 1) {
  1150.                                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaInclude, xsiType.Namespace, getSchemaMethod.DeclaringType.FullName, getSchemaMethod.Name));
  1151.                             }
  1152.                             XmlSchema s = (XmlSchema)srcSchemas[0];
  1153.                             if (s == null) {
  1154.                                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingSchema, xsiType.Namespace));
  1155.                             }
  1156.                             xsdType = (XmlSchemaType)s.SchemaTypes[xsiType];
  1157.                             if (xsdType == null) {
  1158.                                 throw new InvalidOperationException(Res.GetString(Res.XmlGetSchemaTypeMissing, getSchemaMethod.DeclaringType.FullName, getSchemaMethod.Name, xsiType.Name, xsiType.Namespace));
  1159.                             }
  1160.                             xsdType = xsdType.Redefined != null ? xsdType.Redefined : xsdType;
  1161.                         }
  1162.                     }
  1163.                 }
  1164.                 else {
  1165.                     IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(type);
  1166.                     schema = serializable.GetSchema();
  1167.                    
  1168.                     if (schema != null) {
  1169.                         if (schema.Id == null || schema.Id.Length == 0)
  1170.                             throw new InvalidOperationException(Res.GetString(Res.XmlSerializableNameMissing1, type.FullName));
  1171.                     }
  1172.                 }
  1173.             }
  1174.         }
  1175.     }
  1176. }

Developer Fusion