1 // created on 09/04/2003 at 18:58
3 // System.Runtime.Serialization.Formatters.Soap.SoapTypeMapper
6 // Jean-Marc Andre (jean-marc.andre@polymtl.ca)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Reflection;
32 using System.Collections;
33 using System.Runtime.Remoting;
35 using System.Xml.Serialization;
36 using System.Runtime.Serialization.Formatters;
37 using System.Xml.Schema;
38 using System.Runtime.Remoting.Metadata.W3cXsd2001;
39 using System.Globalization;
41 namespace System.Runtime.Serialization.Formatters.Soap {
43 internal class Element
45 private string _prefix;
46 private string _localName;
47 private string _namespaceURI;
49 public Element(string prefix, string localName, string namespaceURI)
52 _localName = localName;
53 _namespaceURI = namespaceURI;
56 public Element(string localName, string namespaceURI): this(null, localName, namespaceURI)
68 public string LocalName
76 public string NamespaceURI
84 public override bool Equals(object obj)
86 Element element = obj as Element;
87 return (_localName == XmlConvert.DecodeName(element._localName) &&
88 _namespaceURI == XmlConvert.DecodeName(element._namespaceURI))?true:false;
91 public override int GetHashCode()
93 return (String.Format("{0} {1}",
94 XmlConvert.DecodeName(_localName),
95 XmlConvert.DecodeName(_namespaceURI))).GetHashCode();
98 public override string ToString()
100 return string.Format("Element.Prefix = {0}, Element.LocalName = {1}, Element.NamespaceURI = {2}", this.Prefix, this.LocalName, this.NamespaceURI);
104 internal class SoapTypeMapper {
105 private static Hashtable xmlNodeToTypeTable = new Hashtable();
106 private static Hashtable typeToXmlNodeTable = new Hashtable();
107 public static readonly string SoapEncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
108 public static readonly string SoapEncodingPrefix = "SOAP-ENC";
109 public static readonly string SoapEnvelopeNamespace = "http://schemas.xmlsoap.org/soap/envelope/";
110 public static readonly string SoapEnvelopePrefix = "SOAP-ENV";
111 //internal static readonly string SoapEnvelope;
112 private XmlTextWriter _xmlWriter;
113 private long _prefixNumber;
114 private Hashtable namespaceToPrefixTable = new Hashtable();
115 private SerializationBinder _binder;
116 private static ArrayList _canBeValueTypeList;
117 private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;
118 private Element elementString;
121 // Constructor used by SoapReader
122 public SoapTypeMapper(SerializationBinder binder)
127 // Constructor used by SoapWriter
128 public SoapTypeMapper(
129 XmlTextWriter xmlWriter,
130 FormatterAssemblyStyle assemblyFormat,
131 FormatterTypeStyle typeFormat)
133 _xmlWriter = xmlWriter;
134 _assemblyFormat = assemblyFormat;
136 //Type elementType = typeof(string);
137 if(typeFormat == FormatterTypeStyle.XsdString)
\r
139 elementString = new Element("xsd", "string", XmlSchema.Namespace);
143 elementString = new Element(SoapEncodingPrefix, "string", SoapEncodingNamespace);
145 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
148 static SoapTypeMapper() {
149 // SoapEnvelope = String.Format(
150 // "<{0}:Envelope xmlns:{0}='{1}' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='{2}' xmlns:{3}='{4}' xmlns:clr='{5}' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>",
151 // SoapEnvelopePrefix,
152 // SoapEnvelopeNamespace,
153 // XmlSchema.Namespace,
154 // SoapEncodingPrefix,
155 // SoapEncodingNamespace,
156 // SoapServices.XmlNsForClrType);
157 _canBeValueTypeList = new ArrayList();
158 _canBeValueTypeList.Add(typeof(DateTime).ToString());
159 _canBeValueTypeList.Add(typeof(TimeSpan).ToString());
160 _canBeValueTypeList.Add(typeof(string).ToString());
161 _canBeValueTypeList.Add(typeof(decimal).ToString());
162 _canBeValueTypeList.Sort();
167 public Type this[Element element]
173 string localName = XmlConvert.DecodeName(element.LocalName);
174 string namespaceURI = XmlConvert.DecodeName(element.NamespaceURI);
175 string typeNamespace, assemblyName;
176 SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
177 element.NamespaceURI,
180 string typeName = typeNamespace + Type.Delimiter + localName;
182 if(assemblyName != null && assemblyName != string.Empty && _binder != null)
184 type = _binder.BindToType(assemblyName, typeName);
188 string assemblyQualifiedName = (string)xmlNodeToTypeTable[element];
189 if(assemblyQualifiedName != null)
190 type = Type.GetType(assemblyQualifiedName);
194 type = Type.GetType(element.LocalName);
198 type = Type.GetType(typeName);
202 if(assemblyName == null || assemblyName == String.Empty)
203 throw new SerializationException(
204 String.Format("Parse Error, no assembly associated with XML key {0} {1}",
207 type = FormatterServices.GetTypeFromAssembly(
208 Assembly.Load(assemblyName),
214 throw new SerializationException();
221 public Element this[string typeFullName, string assemblyName]
226 string typeNamespace = string.Empty;
227 string typeName = typeFullName;
228 if(_assemblyFormat == FormatterAssemblyStyle.Simple)
\r
230 string[] items = assemblyName.Split(',');
231 assemblyName = items[0];
233 string assemblyQualifiedName = typeFullName + ", " + assemblyName;
234 element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
237 int typeNameIndex = typeFullName.LastIndexOf('.');
238 if(typeNameIndex != -1)
240 typeNamespace = typeFullName.Substring(0, typeNameIndex);
241 typeName = typeFullName.Substring(typeNamespace.Length + 1);
243 string namespaceURI =
244 SoapServices.CodeXmlNamespaceForClrTypeNamespace(
246 (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
247 string prefix = (string) namespaceToPrefixTable[namespaceURI];
248 if(prefix == null || prefix == string.Empty)
250 prefix = "a" + (_prefixNumber++).ToString();
251 namespaceToPrefixTable[namespaceURI] = prefix;
254 element = new Element(
256 XmlConvert.EncodeName(typeName),
263 public Element this[Type type]
267 if(type == typeof(string)) return elementString;
268 Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
271 element = this[type.FullName, type.Assembly.FullName];
272 // if(_assemblyFormat == FormatterAssemblyStyle.Full)
273 // element = this[type.FullName, type.Assembly.FullName];
275 // element = this[type.FullName, type.Assembly.GetName().Name];
280 element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
283 throw new SerializationException("Oooops");
288 public static bool CanBeValue(Type type)
290 if(type.IsPrimitive) return true;
291 if(type.IsEnum) return true;
292 if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0)
299 private static void InitMappingTables()
303 element = new Element("Array", SoapEncodingNamespace);
304 elementType = typeof(System.Array);
305 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
306 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
308 element = new Element("string", XmlSchema.Namespace);
309 elementType = typeof(string);
310 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
311 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
313 element = new Element("string", SoapEncodingNamespace);
314 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
316 element = new Element("long", XmlSchema.Namespace);
317 elementType = typeof(long);
318 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
319 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
321 element = new Element("int", XmlSchema.Namespace);
322 elementType = typeof(int);
323 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
324 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
326 element = new Element("float", XmlSchema.Namespace);
327 elementType = typeof(float);
328 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
329 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
331 element = new Element("decimal", XmlSchema.Namespace);
332 elementType = typeof(decimal);
333 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
334 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
336 element = new Element("short", XmlSchema.Namespace);
337 elementType = typeof(short);
338 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
339 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
341 element = new Element("anyType", XmlSchema.Namespace);
342 elementType = typeof(object);
343 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
344 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
346 element = new Element("dateTime", XmlSchema.Namespace);
347 elementType = typeof(DateTime);
348 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
349 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
351 element = new Element("duration", XmlSchema.Namespace);
352 elementType = typeof(TimeSpan);
353 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
354 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
356 element = new Element("Fault", SoapEnvelopeNamespace);
357 elementType = typeof(System.Runtime.Serialization.Formatters.SoapFault);
358 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
359 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
361 element = new Element("base64", SoapEncodingNamespace);
362 elementType = typeof(byte[]);
363 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
364 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
367 public static string GetXsdValue (object value)
369 if (value is DateTime) {
370 return SoapDateTime.ToString ((DateTime)value);
372 else if (value is decimal) {
373 return ((decimal) value).ToString (CultureInfo.InvariantCulture);
375 else if (value is double) {
376 return ((double) value).ToString (CultureInfo.InvariantCulture);
378 else if (value is float) {
379 return ((float) value).ToString (CultureInfo.InvariantCulture);
381 else if (value is TimeSpan) {
382 return SoapDuration.ToString ((TimeSpan)value);
385 return value.ToString ();
389 public static object ParseXsdValue (string value, Type type)
391 if (type == typeof(DateTime)) {
392 return SoapDateTime.Parse (value);
394 else if (type == typeof(decimal)) {
395 return decimal.Parse (value, CultureInfo.InvariantCulture);
397 else if (type == typeof(double)) {
398 return double.Parse (value, CultureInfo.InvariantCulture);
400 else if (type == typeof(float)) {
401 return float.Parse (value, CultureInfo.InvariantCulture);
403 else if (type == typeof (TimeSpan)) {
404 return SoapDuration.Parse (value);
406 else if(type.IsEnum) {
407 return Enum.Parse(type, value);
410 return Convert.ChangeType (value, type, CultureInfo.InvariantCulture);