Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / mcs / class / System.Runtime.Serialization.Formatters.Soap / System.Runtime.Serialization.Formatters.Soap / SoapWriter.cs
1 // created on 07/04/2003 at 17:56\r
2 //\r
3 //      System.Runtime.Serialization.Formatters.Soap.SoapWriter\r
4 //\r
5 //      Authors:\r
6 //              Jean-Marc Andre (jean-marc.andre@polymtl.ca)\r
7 //\r
8 \r
9 //\r
10 // Permission is hereby granted, free of charge, to any person obtaining\r
11 // a copy of this software and associated documentation files (the\r
12 // "Software"), to deal in the Software without restriction, including\r
13 // without limitation the rights to use, copy, modify, merge, publish,\r
14 // distribute, sublicense, and/or sell copies of the Software, and to\r
15 // permit persons to whom the Software is furnished to do so, subject to\r
16 // the following conditions:\r
17 // \r
18 // The above copyright notice and this permission notice shall be\r
19 // included in all copies or substantial portions of the Software.\r
20 // \r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
28 //\r
29 \r
30 using System;\r
31 using System.IO;\r
32 using System.Threading;\r
33 using System.Reflection;\r
34 using System.Collections;\r
35 using System.Runtime.Remoting;\r
36 using System.Runtime.Remoting.Metadata;\r
37 using System.Runtime.Remoting.Messaging;\r
38 using System.Runtime.Serialization;\r
39 using System.Runtime.Serialization.Formatters;\r
40 using System.Xml;\r
41 using System.Xml.Schema;\r
42 using System.Xml.Serialization;\r
43 using System.Globalization;\r
44 using System.Text;\r
45 \r
46 namespace System.Runtime.Serialization.Formatters.Soap {\r
47         \r
48         internal class SoapWriter: IComparer {\r
49                 private struct EnqueuedObject {\r
50                         public long _id;\r
51                         public object _object;\r
52                         \r
53                         public EnqueuedObject(object currentObject, long id) {\r
54                                 _id = id;\r
55                                 _object = currentObject;\r
56                         }\r
57 \r
58                         public long Id \r
59                         {\r
60                                 get \r
61                                 {\r
62                                         return _id;\r
63                                 }\r
64                         }\r
65 \r
66                         public object Object \r
67                         {\r
68                                 get \r
69                                 {\r
70                                         return _object;\r
71                                 }\r
72                         }\r
73                 }\r
74                 \r
75                 #region Fields\r
76 \r
77                 private XmlTextWriter _xmlWriter;\r
78                 private Queue _objectQueue = new Queue();\r
79                 private Hashtable _objectToIdTable = new Hashtable();\r
80                 private ISurrogateSelector _surrogateSelector;\r
81                 private SoapTypeMapper _mapper;\r
82                 private StreamingContext _context;\r
83                 private ObjectIDGenerator idGen = new ObjectIDGenerator();\r
84                 private FormatterAssemblyStyle _assemblyFormat = FormatterAssemblyStyle.Full;\r
85                 private FormatterTypeStyle _typeFormat = FormatterTypeStyle.TypesWhenNeeded;\r
86                 private static string defaultMessageNamespace;\r
87 #if NET_2_0\r
88                 SerializationObjectManager _manager;\r
89 #endif\r
90 \r
91                 #endregion\r
92                 \r
93                 ~SoapWriter() \r
94                 {\r
95                 }\r
96 \r
97                 #region Constructors\r
98 \r
99                 internal SoapWriter(\r
100                         Stream outStream, \r
101                         ISurrogateSelector selector, \r
102                         StreamingContext context,\r
103                         ISoapMessage soapMessage)\r
104                 {\r
105                         _xmlWriter = new XmlTextWriter(outStream, null);\r
106                         _xmlWriter.Formatting = Formatting.Indented;\r
107                         _surrogateSelector = selector;\r
108                         _context = context;\r
109 #if NET_2_0\r
110                         _manager = new SerializationObjectManager (_context);\r
111 #endif\r
112                 }\r
113 \r
114                 static SoapWriter() \r
115                 {\r
116                         defaultMessageNamespace = typeof(SoapWriter).Assembly.GetName().FullName;\r
117                 }\r
118 \r
119                 #endregion\r
120                 \r
121                 public SoapTypeMapper Mapper {\r
122                         get { return _mapper; }\r
123                 }\r
124                 \r
125                 public XmlTextWriter XmlWriter {\r
126                         get { return _xmlWriter; }\r
127                 }\r
128 \r
129                 #region Internal Properties\r
130 \r
131                 internal FormatterAssemblyStyle AssemblyFormat\r
132                 {\r
133                         get \r
134                         {\r
135                                 return _assemblyFormat;\r
136                         }\r
137                         set \r
138                         {\r
139                                 _assemblyFormat = value;\r
140                         }\r
141                 }\r
142 \r
143                 internal FormatterTypeStyle TypeFormat \r
144                 {\r
145                         get \r
146                         {\r
147                                 return _typeFormat;\r
148                         }\r
149                         set \r
150                         {\r
151                                 _typeFormat = value;\r
152                         }\r
153                 }\r
154 \r
155                 #endregion\r
156 \r
157                 private void Id(long id) \r
158                 {\r
159                         _xmlWriter.WriteAttributeString(null, "id", null, "ref-" + id.ToString());\r
160                 }\r
161 \r
162                 private void Href(long href) \r
163                 {\r
164                         _xmlWriter.WriteAttributeString(null, "href", null, "#ref-" + href.ToString());\r
165                 }\r
166 \r
167 \r
168                 private void Null() \r
169                 {\r
170                         _xmlWriter.WriteAttributeString("xsi", "null", XmlSchema.InstanceNamespace, "1");\r
171                 }\r
172 \r
173                 private bool IsEncodingNeeded(\r
174                         object componentObject,\r
175                         Type componentType)\r
176                 {\r
177                         if(componentObject == null)\r
178                                 return false;\r
179                         if(_typeFormat == FormatterTypeStyle.TypesAlways)\r
180                                 return true;\r
181                         if(componentType == null) \r
182                         {\r
183                                 componentType = componentObject.GetType();\r
184                                 if(componentType.IsPrimitive || componentType == typeof(string))\r
185                                         return false;\r
186                                 else\r
187                                         return true;\r
188 \r
189                         }\r
190                         else \r
191                         {\r
192                                 if(componentType == typeof(object) || componentType != componentObject.GetType())\r
193                                         return true;\r
194                                 else\r
195                                         return false;\r
196                         }\r
197                 }\r
198 \r
199 \r
200                 internal void Serialize (object objGraph, Header[] headers, FormatterTypeStyle typeFormat, FormatterAssemblyStyle assemblyFormat)\r
201                 {\r
202                         CultureInfo savedCi = CultureInfo.CurrentCulture;\r
203                         try {\r
204                                 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");\r
205                                 Serialize_inner (objGraph, headers, typeFormat, assemblyFormat);\r
206                         } finally {\r
207                                 Thread.CurrentThread.CurrentCulture = savedCi;\r
208                         }\r
209 \r
210 #if NET_2_0\r
211                         _manager.RaiseOnSerializedEvent ();\r
212 #endif\r
213                 }\r
214 \r
215                 void Serialize_inner (object objGraph, Header[] headers, FormatterTypeStyle typeFormat, FormatterAssemblyStyle assemblyFormat)\r
216                 {\r
217                         _typeFormat = typeFormat;\r
218                         _assemblyFormat = assemblyFormat;\r
219                         // Create the XmlDocument with the \r
220                         // Envelope and Body elements\r
221                         _mapper = new SoapTypeMapper(_xmlWriter, assemblyFormat, typeFormat);\r
222 \r
223                         // The root element\r
224                         _xmlWriter.WriteStartElement(\r
225                                 SoapTypeMapper.SoapEnvelopePrefix, \r
226                                 "Envelope",\r
227                                 SoapTypeMapper.SoapEnvelopeNamespace);\r
228 \r
229                         // adding namespaces\r
230                         _xmlWriter.WriteAttributeString(\r
231                                 "xmlns",\r
232                                 "xsi",\r
233                                 "http://www.w3.org/2000/xmlns/",\r
234                                 "http://www.w3.org/2001/XMLSchema-instance");\r
235 \r
236                         _xmlWriter.WriteAttributeString(\r
237                                 "xmlns",\r
238                                 "xsd",\r
239                                 "http://www.w3.org/2000/xmlns/",\r
240                                 XmlSchema.Namespace);\r
241 \r
242                         _xmlWriter.WriteAttributeString(\r
243                                 "xmlns",\r
244                                 SoapTypeMapper.SoapEncodingPrefix,\r
245                                 "http://www.w3.org/2000/xmlns/",\r
246                                 SoapTypeMapper.SoapEncodingNamespace);\r
247 \r
248                         _xmlWriter.WriteAttributeString(\r
249                                 "xmlns",\r
250                                 SoapTypeMapper.SoapEnvelopePrefix,\r
251                                 "http://www.w3.org/2000/xmlns/",\r
252                                 SoapTypeMapper.SoapEnvelopeNamespace);\r
253 \r
254                         _xmlWriter.WriteAttributeString(\r
255                                 "xmlns",\r
256                                 "clr",\r
257                                 "http://www.w3.org/2000/xmlns/",\r
258                                 SoapServices.XmlNsForClrType);\r
259 \r
260                         _xmlWriter.WriteAttributeString(\r
261                                 SoapTypeMapper.SoapEnvelopePrefix,\r
262                                 "encodingStyle",\r
263                                 SoapTypeMapper.SoapEnvelopeNamespace,\r
264                                 "http://schemas.xmlsoap.org/soap/encoding/");\r
265                                                 \r
266                         ISoapMessage msg = objGraph as ISoapMessage;\r
267                         if (msg != null)\r
268                                 headers = msg.Headers;\r
269                         \r
270                         if (headers != null && headers.Length > 0)\r
271                         {\r
272                                 _xmlWriter.WriteStartElement (SoapTypeMapper.SoapEnvelopePrefix, "Header", SoapTypeMapper.SoapEnvelopeNamespace);\r
273                                 foreach (Header h in headers)\r
274                                         SerializeHeader (h);\r
275                                         \r
276                                 WriteObjectQueue ();\r
277                                 _xmlWriter.WriteEndElement ();\r
278                         }\r
279                                 \r
280                         // The body element\r
281                         _xmlWriter.WriteStartElement(\r
282                                 SoapTypeMapper.SoapEnvelopePrefix,\r
283                                 "Body",\r
284                                 SoapTypeMapper.SoapEnvelopeNamespace);\r
285 \r
286 \r
287                         bool firstTime = false;\r
288 \r
289                         if (msg != null)\r
290                                 SerializeMessage(msg);\r
291                         else\r
292                                 _objectQueue.Enqueue(new EnqueuedObject( objGraph, idGen.GetId(objGraph, out firstTime)));\r
293 \r
294                         WriteObjectQueue ();\r
295 \r
296                         _xmlWriter.WriteFullEndElement(); // the body element\r
297                         _xmlWriter.WriteFullEndElement(); // the envelope element\r
298                         _xmlWriter.Flush();\r
299                 }\r
300                 \r
301                 private void WriteObjectQueue ()\r
302                 {\r
303                         while(_objectQueue.Count > 0) \r
304                         {\r
305                                 EnqueuedObject currentEnqueuedObject;\r
306                                 currentEnqueuedObject = (EnqueuedObject) _objectQueue.Dequeue();\r
307                                 object currentObject =  currentEnqueuedObject.Object;\r
308                                 Type currentType = currentObject.GetType();\r
309 \r
310                                 if(!currentType.IsValueType) _objectToIdTable[currentObject] = currentEnqueuedObject.Id;\r
311 \r
312                                 if(currentType.IsArray)\r
313                                         SerializeArray((Array) currentObject, currentEnqueuedObject.Id);\r
314                                 else\r
315                                         SerializeObject(currentObject, currentEnqueuedObject.Id);\r
316                         }\r
317                 }\r
318 \r
319                 private void SerializeMessage(ISoapMessage message) \r
320                 {\r
321                         bool firstTime;\r
322                         string ns = message.XmlNameSpace != null ? message.XmlNameSpace : defaultMessageNamespace;\r
323                         \r
324                         _xmlWriter.WriteStartElement("i2", message.MethodName, ns);\r
325                         Id(idGen.GetId(message, out firstTime));\r
326 \r
327                         string[] paramNames = message.ParamNames;\r
328                         object[] paramValues = message.ParamValues;\r
329                         int length = (paramNames != null)?paramNames.Length:0;\r
330                         for(int i = 0; i < length; i++) \r
331                         {\r
332                                 _xmlWriter.WriteStartElement(paramNames[i]);\r
333                                 SerializeComponent(paramValues[i], true);\r
334                                 _xmlWriter.WriteEndElement();\r
335                         }\r
336 \r
337 \r
338                         _xmlWriter.WriteFullEndElement();\r
339                 }\r
340                 \r
341                 private void SerializeHeader (Header header)\r
342                 {\r
343                         string ns = header.HeaderNamespace != null ? header.HeaderNamespace : "http://schemas.microsoft.com/clr/soap"; \r
344                         _xmlWriter.WriteStartElement ("h4", header.Name, ns);\r
345                         if (header.MustUnderstand)\r
346                                 _xmlWriter.WriteAttributeString ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace, "1");\r
347                         _xmlWriter.WriteAttributeString ("root", SoapTypeMapper.SoapEncodingNamespace, "1");\r
348                         \r
349                         if (header.Name == "__MethodSignature") {\r
350                                 // This is a lame way of identifying the signature header, but looks like it is\r
351                                 // what MS.NET does.\r
352                                 Type[] val = header.Value as Type[];\r
353                                 if (val == null)\r
354                                         throw new SerializationException ("Invalid method signature.");\r
355                                 SerializeComponent (new MethodSignature (val), true);\r
356                         } else\r
357                                 SerializeComponent (header.Value, true);\r
358                                 \r
359                         _xmlWriter.WriteEndElement();\r
360                 }\r
361 \r
362                 private void SerializeObject(object currentObject, long currentObjectId) \r
363                 {\r
364                         bool needsSerializationInfo = false;\r
365                         ISurrogateSelector selector;\r
366                         ISerializationSurrogate surrogate = null;\r
367                         if(_surrogateSelector != null)\r
368                         {\r
369                                  surrogate = _surrogateSelector.GetSurrogate(\r
370                                         currentObject.GetType(),\r
371                                         _context,\r
372                                         out selector);\r
373                         }\r
374                         if(currentObject is ISerializable || surrogate != null) needsSerializationInfo = true;\r
375 \r
376 #if NET_2_0\r
377                         _manager.RegisterObject (currentObject);\r
378 #endif\r
379 \r
380                         if(needsSerializationInfo) \r
381                         {\r
382                                 SerializeISerializableObject(currentObject, currentObjectId, surrogate);\r
383                         }\r
384                         else \r
385                         {\r
386                                 if(!currentObject.GetType().IsSerializable)\r
387                                         throw new SerializationException(String.Format("Type {0} in assembly {1} is not marked as serializable.", currentObject.GetType(), currentObject.GetType().Assembly.FullName));\r
388                                 SerializeSimpleObject(currentObject, currentObjectId);\r
389                         }\r
390                 }\r
391 \r
392                 // implement IComparer\r
393                 public int Compare(object x, object y) \r
394                 {\r
395                         MemberInfo a = x as MemberInfo;\r
396                         MemberInfo b = y as MemberInfo;\r
397 \r
398                         return String.Compare(a.Name, b.Name);\r
399                 }\r
400 \r
401                 private void SerializeSimpleObject(\r
402                         object currentObject, \r
403                         long currentObjectId) \r
404                 {\r
405                         Type currentType = currentObject.GetType();\r
406                         \r
407                         // Value type have to be serialized "on the fly" so\r
408                         // SerializeComponent calls SerializeObject when\r
409                         // a field of another object is a struct. A node with the field\r
410                         // name has already be written so WriteStartElement must not be called\r
411                         // again. Fields that are structs are passed to SerializeObject\r
412                         // with a id = 0\r
413                         if(currentObjectId > 0)\r
414                         {\r
415                                 Element element = _mapper.GetXmlElement (currentType);\r
416                                 _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
417                                 Id(currentObjectId);\r
418                         }\r
419 \r
420                         if (currentType == typeof(TimeSpan))\r
421                         {\r
422                                 _xmlWriter.WriteString(SoapTypeMapper.GetXsdValue(currentObject));\r
423                         }\r
424                         else if(currentType == typeof(string))\r
425                         {\r
426                                 _xmlWriter.WriteString(currentObject.ToString());\r
427                         }\r
428                         else\r
429                         {\r
430                                 MemberInfo[] memberInfos = FormatterServices.GetSerializableMembers(currentType, _context);\r
431                                 object[] objectData = FormatterServices.GetObjectData(currentObject, memberInfos);\r
432                                 \r
433                                 for(int i = 0; i < memberInfos.Length; i++) \r
434                                 {\r
435                                         FieldInfo fieldInfo = (FieldInfo) memberInfos[i];\r
436                                         SoapFieldAttribute at = (SoapFieldAttribute) InternalRemotingServices.GetCachedSoapAttribute (fieldInfo);\r
437                                         _xmlWriter.WriteStartElement (XmlConvert.EncodeLocalName (at.XmlElementName));\r
438                                         SerializeComponent(\r
439                                                 objectData[i], \r
440                                                 IsEncodingNeeded(objectData[i], fieldInfo.FieldType));\r
441                                         _xmlWriter.WriteEndElement();\r
442                                 }\r
443                         }\r
444                         if(currentObjectId > 0)\r
445                                 _xmlWriter.WriteFullEndElement();\r
446 \r
447                 }\r
448                 \r
449                 \r
450                 private void SerializeISerializableObject(\r
451                         object currentObject,\r
452                         long currentObjectId,\r
453                         ISerializationSurrogate surrogate)\r
454                 {\r
455                         Type currentType = currentObject.GetType();\r
456                         SerializationInfo info = new SerializationInfo(currentType, new FormatterConverter());\r
457 \r
458 \r
459                         ISerializable objISerializable = currentObject as ISerializable;\r
460                         if(surrogate != null) surrogate.GetObjectData(currentObject, info, _context);\r
461                         else\r
462                         {\r
463                                 objISerializable.GetObjectData(info, _context);\r
464                         }\r
465 \r
466                         // Same as above\r
467                         if(currentObjectId > 0L)\r
468                         {\r
469                                 Element element = _mapper. GetXmlElement (info.FullTypeName, info.AssemblyName);\r
470                                 _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
471                                 Id(currentObjectId);\r
472                         }\r
473 \r
474                         foreach(SerializationEntry entry in info)\r
475                         {\r
476                                 _xmlWriter.WriteStartElement(XmlConvert.EncodeLocalName (entry.Name));\r
477                                 SerializeComponent(entry.Value, IsEncodingNeeded(entry.Value, null));\r
478                                 _xmlWriter.WriteEndElement();\r
479                         }\r
480                         if(currentObjectId > 0)\r
481                                 _xmlWriter.WriteFullEndElement();\r
482 \r
483                 }\r
484 \r
485                 private void SerializeArray(Array currentArray, long currentArrayId) \r
486                 {\r
487                         Element element = _mapper.GetXmlElement (typeof(System.Array));\r
488                         \r
489 \r
490                         // Set the arrayType attribute\r
491                         Type arrayType = currentArray.GetType().GetElementType();\r
492                         Element xmlArrayType = _mapper.GetXmlElement (arrayType);\r
493                         _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
494                         if(currentArrayId > 0) Id(currentArrayId);\r
495                         \r
496                         if (arrayType == typeof(byte)) {\r
497                                 EncodeType (currentArray.GetType());\r
498                                 _xmlWriter.WriteString (Convert.ToBase64String ((byte[])currentArray));\r
499                                 _xmlWriter.WriteFullEndElement();\r
500                                 return;\r
501                         }\r
502 \r
503                         string prefix = GetNamespacePrefix (xmlArrayType);\r
504 \r
505                         StringBuilder str = new StringBuilder();\r
506                         str.AppendFormat("{0}:{1}[", prefix, xmlArrayType.LocalName);\r
507                         for(int i = 0; i < currentArray.Rank; i++)\r
508                         {\r
509                                 str.AppendFormat("{0},", currentArray.GetUpperBound(i) + 1);\r
510                         }\r
511                         str.Replace(',', ']', str.Length - 1, 1);\r
512                         _xmlWriter.WriteAttributeString(\r
513                                 SoapTypeMapper.SoapEncodingPrefix,\r
514                                 "arrayType",\r
515                                 SoapTypeMapper.SoapEncodingNamespace,\r
516                                 str.ToString());\r
517                                 \r
518 \r
519                         // Get the array items\r
520                         int lastNonNullItem = 0;\r
521                         int currentIndex = 0;\r
522 //                      bool specifyEncoding = false;\r
523                         foreach(object item in currentArray) \r
524                         {\r
525                                 if(item != null)\r
526                                 {\r
527                                         for(int j = lastNonNullItem; j < currentIndex; j++)\r
528                                         {\r
529                                                 _xmlWriter.WriteStartElement("item");\r
530                                                 Null();\r
531                                                 _xmlWriter.WriteEndElement();\r
532                                         }; \r
533                                         lastNonNullItem = currentIndex + 1;\r
534 //                                      specifyEncoding |= (arrayType != item.GetType());\r
535                                         _xmlWriter.WriteStartElement("item");\r
536                                         SerializeComponent(item, IsEncodingNeeded(item, arrayType));\r
537                                         _xmlWriter.WriteEndElement();\r
538                                 }\r
539                                 currentIndex++;\r
540                         }\r
541                         _xmlWriter.WriteFullEndElement();\r
542                         \r
543                 }\r
544 \r
545                 private void SerializeComponent(\r
546                         object obj,\r
547                         bool specifyEncoding)\r
548                 {\r
549                         if(_typeFormat == FormatterTypeStyle.TypesAlways)\r
550                                 specifyEncoding = true;\r
551 \r
552                         // A null component\r
553                         if(obj == null)\r
554                         {\r
555                                 Null();\r
556                                 return;\r
557                         }\r
558                         Type objType = obj.GetType();\r
559                         bool canBeValue = _mapper.IsInternalSoapType (objType);\r
560                         bool firstTime;\r
561                         long id = 0;\r
562                         \r
563                         // An object already serialized\r
564                         if((id = idGen.HasId(obj, out firstTime)) != 0L) \r
565                         {\r
566                                 Href((long)idGen.GetId(obj, out firstTime));\r
567                                 return;\r
568                         }\r
569 \r
570 \r
571 \r
572                         // A string\r
573                         if(objType == typeof(string)) \r
574                         {\r
575                                 if(_typeFormat != FormatterTypeStyle.XsdString)\r
576                                 {\r
577                                         id = idGen.GetId(obj, out firstTime);\r
578                                         Id(id);\r
579                                 }\r
580 //                              specifyEncoding = false;\r
581                         }\r
582 \r
583                         // This component has to be \r
584                         // serialized later\r
585                         if(!canBeValue && !objType.IsValueType)\r
586                         {\r
587                                 long href = idGen.GetId(obj, out firstTime);\r
588                                 Href(href);\r
589                                 _objectQueue.Enqueue(new EnqueuedObject(obj, href));\r
590                                 return;\r
591                         }\r
592 \r
593                         if(specifyEncoding)\r
594                         {\r
595                                 EncodeType(objType);\r
596                         }\r
597 \r
598                         // A struct\r
599                         if(!canBeValue && objType.IsValueType)\r
600                         {\r
601                                 SerializeObject(obj, 0);\r
602                                 return;\r
603                         }\r
604 \r
605                         _xmlWriter.WriteString (_mapper.GetInternalSoapValue (this, obj));\r
606                 }\r
607                 \r
608                 private void EncodeType(Type type) \r
609                 {\r
610                         if(type == null) \r
611                                 throw new SerializationException("Oooops");\r
612 \r
613                         Element xmlType = _mapper.GetXmlElement (type);\r
614 \r
615                         string prefix = GetNamespacePrefix (xmlType);\r
616                         \r
617                         _xmlWriter.WriteAttributeString (\r
618                                 "xsi",\r
619                                 "type",\r
620                                 "http://www.w3.org/2001/XMLSchema-instance",\r
621                                 prefix + ":" + xmlType.LocalName);\r
622                 }\r
623                 \r
624                 public string GetNamespacePrefix (Element xmlType)\r
625                 {\r
626                         string prefix = _xmlWriter.LookupPrefix (xmlType.NamespaceURI);\r
627                         if(prefix == null || prefix == string.Empty) \r
628                         {\r
629                                 _xmlWriter.WriteAttributeString(\r
630                                         "xmlns",\r
631                                         xmlType.Prefix,\r
632                                         "http://www.w3.org/2000/xmlns/",\r
633                                         xmlType.NamespaceURI);\r
634                                 return xmlType.Prefix;\r
635                         }\r
636                         return prefix;\r
637                 }\r
638         }\r
639 }\r