The Labs \ Source Viewer \ SSCLI \ System.Xml.Schema \ XmlAtomicValue

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlAtomicValue.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">akimball</owner>
  15. //------------------------------------------------------------------------------
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Runtime.InteropServices;
  20. using System.Xml.XPath;
  21. using System.Diagnostics;
  22. namespace System.Xml.Schema
  23. {
  24.    
  25.     /// <summary>
  26.     /// This class contains a (CLR Object, XmlType) pair that represents an instance of an Xml atomic value.
  27.     /// It is optimized to avoid boxing.
  28.     /// </summary>
  29.     public sealed class XmlAtomicValue : XPathItem, ICloneable
  30.     {
  31.         private XmlSchemaType xmlType;
  32.         private object objVal;
  33.         private TypeCode clrType;
  34.         private Union unionVal;
  35.         private NamespacePrefixForQName nsPrefix;
  36.        
  37.         [StructLayout(LayoutKind.Explicit, Size = 8)]
  38.         private struct Union
  39.         {
  40.             [FieldOffset(0)]
  41.             public bool boolVal;
  42.             [FieldOffset(0)]
  43.             public double dblVal;
  44.             [FieldOffset(0)]
  45.             public long i64Val;
  46.             [FieldOffset(0)]
  47.             public int i32Val;
  48.             [FieldOffset(0)]
  49.             public DateTime dtVal;
  50.         }
  51.        
  52.         class NamespacePrefixForQName : IXmlNamespaceResolver
  53.         {
  54.             public string prefix;
  55.             public string ns;
  56.            
  57.             public NamespacePrefixForQName(string prefix, string ns)
  58.             {
  59.                 this.ns = ns;
  60.                 this.prefix = prefix;
  61.             }
  62.             public string LookupNamespace(string prefix)
  63.             {
  64.                 if (prefix == this.prefix) {
  65.                     return ns;
  66.                 }
  67.                 return null;
  68.             }
  69.            
  70.             public string LookupPrefix(string namespaceName)
  71.             {
  72.                 if (ns == namespaceName) {
  73.                     return prefix;
  74.                 }
  75.                 return null;
  76.             }
  77.            
  78.             public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
  79.             {
  80.                 Dictionary<string, string> dict = new Dictionary<string, string>(1);
  81.                 dict[prefix] = ns;
  82.                 return dict;
  83.             }
  84.         }
  85.        
  86.         //-----------------------------------------------
  87.         // XmlAtomicValue constructors and methods
  88.         //-----------------------------------------------
  89.        
  90.         internal XmlAtomicValue(XmlSchemaType xmlType, bool value)
  91.         {
  92.             if (xmlType == null)
  93.                 throw new ArgumentNullException("xmlType");
  94.             this.xmlType = xmlType;
  95.             this.clrType = TypeCode.Boolean;
  96.             this.unionVal.boolVal = value;
  97.         }
  98.        
  99.         internal XmlAtomicValue(XmlSchemaType xmlType, DateTime value)
  100.         {
  101.             if (xmlType == null)
  102.                 throw new ArgumentNullException("xmlType");
  103.             this.xmlType = xmlType;
  104.             this.clrType = TypeCode.DateTime;
  105.             this.unionVal.dtVal = value;
  106.         }
  107.        
  108.         internal XmlAtomicValue(XmlSchemaType xmlType, double value)
  109.         {
  110.             if (xmlType == null)
  111.                 throw new ArgumentNullException("xmlType");
  112.             this.xmlType = xmlType;
  113.             this.clrType = TypeCode.Double;
  114.             this.unionVal.dblVal = value;
  115.         }
  116.        
  117.         internal XmlAtomicValue(XmlSchemaType xmlType, int value)
  118.         {
  119.             if (xmlType == null)
  120.                 throw new ArgumentNullException("xmlType");
  121.             this.xmlType = xmlType;
  122.             this.clrType = TypeCode.Int32;
  123.             this.unionVal.i32Val = value;
  124.         }
  125.        
  126.         internal XmlAtomicValue(XmlSchemaType xmlType, long value)
  127.         {
  128.             if (xmlType == null)
  129.                 throw new ArgumentNullException("xmlType");
  130.             this.xmlType = xmlType;
  131.             this.clrType = TypeCode.Int64;
  132.             this.unionVal.i64Val = value;
  133.         }
  134.        
  135.         internal XmlAtomicValue(XmlSchemaType xmlType, string value)
  136.         {
  137.             if (value == null)
  138.                 throw new ArgumentNullException("value");
  139.             if (xmlType == null)
  140.                 throw new ArgumentNullException("xmlType");
  141.             this.xmlType = xmlType;
  142.             this.objVal = value;
  143.         }
  144.        
  145.         internal XmlAtomicValue(XmlSchemaType xmlType, string value, IXmlNamespaceResolver nsResolver)
  146.         {
  147.             if (value == null)
  148.                 throw new ArgumentNullException("value");
  149.             if (xmlType == null)
  150.                 throw new ArgumentNullException("xmlType");
  151.             this.xmlType = xmlType;
  152.             this.objVal = value;
  153.             if (nsResolver != null && (this.xmlType.TypeCode == XmlTypeCode.QName || this.xmlType.TypeCode == XmlTypeCode.Notation)) {
  154.                 string prefix = GetPrefixFromQName(value);
  155.                 this.nsPrefix = new NamespacePrefixForQName(prefix, nsResolver.LookupNamespace(prefix));
  156.             }
  157.         }
  158.        
  159.         internal XmlAtomicValue(XmlSchemaType xmlType, object value)
  160.         {
  161.             if (value == null)
  162.                 throw new ArgumentNullException("value");
  163.             if (xmlType == null)
  164.                 throw new ArgumentNullException("xmlType");
  165.             this.xmlType = xmlType;
  166.             this.objVal = value;
  167.         }
  168.        
  169.         internal XmlAtomicValue(XmlSchemaType xmlType, object value, IXmlNamespaceResolver nsResolver)
  170.         {
  171.             if (value == null)
  172.                 throw new ArgumentNullException("value");
  173.             if (xmlType == null)
  174.                 throw new ArgumentNullException("xmlType");
  175.             this.xmlType = xmlType;
  176.             this.objVal = value;
  177.            
  178.             if (nsResolver != null && (this.xmlType.TypeCode == XmlTypeCode.QName || this.xmlType.TypeCode == XmlTypeCode.Notation)) {
  179.                 //Its a qualifiedName
  180.                 XmlQualifiedName qname = this.objVal as XmlQualifiedName;
  181.                 Debug.Assert(qname != null);
  182.                 //string representation is handled in a different overload
  183.                 string ns = qname.Namespace;
  184.                 this.nsPrefix = new NamespacePrefixForQName(nsResolver.LookupPrefix(ns), ns);
  185.             }
  186.         }
  187.        
  188.         /// <summary>
  189.         /// Since XmlAtomicValue is immutable, clone simply returns this.
  190.         /// </summary>
  191.         public XmlAtomicValue Clone()
  192.         {
  193.             return this;
  194.         }
  195.        
  196.        
  197.         //-----------------------------------------------
  198.         // ICloneable methods
  199.         //-----------------------------------------------
  200.        
  201.         /// <summary>
  202.         /// Since XmlAtomicValue is immutable, clone simply returns this.
  203.         /// </summary>
  204.         object ICloneable.Clone()
  205.         {
  206.             return this;
  207.         }
  208.        
  209.        
  210.         //-----------------------------------------------
  211.         // XPathItem methods
  212.         //-----------------------------------------------
  213.        
  214.         public override bool IsNode {
  215.             get { return false; }
  216.         }
  217.        
  218.         public override XmlSchemaType XmlType {
  219.             get { return this.xmlType; }
  220.         }
  221.        
  222.         public override Type ValueType {
  223.             get { return this.xmlType.Datatype.ValueType; }
  224.         }
  225.        
  226.         public override object TypedValue {
  227.             get {
  228.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  229.                
  230.                 if (this.objVal == null) {
  231.                     switch (this.clrType) {
  232.                         case TypeCode.Boolean:
  233.                             return valueConverter.ChangeType(this.unionVal.boolVal, ValueType);
  234.                         case TypeCode.Int32:
  235.                             return valueConverter.ChangeType(this.unionVal.i32Val, ValueType);
  236.                         case TypeCode.Int64:
  237.                             return valueConverter.ChangeType(this.unionVal.i64Val, ValueType);
  238.                         case TypeCode.Double:
  239.                             return valueConverter.ChangeType(this.unionVal.dblVal, ValueType);
  240.                         case TypeCode.DateTime:
  241.                             return valueConverter.ChangeType(this.unionVal.dtVal, ValueType);
  242.                         default:
  243.                             Debug.Assert(false, "Should never get here");
  244.                             break;
  245.                     }
  246.                 }
  247.                 return valueConverter.ChangeType(this.objVal, ValueType, this.nsPrefix);
  248.             }
  249.         }
  250.        
  251.         public override bool ValueAsBoolean {
  252.             get {
  253.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  254.                
  255.                 if (this.objVal == null) {
  256.                     switch (this.clrType) {
  257.                         case TypeCode.Boolean:
  258.                             return this.unionVal.boolVal;
  259.                         case TypeCode.Int32:
  260.                             return valueConverter.ToBoolean(this.unionVal.i32Val);
  261.                         case TypeCode.Int64:
  262.                             return valueConverter.ToBoolean(this.unionVal.i64Val);
  263.                         case TypeCode.Double:
  264.                             return valueConverter.ToBoolean(this.unionVal.dblVal);
  265.                         case TypeCode.DateTime:
  266.                             return valueConverter.ToBoolean(this.unionVal.dtVal);
  267.                         default:
  268.                             Debug.Assert(false, "Should never get here");
  269.                             break;
  270.                     }
  271.                 }
  272.                
  273.                 return valueConverter.ToBoolean(this.objVal);
  274.             }
  275.         }
  276.        
  277.         public override DateTime ValueAsDateTime {
  278.             get {
  279.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  280.                
  281.                 if (this.objVal == null) {
  282.                     switch (this.clrType) {
  283.                         case TypeCode.Boolean:
  284.                             return valueConverter.ToDateTime(this.unionVal.boolVal);
  285.                         case TypeCode.Int32:
  286.                             return valueConverter.ToDateTime(this.unionVal.i32Val);
  287.                         case TypeCode.Int64:
  288.                             return valueConverter.ToDateTime(this.unionVal.i64Val);
  289.                         case TypeCode.Double:
  290.                             return valueConverter.ToDateTime(this.unionVal.dblVal);
  291.                         case TypeCode.DateTime:
  292.                             return this.unionVal.dtVal;
  293.                         default:
  294.                             Debug.Assert(false, "Should never get here");
  295.                             break;
  296.                     }
  297.                 }
  298.                
  299.                 return valueConverter.ToDateTime(this.objVal);
  300.             }
  301.         }
  302.        
  303.        
  304.         public override double ValueAsDouble {
  305.             get {
  306.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  307.                
  308.                 if (this.objVal == null) {
  309.                     switch (this.clrType) {
  310.                         case TypeCode.Boolean:
  311.                             return valueConverter.ToDouble(this.unionVal.boolVal);
  312.                         case TypeCode.Int32:
  313.                             return valueConverter.ToDouble(this.unionVal.i32Val);
  314.                         case TypeCode.Int64:
  315.                             return valueConverter.ToDouble(this.unionVal.i64Val);
  316.                         case TypeCode.Double:
  317.                             return this.unionVal.dblVal;
  318.                         case TypeCode.DateTime:
  319.                             return valueConverter.ToDouble(this.unionVal.dtVal);
  320.                         default:
  321.                             Debug.Assert(false, "Should never get here");
  322.                             break;
  323.                     }
  324.                 }
  325.                
  326.                 return valueConverter.ToDouble(this.objVal);
  327.             }
  328.         }
  329.        
  330.         public override int ValueAsInt {
  331.             get {
  332.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  333.                
  334.                 if (this.objVal == null) {
  335.                     switch (this.clrType) {
  336.                         case TypeCode.Boolean:
  337.                             return valueConverter.ToInt32(this.unionVal.boolVal);
  338.                         case TypeCode.Int32:
  339.                             return this.unionVal.i32Val;
  340.                         case TypeCode.Int64:
  341.                             return valueConverter.ToInt32(this.unionVal.i64Val);
  342.                         case TypeCode.Double:
  343.                             return valueConverter.ToInt32(this.unionVal.dblVal);
  344.                         case TypeCode.DateTime:
  345.                             return valueConverter.ToInt32(this.unionVal.dtVal);
  346.                         default:
  347.                             Debug.Assert(false, "Should never get here");
  348.                             break;
  349.                     }
  350.                 }
  351.                
  352.                 return valueConverter.ToInt32(this.objVal);
  353.             }
  354.         }
  355.        
  356.         public override long ValueAsLong {
  357.             get {
  358.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  359.                
  360.                 if (this.objVal == null) {
  361.                     switch (this.clrType) {
  362.                         case TypeCode.Boolean:
  363.                             return valueConverter.ToInt64(this.unionVal.boolVal);
  364.                         case TypeCode.Int32:
  365.                             return valueConverter.ToInt64(this.unionVal.i32Val);
  366.                         case TypeCode.Int64:
  367.                             return this.unionVal.i64Val;
  368.                         case TypeCode.Double:
  369.                             return valueConverter.ToInt64(this.unionVal.dblVal);
  370.                         case TypeCode.DateTime:
  371.                             return valueConverter.ToInt64(this.unionVal.dtVal);
  372.                         default:
  373.                             Debug.Assert(false, "Should never get here");
  374.                             break;
  375.                     }
  376.                 }
  377.                
  378.                 return valueConverter.ToInt64(this.objVal);
  379.             }
  380.         }
  381.        
  382.         public override object ValueAs(Type type, IXmlNamespaceResolver nsResolver)
  383.         {
  384.             XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  385.            
  386.             if (type == typeof(XPathItem) || type == typeof(XmlAtomicValue))
  387.                 return this;
  388.            
  389.             if (this.objVal == null) {
  390.                 switch (this.clrType) {
  391.                     case TypeCode.Boolean:
  392.                         return valueConverter.ChangeType(this.unionVal.boolVal, type);
  393.                     case TypeCode.Int32:
  394.                         return valueConverter.ChangeType(this.unionVal.i32Val, type);
  395.                     case TypeCode.Int64:
  396.                         return valueConverter.ChangeType(this.unionVal.i64Val, type);
  397.                     case TypeCode.Double:
  398.                         return valueConverter.ChangeType(this.unionVal.dblVal, type);
  399.                     case TypeCode.DateTime:
  400.                         return valueConverter.ChangeType(this.unionVal.dtVal, type);
  401.                     default:
  402.                         Debug.Assert(false, "Should never get here");
  403.                         break;
  404.                 }
  405.             }
  406.            
  407.             return valueConverter.ChangeType(this.objVal, type, nsResolver);
  408.         }
  409.        
  410.         public override string Value {
  411.             get {
  412.                 XmlValueConverter valueConverter = this.xmlType.ValueConverter;
  413.                
  414.                 if (this.objVal == null) {
  415.                     switch (this.clrType) {
  416.                         case TypeCode.Boolean:
  417.                             return valueConverter.ToString(this.unionVal.boolVal);
  418.                         case TypeCode.Int32:
  419.                             return valueConverter.ToString(this.unionVal.i32Val);
  420.                         case TypeCode.Int64:
  421.                             return valueConverter.ToString(this.unionVal.i64Val);
  422.                         case TypeCode.Double:
  423.                             return valueConverter.ToString(this.unionVal.dblVal);
  424.                         case TypeCode.DateTime:
  425.                             return valueConverter.ToString(this.unionVal.dtVal);
  426.                         default:
  427.                             Debug.Assert(false, "Should never get here");
  428.                             break;
  429.                     }
  430.                 }
  431.                 return valueConverter.ToString(this.objVal, this.nsPrefix);
  432.             }
  433.         }
  434.        
  435.         public override string ToString()
  436.         {
  437.             return Value;
  438.         }
  439.        
  440.         private string GetPrefixFromQName(string value)
  441.         {
  442.             int colonOffset;
  443.             int len = ValidateNames.ParseQName(value, 0, out colonOffset);
  444.            
  445.             if (len == 0 || len != value.Length) {
  446.                 return null;
  447.             }
  448.             if (colonOffset != 0) {
  449.                 return value.Substring(0, colonOffset);
  450.             }
  451.             else {
  452.                 return string.Empty;
  453.             }
  454.         }
  455.     }
  456. }

Developer Fusion