PageRenderTime 35ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/XmlFormatterDeserializer.cs

https://bitbucket.org/steenlund/mono-2.6.7-for-amiga
C# | 204 lines | 140 code | 23 blank | 41 comment | 57 complexity | 0a8715d037578bf300bb259fd35d0f73 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, LGPL-2.1
  1. //
  2. // XmlFormatterDeserializer.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <atsushi@ximian.com>
  6. //
  7. // Copyright (C) 2005 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. #if NET_2_0
  29. using System;
  30. using System.Collections;
  31. using System.IO;
  32. using System.Linq;
  33. using System.Reflection;
  34. using System.Runtime.Serialization.Formatters.Binary;
  35. using System.Xml;
  36. using System.Xml.Schema;
  37. using QName = System.Xml.XmlQualifiedName;
  38. namespace System.Runtime.Serialization
  39. {
  40. internal class XmlFormatterDeserializer
  41. {
  42. KnownTypeCollection types;
  43. IDataContractSurrogate surrogate;
  44. // 3.5 SP1 supports deserialization by reference (id->obj).
  45. // Though unlike XmlSerializer, it does not support forward-
  46. // reference resolution i.e. a referenced object must appear
  47. // before any references to it.
  48. Hashtable references = new Hashtable ();
  49. public static object Deserialize (XmlReader reader, Type type,
  50. KnownTypeCollection knownTypes, IDataContractSurrogate surrogate,
  51. string name, string ns, bool verifyObjectName)
  52. {
  53. reader.MoveToContent ();
  54. if (verifyObjectName)
  55. if (reader.NodeType != XmlNodeType.Element ||
  56. reader.LocalName != name ||
  57. reader.NamespaceURI != ns)
  58. throw new SerializationException (String.Format ("Expected element '{0}' in namespace '{1}', but found {2} node '{3}' in namespace '{4}'", name, ns, reader.NodeType, reader.LocalName, reader.NamespaceURI));
  59. // Verify (knownTypes, type, name, ns, reader);
  60. return new XmlFormatterDeserializer (knownTypes, surrogate).Deserialize (type, reader);
  61. }
  62. // Verify the top element name and namespace.
  63. private static void Verify (KnownTypeCollection knownTypes, Type type, string name, string Namespace, XmlReader reader)
  64. {
  65. QName graph_qname = new QName (reader.Name, reader.NamespaceURI);
  66. if (graph_qname.Name == name && graph_qname.Namespace == Namespace)
  67. return;
  68. // <BClass .. i:type="EClass" >..</BClass>
  69. // Expecting type EClass : allowed
  70. // See test Serialize1b, and Serialize1c (for
  71. // negative cases)
  72. // Run through inheritance heirarchy ..
  73. for (Type baseType = type; baseType != null; baseType = baseType.BaseType)
  74. if (knownTypes.GetQName (baseType) == graph_qname)
  75. return;
  76. QName typeQName = knownTypes.GetQName (type);
  77. throw new SerializationException (String.Format (
  78. "Expecting element '{0}' from namespace '{1}'. Encountered 'Element' with name '{2}', namespace '{3}'",
  79. typeQName.Name, typeQName.Namespace, graph_qname.Name, graph_qname.Namespace));
  80. }
  81. private XmlFormatterDeserializer (
  82. KnownTypeCollection knownTypes,
  83. IDataContractSurrogate surrogate)
  84. {
  85. this.types = knownTypes;
  86. this.surrogate = surrogate;
  87. }
  88. public Hashtable References {
  89. get { return references; }
  90. }
  91. // At the beginning phase, we still have to instantiate a new
  92. // target object even if fromContent is true.
  93. public object Deserialize (Type type, XmlReader reader)
  94. {
  95. string label = reader.GetAttribute ("Id", KnownTypeCollection.MSSimpleNamespace);
  96. object o = DeserializeCore (type, reader);
  97. if (label != null)
  98. references.Add (label, o);
  99. return o;
  100. }
  101. public object DeserializeCore (Type type, XmlReader reader)
  102. {
  103. QName graph_qname = types.GetQName (type);
  104. string itype = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
  105. if (itype != null) {
  106. string[] parts = itype.Split (':');
  107. if (parts.Length > 1)
  108. graph_qname = new QName (parts [1], reader.LookupNamespace (reader.NameTable.Get (parts[0])));
  109. else
  110. graph_qname = new QName (itype, reader.NamespaceURI);
  111. }
  112. string label = reader.GetAttribute ("Ref", KnownTypeCollection.MSSimpleNamespace);
  113. if (label != null) {
  114. object o = references [label];
  115. if (o == null)
  116. throw new SerializationException (String.Format ("Deserialized object with reference Id '{0}' was not found", label));
  117. reader.Skip ();
  118. return o;
  119. }
  120. bool isNil = reader.GetAttribute ("nil", XmlSchema.InstanceNamespace) == "true";
  121. if (isNil) {
  122. reader.Skip ();
  123. if (!type.IsValueType)
  124. return null;
  125. else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>))
  126. return null;
  127. else
  128. throw new SerializationException (String.Format ("Value type {0} cannot be null.", type));
  129. }
  130. if (KnownTypeCollection.GetPrimitiveTypeFromName (graph_qname.Name) != null) {
  131. string value;
  132. if (reader.IsEmptyElement) {
  133. reader.Read (); // advance
  134. if (type.IsValueType)
  135. return Activator.CreateInstance (type);
  136. else
  137. // FIXME: Workaround for creating empty objects of the correct type.
  138. value = String.Empty;
  139. }
  140. else
  141. value = reader.ReadElementContentAsString ();
  142. return KnownTypeCollection.PredefinedTypeStringToObject (value, graph_qname.Name, reader);
  143. }
  144. return DeserializeByMap (graph_qname, type, reader);
  145. }
  146. object DeserializeByMap (QName name, Type type, XmlReader reader)
  147. {
  148. SerializationMap map = types.FindUserMap (name);
  149. if (map == null && (name.Namespace == KnownTypeCollection.MSArraysNamespace ||
  150. name.Namespace.StartsWith (KnownTypeCollection.DefaultClrNamespaceBase, StringComparison.Ordinal))) {
  151. var it = GetTypeFromNamePair (name.Name, name.Namespace);
  152. types.TryRegister (it);
  153. map = types.FindUserMap (name);
  154. }
  155. if (map == null)
  156. throw new SerializationException (String.Format ("Unknown type {0} is used for DataContract with reference of name {1}. Any derived types of a data contract or a data member should be added to KnownTypes.", type, name));
  157. return map.DeserializeObject (reader, this);
  158. }
  159. Type GetTypeFromNamePair (string name, string ns)
  160. {
  161. Type p = KnownTypeCollection.GetPrimitiveTypeFromName (name); // FIXME: namespace?
  162. if (p != null)
  163. return p;
  164. if (name.StartsWith ("ArrayOf", StringComparison.Ordinal) && ns == KnownTypeCollection.MSArraysNamespace)
  165. return GetTypeFromNamePair (name.Substring (7), String.Empty).MakeArrayType ();
  166. int xlen = KnownTypeCollection.DefaultClrNamespaceBase.Length;
  167. string clrns = ns.Length > xlen ? ns.Substring (xlen) : null;
  168. foreach (var ass in AppDomain.CurrentDomain.GetAssemblies ()) {
  169. foreach (var t in ass.GetTypes ()) {
  170. var dca = t.GetCustomAttribute<DataContractAttribute> (true);
  171. if (dca != null && dca.Name == name && dca.Namespace == ns)
  172. return t;
  173. if (clrns != null && t.Name == name && t.Namespace == clrns)
  174. return t;
  175. }
  176. }
  177. throw new XmlException (String.Format ("Type not found; name: {0}, namespace: {1}", name, ns));
  178. }
  179. }
  180. }
  181. #endif