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
;
137 elementType
= typeof(string);
138 if(typeFormat
== FormatterTypeStyle
.XsdString
)
140 elementString
= new Element("xsd", "string", XmlSchema
.Namespace
);
144 elementString
= new Element(SoapEncodingPrefix
, "string", SoapEncodingNamespace
);
146 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
149 static SoapTypeMapper() {
150 // SoapEnvelope = String.Format(
151 // "<{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/'/>",
152 // SoapEnvelopePrefix,
153 // SoapEnvelopeNamespace,
154 // XmlSchema.Namespace,
155 // SoapEncodingPrefix,
156 // SoapEncodingNamespace,
157 // SoapServices.XmlNsForClrType);
158 _canBeValueTypeList
= new ArrayList();
159 _canBeValueTypeList
.Add(typeof(DateTime
).ToString());
160 _canBeValueTypeList
.Add(typeof(TimeSpan
).ToString());
161 _canBeValueTypeList
.Add(typeof(string).ToString());
162 _canBeValueTypeList
.Add(typeof(decimal).ToString());
163 _canBeValueTypeList
.Sort();
168 public Type
this[Element element
]
174 string localName
= XmlConvert
.DecodeName(element
.LocalName
);
175 string namespaceURI
= XmlConvert
.DecodeName(element
.NamespaceURI
);
176 string typeNamespace
, assemblyName
;
177 SoapServices
.DecodeXmlNamespaceForClrTypeNamespace(
178 element
.NamespaceURI
,
181 string typeName
= typeNamespace
+ Type
.Delimiter
+ localName
;
183 if(assemblyName
!= null && assemblyName
!= string.Empty
&& _binder
!= null)
185 type
= _binder
.BindToType(assemblyName
, typeName
);
189 string assemblyQualifiedName
= (string)xmlNodeToTypeTable
[element
];
190 if(assemblyQualifiedName
!= null)
191 type
= Type
.GetType(assemblyQualifiedName
);
195 type
= Type
.GetType(element
.LocalName
);
199 type
= Type
.GetType(typeName
);
203 if(assemblyName
== null || assemblyName
== String
.Empty
)
204 throw new SerializationException(
205 String
.Format("Parse Error, no assembly associated with XML key {0} {1}",
208 type
= FormatterServices
.GetTypeFromAssembly(
209 Assembly
.Load(assemblyName
),
215 throw new SerializationException();
222 public Element
this[string typeFullName
, string assemblyName
]
227 string typeNamespace
= string.Empty
;
228 string typeName
= typeFullName
;
229 if(_assemblyFormat
== FormatterAssemblyStyle
.Simple
)
231 string[] items
= assemblyName
.Split(',');
232 assemblyName
= items
[0];
234 string assemblyQualifiedName
= typeFullName
+ ", " + assemblyName
;
235 element
= (Element
) typeToXmlNodeTable
[assemblyQualifiedName
];
238 int typeNameIndex
= typeFullName
.LastIndexOf('.');
239 if(typeNameIndex
!= -1)
241 typeNamespace
= typeFullName
.Substring(0, typeNameIndex
);
242 typeName
= typeFullName
.Substring(typeNamespace
.Length
+ 1);
244 string namespaceURI
=
245 SoapServices
.CodeXmlNamespaceForClrTypeNamespace(
247 (!assemblyName
.StartsWith("mscorlib"))?assemblyName
:String
.Empty
);
248 string prefix
= (string) namespaceToPrefixTable
[namespaceURI
];
249 if(prefix
== null || prefix
== string.Empty
)
251 prefix
= "a" + (_prefixNumber
++).ToString();
252 namespaceToPrefixTable
[namespaceURI
] = prefix
;
255 element
= new Element(
257 XmlConvert
.EncodeName(typeName
),
264 public Element
this[Type type
]
268 if(type
== typeof(string)) return elementString
;
269 Element element
= (Element
) typeToXmlNodeTable
[type
.AssemblyQualifiedName
];
272 element
= this[type
.FullName
, type
.Assembly
.FullName
];
273 // if(_assemblyFormat == FormatterAssemblyStyle.Full)
274 // element = this[type.FullName, type.Assembly.FullName];
276 // element = this[type.FullName, type.Assembly.GetName().Name];
281 element
= new Element((element
.Prefix
== null)?_xmlWriter
.LookupPrefix(element
.NamespaceURI
):element
.Prefix
, element
.LocalName
, element
.NamespaceURI
);
284 throw new SerializationException("Oooops");
289 public static bool CanBeValue(Type type
)
291 if(type
.IsPrimitive
) return true;
292 if(type
.IsEnum
) return true;
293 if(_canBeValueTypeList
.BinarySearch(type
.ToString()) >= 0)
300 private static void InitMappingTables()
304 element
= new Element("Array", SoapEncodingNamespace
);
305 elementType
= typeof(System
.Array
);
306 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
307 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
309 element
= new Element("string", XmlSchema
.Namespace
);
310 elementType
= typeof(string);
311 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
312 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
314 element
= new Element("string", SoapEncodingNamespace
);
315 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
317 element
= new Element("long", XmlSchema
.Namespace
);
318 elementType
= typeof(long);
319 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
320 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
322 element
= new Element("int", XmlSchema
.Namespace
);
323 elementType
= typeof(int);
324 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
325 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
327 element
= new Element("float", XmlSchema
.Namespace
);
328 elementType
= typeof(float);
329 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
330 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
332 element
= new Element("decimal", XmlSchema
.Namespace
);
333 elementType
= typeof(decimal);
334 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
335 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
337 element
= new Element("short", XmlSchema
.Namespace
);
338 elementType
= typeof(short);
339 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
340 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
342 element
= new Element("anyType", XmlSchema
.Namespace
);
343 elementType
= typeof(object);
344 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
345 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
347 element
= new Element("dateTime", XmlSchema
.Namespace
);
348 elementType
= typeof(DateTime
);
349 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
350 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
352 element
= new Element("duration", XmlSchema
.Namespace
);
353 elementType
= typeof(TimeSpan
);
354 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
355 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
357 element
= new Element("Fault", SoapEnvelopeNamespace
);
358 elementType
= typeof(System
.Runtime
.Serialization
.Formatters
.SoapFault
);
359 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
360 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
362 element
= new Element("base64", SoapEncodingNamespace
);
363 elementType
= typeof(byte[]);
364 xmlNodeToTypeTable
.Add(element
, elementType
.AssemblyQualifiedName
);
365 typeToXmlNodeTable
.Add(elementType
.AssemblyQualifiedName
, element
);
368 public static string GetXsdValue (object value)
370 if (value is DateTime
) {
371 return SoapDateTime
.ToString ((DateTime
)value);
373 else if (value is decimal) {
374 return ((decimal) value).ToString (CultureInfo
.InvariantCulture
);
376 else if (value is double) {
377 return ((double) value).ToString (CultureInfo
.InvariantCulture
);
379 else if (value is float) {
380 return ((float) value).ToString (CultureInfo
.InvariantCulture
);
382 else if (value is TimeSpan
) {
383 return SoapDuration
.ToString ((TimeSpan
)value);
386 return value.ToString ();
390 public static object ParseXsdValue (string value, Type type
)
392 if (type
== typeof(DateTime
)) {
393 return SoapDateTime
.Parse (value);
395 else if (type
== typeof(decimal)) {
396 return decimal.Parse (value, CultureInfo
.InvariantCulture
);
398 else if (type
== typeof(double)) {
399 return double.Parse (value, CultureInfo
.InvariantCulture
);
401 else if (type
== typeof(float)) {
402 return float.Parse (value, CultureInfo
.InvariantCulture
);
404 else if (type
== typeof (TimeSpan
)) {
405 return SoapDuration
.Parse (value);
407 else if(type
.IsEnum
) {
408 return Enum
.Parse(type
, value);
411 return Convert
.ChangeType (value, type
, CultureInfo
.InvariantCulture
);