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 using System.Reflection;
11 using System.Collections;
12 using System.Runtime.Remoting;
14 using System.Xml.Serialization;
15 using System.Runtime.Serialization.Formatters;
16 using System.Xml.Schema;
17 using System.Runtime.Remoting.Metadata.W3cXsd2001;
18 using System.Globalization;
20 namespace System.Runtime.Serialization.Formatters.Soap {
22 internal class Element
24 private string _prefix;
25 private string _localName;
26 private string _namespaceURI;
28 public Element(string prefix, string localName, string namespaceURI)
31 _localName = localName;
32 _namespaceURI = namespaceURI;
35 public Element(string localName, string namespaceURI): this(null, localName, namespaceURI)
47 public string LocalName
55 public string NamespaceURI
63 public override bool Equals(object obj)
65 Element element = obj as Element;
66 return (_localName == XmlConvert.DecodeName(element._localName) &&
67 _namespaceURI == XmlConvert.DecodeName(element._namespaceURI))?true:false;
70 public override int GetHashCode()
72 return (String.Format("{0} {1}",
73 XmlConvert.DecodeName(_localName),
74 XmlConvert.DecodeName(_namespaceURI))).GetHashCode();
77 public override string ToString()
79 return string.Format("Element.Prefix = {0}, Element.LocalName = {1}, Element.NamespaceURI = {2}", this.Prefix, this.LocalName, this.NamespaceURI);
83 internal class SoapTypeMapper {
84 private static Hashtable xmlNodeToTypeTable = new Hashtable();
85 private static Hashtable typeToXmlNodeTable = new Hashtable();
86 public static readonly string SoapEncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
87 public static readonly string SoapEncodingPrefix = "SOAP-ENC";
88 public static readonly string SoapEnvelopeNamespace = "http://schemas.xmlsoap.org/soap/envelope/";
89 public static readonly string SoapEnvelopePrefix = "SOAP-ENV";
90 internal static readonly string SoapEnvelope;
91 private XmlTextWriter _xmlWriter;
92 private long _prefixNumber;
93 private Hashtable namespaceToPrefixTable = new Hashtable();
94 private SerializationBinder _binder;
95 private static ArrayList _canBeValueTypeList;
96 private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;
97 private Element elementString;
100 // Constructor used by SoapReader
101 public SoapTypeMapper(SerializationBinder binder)
106 // Constructor used by SoapWriter
107 public SoapTypeMapper(
108 XmlTextWriter xmlWriter,
109 FormatterAssemblyStyle assemblyFormat,
110 FormatterTypeStyle typeFormat)
112 _xmlWriter = xmlWriter;
113 _assemblyFormat = assemblyFormat;
117 elementType = typeof(string);
118 if(typeFormat == FormatterTypeStyle.XsdString)
\r
120 elementString = new Element("xsd", "string", XmlSchema.Namespace);
124 elementString = new Element(SoapEncodingPrefix, "string", SoapEncodingNamespace);
126 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
129 static SoapTypeMapper() {
130 // SoapEnvelope = String.Format(
131 // "<{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/'/>",
132 // SoapEnvelopePrefix,
133 // SoapEnvelopeNamespace,
134 // XmlSchema.Namespace,
135 // SoapEncodingPrefix,
136 // SoapEncodingNamespace,
137 // SoapServices.XmlNsForClrType);
138 _canBeValueTypeList = new ArrayList();
139 _canBeValueTypeList.Add(typeof(DateTime).ToString());
140 _canBeValueTypeList.Add(typeof(TimeSpan).ToString());
141 _canBeValueTypeList.Add(typeof(string).ToString());
142 _canBeValueTypeList.Add(typeof(decimal).ToString());
143 _canBeValueTypeList.Sort();
148 public Type this[Element element]
154 string localName = XmlConvert.DecodeName(element.LocalName);
155 string namespaceURI = XmlConvert.DecodeName(element.NamespaceURI);
156 string typeNamespace, assemblyName;
157 SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
158 element.NamespaceURI,
161 string typeName = typeNamespace + Type.Delimiter + localName;
163 if(assemblyName != null && assemblyName != string.Empty && _binder != null)
165 type = _binder.BindToType(assemblyName, typeName);
169 string assemblyQualifiedName = (string)xmlNodeToTypeTable[element];
170 if(assemblyQualifiedName != null)
171 type = Type.GetType(assemblyQualifiedName);
175 type = Type.GetType(element.LocalName);
179 type = Type.GetType(typeName);
183 if(assemblyName == null || assemblyName == String.Empty)
184 throw new SerializationException(
185 String.Format("Parse Error, no assembly associated with XML key {0} {1}",
188 type = FormatterServices.GetTypeFromAssembly(
189 Assembly.Load(assemblyName),
195 throw new SerializationException();
202 public Element this[string typeFullName, string assemblyName]
207 string typeNamespace = string.Empty;
208 string typeName = typeFullName;
209 if(_assemblyFormat == FormatterAssemblyStyle.Simple)
\r
211 string[] items = assemblyName.Split(',');
212 assemblyName = items[0];
214 string assemblyQualifiedName = typeFullName + ", " + assemblyName;
215 element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
218 int typeNameIndex = typeFullName.LastIndexOf('.');
219 if(typeNameIndex != -1)
221 typeNamespace = typeFullName.Substring(0, typeNameIndex);
222 typeName = typeFullName.Substring(typeNamespace.Length + 1);
224 string namespaceURI =
225 SoapServices.CodeXmlNamespaceForClrTypeNamespace(
227 (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
228 string prefix = (string) namespaceToPrefixTable[namespaceURI];
229 if(prefix == null || prefix == string.Empty)
231 prefix = "a" + (_prefixNumber++).ToString();
232 namespaceToPrefixTable[namespaceURI] = prefix;
235 element = new Element(
237 XmlConvert.EncodeName(typeName),
244 public Element this[Type type]
248 if(type == typeof(string)) return elementString;
249 Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
252 element = this[type.FullName, type.Assembly.FullName];
253 // if(_assemblyFormat == FormatterAssemblyStyle.Full)
254 // element = this[type.FullName, type.Assembly.FullName];
256 // element = this[type.FullName, type.Assembly.GetName().Name];
261 element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
264 throw new SerializationException("Oooops");
269 public static bool CanBeValue(Type type)
271 if(type.IsPrimitive) return true;
272 if(type.IsEnum) return true;
273 if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0)
280 private static void InitMappingTables()
284 element = new Element("Array", SoapEncodingNamespace);
285 elementType = typeof(System.Array);
286 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
287 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
289 element = new Element("string", XmlSchema.Namespace);
290 elementType = typeof(string);
291 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
292 // typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
294 element = new Element("string", SoapEncodingNamespace);
295 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
297 element = new Element("long", XmlSchema.Namespace);
298 elementType = typeof(long);
299 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
300 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
302 element = new Element("int", XmlSchema.Namespace);
303 elementType = typeof(int);
304 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
305 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
307 element = new Element("float", XmlSchema.Namespace);
308 elementType = typeof(float);
309 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
310 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
312 element = new Element("decimal", XmlSchema.Namespace);
313 elementType = typeof(decimal);
314 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
315 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
317 element = new Element("short", XmlSchema.Namespace);
318 elementType = typeof(short);
319 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
320 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
322 element = new Element("anyType", XmlSchema.Namespace);
323 elementType = typeof(object);
324 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
325 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
327 element = new Element("dateTime", XmlSchema.Namespace);
328 elementType = typeof(DateTime);
329 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
330 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
332 element = new Element("duration", XmlSchema.Namespace);
333 elementType = typeof(TimeSpan);
334 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
335 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
337 element = new Element("Fault", SoapEnvelopeNamespace);
338 elementType = typeof(System.Runtime.Serialization.Formatters.SoapFault);
339 xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
340 typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
345 public static string GetXsdValue (object value)
347 if (value is DateTime) {
348 return SoapDateTime.ToString ((DateTime)value);
350 else if (value is decimal) {
351 return ((decimal) value).ToString (CultureInfo.InvariantCulture);
353 else if (value is double) {
354 return ((double) value).ToString (CultureInfo.InvariantCulture);
356 else if (value is float) {
357 return ((float) value).ToString (CultureInfo.InvariantCulture);
359 else if (value is TimeSpan) {
360 return SoapDuration.ToString ((TimeSpan)value);
363 return value.ToString ();
367 public static object ParseXsdValue (string value, Type type)
369 if (type == typeof(DateTime)) {
370 return SoapDateTime.Parse (value);
372 else if (type == typeof(decimal)) {
373 return decimal.Parse (value, CultureInfo.InvariantCulture);
375 else if (type == typeof(double)) {
376 return double.Parse (value, CultureInfo.InvariantCulture);
378 else if (type == typeof(float)) {
379 return float.Parse (value, CultureInfo.InvariantCulture);
381 else if (type == typeof (TimeSpan)) {
382 return SoapDuration.Parse (value);
384 else if(type.IsEnum) {
385 return Enum.Parse(type, value);
388 return Convert.ChangeType (value, type, CultureInfo.InvariantCulture);