Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializationWriterInterpreter.cs
1 //
2 // XmlSerializationWriterInterpreter.cs: 
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Text;
33 using System.Collections;
34 using System.Reflection;
35 using System.Xml.Schema;
36
37 namespace System.Xml.Serialization
38 {
39         internal class XmlSerializationWriterInterpreter: XmlSerializationWriter
40         {
41                 XmlMapping _typeMap;
42                 SerializationFormat _format;
43                 const string xmlNamespace = "http://www.w3.org/2000/xmlns/";
44
45                 public XmlSerializationWriterInterpreter (XmlMapping typeMap)
46                 {
47                         _typeMap = typeMap;
48                         _format = typeMap.Format;
49                 }
50
51                 protected override void InitCallbacks ()
52                 {
53                         ArrayList maps = _typeMap.RelatedMaps;
54                         if (maps != null)
55                         {
56                                 foreach (XmlTypeMapping map in maps)  {
57                                         CallbackInfo info = new CallbackInfo (this, map);
58                                         if (map.TypeData.SchemaType == SchemaTypes.Enum) AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteEnum));
59                                         else AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteObject));
60                                 }
61                         }
62                 }
63
64                 public void WriteRoot (object ob)
65                 {
66                         WriteStartDocument ();
67
68                         if (_typeMap is XmlTypeMapping)
69                         {
70                                 XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
71                                 if (mp.TypeData.SchemaType == SchemaTypes.Class || mp.TypeData.SchemaType == SchemaTypes.Array) 
72                                         TopLevelElement ();
73
74                                 if (_format == SerializationFormat.Literal)
75                                         WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false, true);
76                                 else
77                                         WritePotentiallyReferencingElement (mp.ElementName, mp.Namespace, ob, mp.TypeData.Type, true, false);
78                         }
79                         else if (ob is object[])
80                                 WriteMessage ((XmlMembersMapping)_typeMap, (object[]) ob);
81                         else
82                                 throw CreateUnknownTypeException (ob);
83
84                         WriteReferencedElements ();
85                 }
86                 
87                 protected XmlTypeMapping GetTypeMap (Type type)
88                 {
89                         ArrayList maps = _typeMap.RelatedMaps;
90                         if (maps != null)
91                         {
92                                 foreach (XmlTypeMapping map in maps)
93                                         if (map.TypeData.Type == type) return map;
94                         }
95                         throw new InvalidOperationException ("Type " + type + " not mapped");
96                 }
97
98                 protected virtual void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)
99                 {
100                         if (ob == null)
101                         {
102                                 if (isNullable) 
103                                 {
104                                         if (_format == SerializationFormat.Literal) WriteNullTagLiteral(element, namesp);
105                                         else WriteNullTagEncoded (element, namesp);
106                                 }
107                                 return;
108                         }
109
110                         if (ob is XmlNode)
111                         {
112                                 if (_format == SerializationFormat.Literal) WriteElementLiteral((XmlNode)ob, "", "", true, typeMap.IsAny);
113                                 else WriteElementEncoded((XmlNode)ob, "", "", true, typeMap.IsAny);
114                                 return;
115                         }
116
117                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlSerializable)
118                         {
119                                 WriteSerializable ((IXmlSerializable)ob, element, namesp, isNullable, !typeMap.IsAny);
120                                 return;
121                         }
122
123                         var obExpectedType = typeMap.TypeData.Type;
124                         if (!ob.GetType().IsAssignableFrom (obExpectedType))
125                                 ob = ImplicitConvert (ob, obExpectedType);
126
127                         XmlTypeMapping map = typeMap.GetRealTypeMap (ob.GetType());
128
129                         if (map == null) 
130                         {
131                                 // bug #81539
132                                 if (ob.GetType ().IsArray && typeof (XmlNode).IsAssignableFrom (ob.GetType ().GetElementType ())) {
133                                         Writer.WriteStartElement (element, namesp);
134                                         foreach (XmlNode node in (IEnumerable) ob)
135                                                 node.WriteTo (Writer);
136                                         Writer.WriteEndElement ();
137                                 }
138                                 else
139                                         WriteTypedPrimitive (element, namesp, ob, true);
140                                 return;
141                         }
142
143                         if (writeWrappingElem)
144                         {
145                                 if (map != typeMap || _format == SerializationFormat.Encoded) needType = true;
146                                 WriteStartElement (element, namesp, ob);
147                         }
148
149                         if (needType) 
150                                 WriteXsiType(map.XmlType, map.XmlTypeNamespace);
151
152                         switch (map.TypeData.SchemaType)
153                         {
154                                 case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp); break;
155                                 case SchemaTypes.Array: WriteListElement (map, ob, element, namesp); break;
156                                 case SchemaTypes.Primitive: WritePrimitiveElement (map, ob, element, namesp); break;
157                                 case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp); break;
158                         }
159
160                         if (writeWrappingElem)
161                                 WriteEndElement (ob);
162                 }
163
164                 protected virtual void WriteMessage (XmlMembersMapping membersMap, object[] parameters)
165                 {
166                         if (membersMap.HasWrapperElement) {
167                                 TopLevelElement ();
168                                 WriteStartElement(membersMap.ElementName, membersMap.Namespace, (_format == SerializationFormat.Encoded));
169
170                                 if (Writer.LookupPrefix (XmlSchema.Namespace) == null)
171                                         WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
172         
173                                 if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)
174                                         WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);
175                         }
176                         
177                         WriteMembers ((ClassMap)membersMap.ObjectMap, parameters, true);
178
179                         if (membersMap.HasWrapperElement)
180                                 WriteEndElement();
181                 }
182
183                 protected virtual void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
184                 {
185                         ClassMap map = (ClassMap)typeMap.ObjectMap;
186                         if (map.NamespaceDeclarations != null)
187                                 WriteNamespaceDeclarations ((XmlSerializerNamespaces) map.NamespaceDeclarations.GetValue (ob));
188                         
189                         WriteObjectElementAttributes (typeMap, ob);
190                         WriteObjectElementElements (typeMap, ob);
191                 }
192                 
193                 protected virtual void WriteObjectElementAttributes (XmlTypeMapping typeMap, object ob)
194                 {
195                         ClassMap map = (ClassMap)typeMap.ObjectMap;
196                         WriteAttributeMembers (map, ob, false);
197                 }
198
199                 protected virtual void WriteObjectElementElements (XmlTypeMapping typeMap, object ob)
200                 {
201                         ClassMap map = (ClassMap)typeMap.ObjectMap;
202                         WriteElementMembers (map, ob, false);
203                 }
204
205                 void WriteMembers (ClassMap map, object ob, bool isValueList)
206                 {
207                         WriteAttributeMembers (map, ob, isValueList);
208                         WriteElementMembers (map, ob, isValueList);
209                 }
210                 
211                 void WriteAttributeMembers (ClassMap map, object ob, bool isValueList)
212                 {
213                         // Write attributes
214
215                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
216                         if (anyAttrMember != null && MemberHasValue (anyAttrMember, ob, isValueList))
217                         {
218                                 ICollection extraAtts = (ICollection) GetMemberValue (anyAttrMember, ob, isValueList);
219                                 if (extraAtts != null) 
220                                 {
221                                         foreach (XmlAttribute attr in extraAtts)
222                                                 if (attr.NamespaceURI != xmlNamespace)
223                                                         WriteXmlAttribute (attr, ob);
224                                 }
225                         }
226
227                         ICollection attributes = map.AttributeMembers;
228                         if (attributes != null)
229                         {
230                                 foreach (XmlTypeMapMemberAttribute attr in attributes) {
231                                         if (MemberHasValue (attr, ob, isValueList))
232                                                 WriteAttribute (attr.AttributeName, attr.Namespace, GetStringValue (attr.MappedType, attr.TypeData, GetMemberValue (attr, ob, isValueList)));
233                                 }
234                         }
235                 }
236
237                 void WriteElementMembers (ClassMap map, object ob, bool isValueList)
238                 {
239                         ICollection members = map.ElementMembers;
240                         if (members != null)
241                         {
242                                 foreach (XmlTypeMapMemberElement member in members)
243                                 {
244                                         if (!MemberHasValue (member, ob, isValueList)) continue;
245                                         object memberValue = GetMemberValue (member, ob, isValueList);
246                                         Type memType = member.GetType();
247
248                                         if (memType == typeof(XmlTypeMapMemberList))
249                                         {
250                                                 WriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
251                                         }
252                                         else if (memType == typeof(XmlTypeMapMemberFlatList))
253                                         {
254                                                 if (memberValue != null)
255                                                         WriteListContent (ob, member.TypeData, ((XmlTypeMapMemberFlatList)member).ListMap, memberValue, null);
256                                         }
257                                         else if (memType == typeof(XmlTypeMapMemberAnyElement))
258                                         {
259                                                 if (memberValue != null)
260                                                         WriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
261                                         }
262                                         else if (memType == typeof(XmlTypeMapMemberAnyAttribute))
263                                         {
264                                                 // Ignore
265                                         }
266                                         else if (memType == typeof(XmlTypeMapMemberElement))
267                                         {
268                                                 XmlTypeMapElementInfo elem = member.FindElement (ob, memberValue);
269                                                 WriteMemberElement (elem, memberValue);
270                                         }
271                                         else
272                                                 throw new InvalidOperationException ("Unknown member type");
273                                 }
274                         }
275                 }
276
277                 object GetMemberValue (XmlTypeMapMember member, object ob, bool isValueList)
278                 {
279                         if (isValueList) return ((object[])ob)[member.GlobalIndex];
280                         else return member.GetValue (ob);
281                 }
282
283                 bool MemberHasValue (XmlTypeMapMember member, object ob, bool isValueList)
284                 {
285                         if (isValueList) {
286                                 if (member.IsOptionalValueType && !member.GetValueSpecified (ob))
287                                         return false;
288                                 return member.GlobalIndex < ((object[])ob).Length;
289                         }
290                         else if (member.DefaultValue != System.DBNull.Value) {
291                                 object val = GetMemberValue (member, ob, isValueList);
292                                 if (val == null && member.DefaultValue == null) return false;
293                                 if (val != null && val.GetType().IsEnum)
294                                 {
295                                         if (val.Equals (member.DefaultValue)) return false;
296                                         Type t = Enum.GetUnderlyingType(val.GetType());
297                                         val = Convert.ChangeType (val, t, null);
298                                 }
299                                 if (val != null && val.Equals (member.DefaultValue)) return false;
300                         }
301                         else if (member.IsOptionalValueType)
302                                 return member.GetValueSpecified (ob);
303
304                         return true;
305                 }
306
307                 void WriteMemberElement (XmlTypeMapElementInfo elem, object memberValue)
308                 {
309                         switch (elem.TypeData.SchemaType)
310                         {
311                                 case SchemaTypes.XmlNode:
312                                         string elemName = elem.WrappedElement ? elem.ElementName : "";
313                                         if (_format == SerializationFormat.Literal) WriteElementLiteral(((XmlNode)memberValue), elemName, elem.Namespace, elem.IsNullable, false);
314                                         else WriteElementEncoded(((XmlNode)memberValue), elemName, elem.Namespace, elem.IsNullable, false);
315                                         break;
316
317                                 case SchemaTypes.Enum:
318                                 case SchemaTypes.Primitive:
319                                         if (_format == SerializationFormat.Literal) 
320                                                 WritePrimitiveValueLiteral (memberValue, elem.ElementName, elem.Namespace, elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
321                                         else 
322                                                 WritePrimitiveValueEncoded (memberValue, elem.ElementName, elem.Namespace, new XmlQualifiedName (elem.DataTypeName, elem.DataTypeNamespace), elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
323                                         break;
324
325                                 case SchemaTypes.Array:
326                                         if (memberValue == null) {
327                                                 if (!elem.IsNullable) return;
328                                                 if (_format == SerializationFormat.Literal) WriteNullTagLiteral (elem.ElementName, elem.Namespace);
329                                                 else WriteNullTagEncoded (elem.ElementName, elem.Namespace);
330                                         }
331                                         else if (elem.MappedType.MultiReferenceType) 
332                                                 WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
333                                         else {
334                                                 WriteStartElement(elem.ElementName, elem.Namespace, memberValue);
335                                                 WriteListContent (null, elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue, null);
336                                                 WriteEndElement (memberValue);
337                                         }
338                                         break;
339
340                                 case SchemaTypes.Class:
341                                         if (elem.MappedType.MultiReferenceType) {
342                                                 if (elem.MappedType.TypeData.Type == typeof(object))
343                                                         WritePotentiallyReferencingElement (elem.ElementName, elem.Namespace, memberValue, null, false, elem.IsNullable);
344                                                 else
345                                                         WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
346                                         }
347                                         else WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false, true);
348                                         break;
349
350                                 case SchemaTypes.XmlSerializable:
351                                         // bug #419973
352                                         if (!elem.MappedType.TypeData.Type.IsInstanceOfType (memberValue))
353                                                 memberValue = ImplicitConvert (memberValue, elem.MappedType.TypeData.Type);
354                                         WriteSerializable ((IXmlSerializable) memberValue, elem.ElementName, elem.Namespace, elem.IsNullable);
355                                         break;
356
357                                 default:
358                                         throw new NotSupportedException ("Invalid value type");
359                         }
360                 }
361
362                 internal static object ImplicitConvert (object obj, Type type)
363                 {
364                         if (obj == null)
365                                 return null;
366
367                         for (Type t = obj.GetType (); t != typeof (object); t = t.BaseType) {
368                                 MethodInfo mi = t.GetMethod ("op_Implicit", new Type [] {t});
369                                 if (mi != null && mi.ReturnType == type)
370                                         return mi.Invoke (null, new object [] {obj});
371
372                                 mi = type.GetMethod ("op_Implicit", new Type [] {t});
373                                 if (mi != null && mi.ReturnType == type)
374                                         return mi.Invoke (null, new object [] {obj});
375                         }
376                         return obj;
377                 }
378
379                 void WritePrimitiveValueLiteral (object memberValue, string name, string ns, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
380                 {
381                         if (!wrapped) {
382                                 WriteValue (GetStringValue (mappedType, typeData, memberValue));
383                         }
384                         else if (isNullable) {
385                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteNullableQualifiedNameLiteral (name, ns, (XmlQualifiedName)memberValue);
386                                 else WriteNullableStringLiteral (name, ns, GetStringValue (mappedType, typeData, memberValue));
387                         }
388                         else {
389                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteElementQualifiedName (name, ns, (XmlQualifiedName)memberValue);
390                                 else WriteElementString (name, ns, GetStringValue (mappedType, typeData, memberValue));
391                         }
392                 }
393
394                 void WritePrimitiveValueEncoded (object memberValue, string name, string ns, XmlQualifiedName xsiType, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
395                 {
396                         if (!wrapped) {
397                                 WriteValue (GetStringValue (mappedType, typeData, memberValue));
398                         }
399                         else if (isNullable) {
400                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteNullableQualifiedNameEncoded (name, ns, (XmlQualifiedName)memberValue, xsiType);
401                                 else WriteNullableStringEncoded (name, ns, GetStringValue (mappedType, typeData, memberValue), xsiType);
402                         }
403                         else {
404                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteElementQualifiedName (name, ns, (XmlQualifiedName)memberValue, xsiType);
405                                 else WriteElementString (name, ns, GetStringValue (mappedType, typeData, memberValue), xsiType);
406                         }
407                 }
408
409                 protected virtual void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
410                 {
411                         if (_format == SerializationFormat.Encoded)
412                         {
413                                 string n, ns;
414                                 int itemCount = GetListCount (typeMap.TypeData, ob);
415                                 ((ListMap) typeMap.ObjectMap).GetArrayType (itemCount, out n, out ns);
416                                 string arrayType = (ns != string.Empty) ? FromXmlQualifiedName (new XmlQualifiedName(n,ns)) : n;
417                                 WriteAttribute ("arrayType", XmlSerializer.EncodingNamespace, arrayType);
418                         }
419                         WriteListContent (null, typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob, null);
420                 }
421
422                 void WriteListContent (object container, TypeData listType, ListMap map, object ob, StringBuilder targetString)
423                 {
424                         if (listType.Type.IsArray)
425                         {
426                                 Array array = (Array)ob;
427                                 for (int n=0; n<array.Length; n++)
428                                 {
429                                         object item = array.GetValue (n);
430                                         XmlTypeMapElementInfo info = map.FindElement (container, n, item);
431                                         if (info != null && targetString == null) WriteMemberElement (info, item);
432                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
433                                         else if (item != null) throw CreateUnknownTypeException (item);
434                                 }
435                         }
436                         else if (ob is ICollection)
437                         {
438                                 int count = (int) ob.GetType().GetProperty ("Count").GetValue(ob,null);
439                                 PropertyInfo itemProp = TypeData.GetIndexerProperty (listType.Type);
440                                 object[] index = new object[1];
441                                 for (int n=0; n<count; n++)
442                                 {
443                                         index[0] = n;
444                                         object item = itemProp.GetValue (ob, index);
445                                         XmlTypeMapElementInfo info = map.FindElement (container, n, item);
446                                         if (info != null && targetString == null) WriteMemberElement (info, item);
447                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
448                                         else if (item != null) throw CreateUnknownTypeException (item);
449                                 }
450                         }
451                         else if (ob is IEnumerable)
452                         {
453                                 IEnumerable e = (IEnumerable)ob;
454                                 foreach (object item in e)
455                                 {
456                                         XmlTypeMapElementInfo info = map.FindElement (container, -1, item);
457                                         if (info != null && targetString == null) WriteMemberElement (info, item);
458                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
459                                         else if (item != null) throw CreateUnknownTypeException (item);
460                                 }
461                         }
462                         else
463                                 throw new Exception ("Unsupported collection type");
464                 }
465
466                 int GetListCount (TypeData listType, object ob)
467                 {
468                         if (listType.Type.IsArray)
469                                 return ((Array)ob).Length;
470                         else
471                                 return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
472                 }
473
474                 void WriteAnyElementContent (XmlTypeMapMemberAnyElement member, object memberValue)
475                 {
476                         //
477                         // XmlAnyElement can be of XmlElement or XmlNode type
478                         // 
479                         if (member.TypeData.Type == typeof (XmlElement) || member.TypeData.Type == typeof(XmlNode)) {
480                                 memberValue = new object[] { memberValue };
481                         }
482
483                         Array elems = (Array) memberValue;
484                         foreach (var elem_ in elems)
485                         {
486                                 XmlNode elem = elem_ as XmlNode;
487                                 if (elem == null)
488                                         throw new InvalidOperationException (String.Format ("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]. The target object is {0}", elem_ != null ? elem_.GetType () : null));
489                                 if (elem is XmlElement) 
490                                 {
491                                         if (member.IsElementDefined (elem.Name, elem.NamespaceURI))
492                                         {
493                                                 if (_format == SerializationFormat.Literal) WriteElementLiteral (elem, "", "", false, true);
494                                                 else WriteElementEncoded (elem, "", "", false, true);
495                                         }
496                                         else
497                                                 throw CreateUnknownAnyElementException (elem.Name, elem.NamespaceURI);
498                                 }
499                                 else
500                                         elem.WriteTo (Writer);
501                         }
502                 }
503
504                 protected virtual void WritePrimitiveElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
505                 {
506                         Writer.WriteString (GetStringValue (typeMap, typeMap.TypeData, ob));
507                 }
508
509                 protected virtual void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
510                 {
511                         Writer.WriteString (GetEnumXmlValue (typeMap, ob));
512                 }
513
514                 string GetStringValue (XmlTypeMapping typeMap, TypeData type, object value)
515                 {
516                         if (type.SchemaType == SchemaTypes.Array) {
517                                 if (value == null) return null;
518                                 StringBuilder sb = new StringBuilder ();
519                                 WriteListContent (null, typeMap.TypeData, (ListMap)typeMap.ObjectMap, value, sb);
520                                 return sb.ToString ().Trim ();
521                         }
522                         else if (type.SchemaType == SchemaTypes.Enum)
523                                 return GetEnumXmlValue (typeMap, value);
524                         else if (type.Type == typeof (XmlQualifiedName))
525                                 return FromXmlQualifiedName ((XmlQualifiedName)value);
526                         else if (value == null)
527                                 return null;
528                         else
529                                 return XmlCustomFormatter.ToXmlString (type, value);
530                 }
531
532                 string GetEnumXmlValue (XmlTypeMapping typeMap, object ob)
533                 {
534                         if (ob == null)
535                                 return null;
536                         EnumMap map = (EnumMap)typeMap.ObjectMap;
537                         return map.GetXmlName (typeMap.TypeFullName, ob);
538                 }
539
540                 class CallbackInfo
541                 {
542                         XmlSerializationWriterInterpreter _swi;
543                         XmlTypeMapping _typeMap;
544
545                         public CallbackInfo (XmlSerializationWriterInterpreter swi, XmlTypeMapping typeMap)
546                         {
547                                 _swi = swi;
548                                 _typeMap = typeMap;
549                         }
550
551                         internal void WriteObject (object ob)
552                         {
553                                 _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, false, false);
554                         }
555
556                         internal void WriteEnum (object ob)
557                         {
558                                 _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, true, false);
559                         }
560                 }
561
562         }
563 }