Merge pull request #1326 from BrzVlad/master
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / SerializationCodeGenerator.cs
1 //
2 // System.Xml.Serialization.SerializationCodeGenerator.cs: 
3 //
4 // Authors:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //   Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2006 Novell, Inc.
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System.IO;
34 using System.Reflection;
35 using System.Xml.Serialization;
36 using System.Collections;
37 using System.Globalization;
38 using System.Text;
39
40 using HookDir = System.Xml.Serialization.XmlMappingAccess;
41
42 namespace System.Xml.Serialization
43 {
44         internal class SerializationCodeGenerator
45         {
46                 XmlMapping _typeMap;
47                 SerializationFormat _format;
48                 TextWriter _writer;
49                 int _tempVarId = 0;
50                 int _indent = 0;
51                 Hashtable _uniqueNames = new Hashtable();
52                 int _methodId = 0;
53                 SerializerInfo _config;
54                 ArrayList _mapsToGenerate = new ArrayList ();
55                 ArrayList _fixupCallbacks;
56                 ArrayList _referencedTypes = new ArrayList ();
57                 GenerationResult[] _results;
58                 GenerationResult _result;
59                 XmlMapping[] _xmlMaps;
60                 
61                 CodeIdentifiers classNames = new CodeIdentifiers ();
62
63                 public SerializationCodeGenerator (XmlMapping[] xmlMaps): this (xmlMaps, null)
64                 {
65                 }
66                 
67                 public SerializationCodeGenerator (XmlMapping[] xmlMaps, SerializerInfo config)
68                 {
69                         _xmlMaps = xmlMaps;
70                         _config = config;
71                 }
72                 
73                 public SerializationCodeGenerator (XmlMapping xmlMap, SerializerInfo config)
74                 {
75                         _xmlMaps = new XmlMapping [] {xmlMap};
76                         _config = config;
77                 }
78                 
79                 public static void Generate (string configFileName, string outputPath)
80                 {
81                         SerializationCodeGeneratorConfiguration cnf = null;
82                         StreamReader sr = new StreamReader (configFileName);
83                         try
84                         {
85                                 XmlReflectionImporter ri = new XmlReflectionImporter ();
86                                 ri.AllowPrivateTypes = true;
87                                 XmlSerializer ser = new XmlSerializer (ri.ImportTypeMapping (typeof (SerializationCodeGeneratorConfiguration)));
88                                 cnf = (SerializationCodeGeneratorConfiguration) ser.Deserialize (sr);
89                         }
90                         finally
91                         {
92                                 sr.Close ();
93                         }
94                         
95                         if (outputPath == null) outputPath = "";
96                         
97                         CodeIdentifiers ids = new CodeIdentifiers ();
98                         if (cnf.Serializers != null)
99                         {
100                                 foreach (SerializerInfo info in cnf.Serializers)
101                                 {                                       
102                                         Type type;
103                                         if (info.Assembly != null)
104                                         {
105                                                 Assembly asm;
106                                                 try {
107                                                         asm = Assembly.Load (info.Assembly);
108                                                 } catch {
109                                                         asm = Assembly.LoadFrom (info.Assembly);
110                                                 }
111                                                 type = asm.GetType (info.ClassName, true);
112                                         }
113                                         else
114                                                 type = Type.GetType (info.ClassName);
115                                         
116                                         if (type == null) throw new InvalidOperationException ("Type " + info.ClassName + " not found");
117                                         
118                                         string file = info.OutFileName;
119                                         if (file == null || file.Length == 0) {
120                                                 int i = info.ClassName.LastIndexOf (".");
121                                                 if (i != -1) file = info.ClassName.Substring (i+1);
122                                                 else file = info.ClassName;
123                                                 file = ids.AddUnique (file, type) + "Serializer.cs";
124                                         }
125                                         StreamWriter writer = new StreamWriter (Path.Combine (outputPath, file));
126                                         
127                                         try
128                                         {
129                                                 XmlTypeMapping map;
130                                                 
131                                                 if (info.SerializationFormat == SerializationFormat.Literal) {
132                                                         XmlReflectionImporter ri = new XmlReflectionImporter ();
133                                                         map = ri.ImportTypeMapping (type);
134                                                 }
135                                                 else {
136                                                         SoapReflectionImporter ri = new SoapReflectionImporter ();
137                                                         map = ri.ImportTypeMapping (type);
138                                                 }
139                                                 
140                                                 SerializationCodeGenerator gen = new SerializationCodeGenerator (map, info);
141                                                 gen.GenerateSerializers (writer);
142                                         }
143                                         finally
144                                         {
145                                                 writer.Close ();
146                                         }
147                                 }
148                         }
149                 }
150                 
151                 public void GenerateSerializers (TextWriter writer)
152                 {
153                         _writer = writer;
154                         _results = new GenerationResult [_xmlMaps.Length];
155                         
156                         WriteLine ("// It is automatically generated");
157                         WriteLine ("using System;");
158                         WriteLine ("using System.Xml;");
159                         WriteLine ("using System.Xml.Schema;");
160                         WriteLine ("using System.Xml.Serialization;");
161                         WriteLine ("using System.Text;");
162                         WriteLine ("using System.Collections;");
163                         WriteLine ("using System.Globalization;");
164                         if (_config != null && _config.NamespaceImports != null && _config.NamespaceImports.Length > 0) {
165                                 foreach (string ns in _config.NamespaceImports)
166                                         WriteLine ("using " + ns + ";");
167                         }
168                         WriteLine ("");
169                         
170                         string readerClassName = null;
171                         string writerClassName = null;
172                         string baseClassName = null;
173                         string implClassName = null;
174                         string namspace = null;
175                         
176                         if (_config != null)
177                         {
178                                 readerClassName = _config.ReaderClassName;
179                                 writerClassName = _config.WriterClassName;
180                                 baseClassName = _config.BaseSerializerClassName;
181                                 implClassName = _config.ImplementationClassName;
182                                 namspace = _config.Namespace;
183                         }
184
185                         if (readerClassName == null || readerClassName.Length == 0)
186                                 readerClassName = "GeneratedReader";
187
188                         if (writerClassName == null || writerClassName.Length == 0)
189                                 writerClassName = "GeneratedWriter";
190                         if (baseClassName == null || baseClassName.Length == 0)
191                                 baseClassName = "BaseXmlSerializer";
192                         if (implClassName == null || implClassName.Length == 0)
193                                 implClassName = "XmlSerializerContract";
194                         readerClassName = GetUniqueClassName (readerClassName);
195                         writerClassName = GetUniqueClassName (writerClassName);
196                         baseClassName = GetUniqueClassName (baseClassName);
197                         implClassName = GetUniqueClassName (implClassName);
198                         Hashtable mapsByNamespace = new Hashtable ();
199                         Hashtable generatedMaps = new Hashtable ();
200                         
201                         for (int n=0; n<_xmlMaps.Length; n++)
202                         {
203                                 _typeMap = _xmlMaps [n];
204                                 if (_typeMap == null) continue;
205                                 
206                                 _result = generatedMaps [_typeMap] as GenerationResult;
207                                 if (_result != null) {
208                                         _results[n] = _result;
209                                         continue;
210                                 }
211                                 
212                                 _result = new GenerationResult ();
213                                 _results[n] = _result;
214                                 
215                                 generatedMaps [_typeMap] = _result;
216                                 
217                                 string typeName;
218                                 if (_typeMap is XmlTypeMapping) typeName = CodeIdentifier.MakeValid (((XmlTypeMapping)_typeMap).TypeData.CSharpName);
219                                 else typeName = ((XmlMembersMapping)_typeMap).ElementName;
220                                 
221                                 _result.ReaderClassName = readerClassName;
222                                 _result.WriterClassName = writerClassName;
223                                 _result.BaseSerializerClassName = baseClassName;
224                                 _result.ImplementationClassName = implClassName;
225
226                                 if (namspace == null || namspace.Length == 0)
227                                         _result.Namespace = "Mono.GeneratedSerializers." + _typeMap.Format;
228                                 else
229                                         _result.Namespace = namspace;
230                                 
231                                 _result.WriteMethodName = GetUniqueName ("rwo", _typeMap, "WriteRoot_" + typeName);
232                                 _result.ReadMethodName = GetUniqueName ("rro", _typeMap, "ReadRoot_" + typeName);
233
234                                 _result.Mapping = _typeMap;
235                                 
236                                 ArrayList maps = (ArrayList) mapsByNamespace [_result.Namespace];
237                                 if (maps == null) {
238                                         maps = new ArrayList ();
239                                         mapsByNamespace [_result.Namespace] = maps;
240                                 }
241                                 maps.Add (_result);
242                         }
243                         
244                         foreach (DictionaryEntry entry in mapsByNamespace)
245                         {
246                                 ArrayList maps = (ArrayList) entry.Value;
247                                 
248                                 WriteLine ("namespace " + entry.Key);
249                                 WriteLineInd ("{");
250                                 
251                                 if (_config == null || !_config.NoReader)
252                                         GenerateReader (readerClassName, maps);
253                                 WriteLine ("");
254                                 if (_config == null || !_config.NoWriter)
255                                         GenerateWriter (writerClassName, maps);
256                                 WriteLine ("");
257                                 
258 #if NET_2_0
259                                 GenerateContract (maps);
260 #endif
261
262                                 WriteLineUni ("}");
263                                 WriteLine ("");
264                         }
265                 }
266                 
267                 public GenerationResult[] GenerationResults
268                 {
269                         get { return _results; }
270                 }
271                 
272                 public ArrayList ReferencedTypes
273                 {
274                         get { return _referencedTypes; }
275                 }
276                 
277                 void UpdateGeneratedTypes (ArrayList list)
278                 {
279                         for (int n=0; n<list.Count; n++)
280                         {
281                                 XmlTypeMapping map = list[n] as XmlTypeMapping;
282                                 if (map != null && !_referencedTypes.Contains (map.TypeData.Type))
283                                         _referencedTypes.Add (map.TypeData.Type);
284                         }
285                 }
286
287                 static string ToCSharpFullName (Type type)
288                 {
289                         return TypeData.ToCSharpName (type, true);
290                 }
291
292                 #region Writer Generation
293                 
294                 //*******************************************************
295                 // Contract generation
296                 //
297                 
298 #if NET_2_0
299                 public void GenerateContract (ArrayList generatedMaps)
300                 {
301                         // Write the base serializer
302                         
303                         if (generatedMaps.Count == 0) return;
304                         
305                         GenerationResult main = (GenerationResult) generatedMaps[0];
306                         
307                         string baseSerializerName = main.BaseSerializerClassName;
308                         string access_mod = (_config == null || !_config.GenerateAsInternal) ? "public" : "internal";
309                         
310                         WriteLine ("");
311                         WriteLine (access_mod + " class " + baseSerializerName + " : System.Xml.Serialization.XmlSerializer");
312                         WriteLineInd ("{");
313                         WriteLineInd ("protected override System.Xml.Serialization.XmlSerializationReader CreateReader () {");
314                         WriteLine ("return new " + main.ReaderClassName + " ();");
315                         WriteLineUni ("}");
316                         WriteLine ("");
317                         
318                         WriteLineInd ("protected override System.Xml.Serialization.XmlSerializationWriter CreateWriter () {");
319                         WriteLine ("return new " + main.WriterClassName + " ();");
320                         WriteLineUni ("}");
321                         WriteLine ("");
322                         
323                         WriteLineInd ("public override bool CanDeserialize (System.Xml.XmlReader xmlReader) {");
324                         WriteLine ("return true;");
325                         WriteLineUni ("}");
326                         
327                         WriteLineUni ("}");
328                         WriteLine ("");
329                         
330                         // Write a serializer for each imported map
331                         
332                         foreach (GenerationResult res in generatedMaps)
333                         {
334                                 res.SerializerClassName = GetUniqueClassName (res.Mapping.ElementName + "Serializer");
335                                 
336                                 WriteLine (access_mod + " sealed class " + res.SerializerClassName + " : " + baseSerializerName);
337                                 WriteLineInd ("{");
338                                 WriteLineInd ("protected override void Serialize (object obj, System.Xml.Serialization.XmlSerializationWriter writer) {");
339                                 WriteLine ("((" + res.WriterClassName + ")writer)." + res.WriteMethodName + "(obj);");
340                                 WriteLineUni ("}");
341                                 WriteLine ("");
342                                 
343                                 WriteLineInd ("protected override object Deserialize (System.Xml.Serialization.XmlSerializationReader reader) {");
344                                 WriteLine ("return ((" + res.ReaderClassName + ")reader)." + res.ReadMethodName + "();");
345                                 WriteLineUni ("}");
346                                 
347                                 WriteLineUni ("}");
348                                 WriteLine ("");
349                         }
350
351                         WriteLine ("#if !TARGET_JVM"); // does it make sense? ;-)
352                         WriteLine (access_mod + " class " + main.ImplementationClassName + " : System.Xml.Serialization.XmlSerializerImplementation");
353                         WriteLineInd ("{");
354                         
355                         WriteLine ("System.Collections.Hashtable readMethods = null;");
356                         WriteLine ("System.Collections.Hashtable writeMethods = null;");
357                         WriteLine ("System.Collections.Hashtable typedSerializers = null;");
358                         WriteLine ("");
359                 
360                         WriteLineInd ("public override System.Xml.Serialization.XmlSerializationReader Reader {");
361                         WriteLineInd ("get {");
362                         WriteLine ("return new " + main.ReaderClassName + "();");
363                         WriteLineUni ("}");
364                         WriteLineUni ("}");
365                         WriteLine ("");
366                         
367                         WriteLineInd ("public override System.Xml.Serialization.XmlSerializationWriter Writer {");
368                         WriteLineInd ("get {");
369                         WriteLine ("return new " + main.WriterClassName + "();");
370                         WriteLineUni ("}");
371                         WriteLineUni ("}");
372                         WriteLine ("");
373                         
374                         WriteLineInd ("public override System.Collections.Hashtable ReadMethods {");
375                         WriteLineInd ("get {");
376                         WriteLineInd ("lock (this) {");
377                         WriteLineInd ("if (readMethods == null) {");
378                         WriteLine ("readMethods = new System.Collections.Hashtable ();");
379                         foreach (GenerationResult res in generatedMaps)
380                                 WriteLine ("readMethods.Add (@\"" + res.Mapping.GetKey () + "\", @\"" + res.ReadMethodName + "\");");
381                         WriteLineUni ("}");
382                         WriteLine ("return readMethods;");
383                         WriteLineUni ("}");
384                         WriteLineUni ("}");
385                         WriteLineUni ("}");
386                         WriteLine ("");
387                         
388                         WriteLineInd ("public override System.Collections.Hashtable WriteMethods {");
389                         WriteLineInd ("get {");
390                         WriteLineInd ("lock (this) {");
391                         WriteLineInd ("if (writeMethods == null) {");
392                         WriteLine ("writeMethods = new System.Collections.Hashtable ();");
393                         foreach (GenerationResult res in generatedMaps)
394                                 WriteLine ("writeMethods.Add (@\"" + res.Mapping.GetKey () + "\", @\"" + res.WriteMethodName + "\");");
395                         WriteLineUni ("}");
396                         WriteLine ("return writeMethods;");
397                         WriteLineUni ("}");
398                         WriteLineUni ("}");
399                         WriteLineUni ("}");
400                         WriteLine ("");
401                         
402                         WriteLineInd ("public override System.Collections.Hashtable TypedSerializers {");
403                         WriteLineInd ("get {");
404                         WriteLineInd ("lock (this) {");
405                         WriteLineInd ("if (typedSerializers == null) {");
406                         WriteLine ("typedSerializers = new System.Collections.Hashtable ();");
407                         foreach (GenerationResult res in generatedMaps)
408                                 WriteLine ("typedSerializers.Add (@\"" + res.Mapping.GetKey () + "\", new " + res.SerializerClassName + "());");
409                         WriteLineUni ("}");
410                         WriteLine ("return typedSerializers;");
411                         WriteLineUni ("}");
412                         WriteLineUni ("}");
413                         WriteLineUni ("}");
414                         WriteLine ("");
415
416                         WriteLine ("public override XmlSerializer GetSerializer (Type type)");
417                         WriteLineInd ("{");
418                         WriteLine ("switch (type.FullName) {");
419                         foreach (GenerationResult res in generatedMaps) {
420                                 if (res.Mapping is XmlTypeMapping) {
421                                         WriteLineInd ("case \"" + ((XmlTypeMapping) res.Mapping).TypeData.CSharpFullName + "\":");
422                                         WriteLine ("return (XmlSerializer) TypedSerializers [\"" + res.Mapping.GetKey () + "\"];");
423                                         WriteLineUni ("");
424                                 }
425                         }
426                         WriteLine ("}");
427                         WriteLine ("return base.GetSerializer (type);");
428                         WriteLineUni ("}");
429                         WriteLine ("");
430                         
431                         WriteLineInd ("public override bool CanSerialize (System.Type type) {");
432                         foreach (GenerationResult res in generatedMaps) {
433                                 if (res.Mapping is XmlTypeMapping)
434                                         WriteLine ("if (type == typeof(" + (res.Mapping as XmlTypeMapping).TypeData.CSharpFullName +  ")) return true;");
435                         }
436                         WriteLine ("return false;");
437                         WriteLineUni ("}");
438                         
439                         WriteLineUni ("}");
440                         WriteLine ("");
441                         WriteLine ("#endif");
442                 }
443 #endif
444
445
446                 //*******************************************************
447                 // Writer generation
448                 //
449
450                 public void GenerateWriter (string writerClassName, ArrayList maps)
451                 {
452                         _mapsToGenerate = new ArrayList ();
453                         
454                         InitHooks ();
455                         
456                         if (_config == null || !_config.GenerateAsInternal)
457                                 WriteLine ("public class " + writerClassName + " : XmlSerializationWriter");
458                         else
459                                 WriteLine ("internal class " + writerClassName + " : XmlSerializationWriter");
460                         WriteLineInd ("{");
461                         WriteLine ("const string xmlNamespace = \"http://www.w3.org/2000/xmlns/\";");
462                         // ToBinHexString() is not public, so use reflection here.
463                         WriteLine ("static readonly System.Reflection.MethodInfo toBinHexStringMethod = typeof (XmlConvert).GetMethod (\"ToBinHexString\", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type [] {typeof (byte [])}, null);");
464                         WriteLine ("static string ToBinHexString (byte [] input)");
465                         WriteLineInd ("{");
466                         WriteLine ("return input == null ? null : (string) toBinHexStringMethod.Invoke (null, new object [] {input});");
467                         WriteLineUni ("}");
468                         
469                         for (int n=0; n<maps.Count; n++)
470                         {
471                                 GenerationResult res = (GenerationResult) maps [n];
472                                 _typeMap = res.Mapping;
473                                 _format = _typeMap.Format;
474                                 _result = res;
475                                 
476                                 GenerateWriteRoot ();
477                         }
478                         
479                         for (int n=0; n<_mapsToGenerate.Count; n++)
480                         {
481                                 XmlTypeMapping map = (XmlTypeMapping) _mapsToGenerate[n];
482                                 GenerateWriteObject (map);
483                                 if (map.TypeData.SchemaType == SchemaTypes.Enum)
484                                         GenerateGetXmlEnumValue (map);
485                         }
486                         
487                         GenerateWriteInitCallbacks ();
488                         UpdateGeneratedTypes (_mapsToGenerate);
489                         
490                         WriteLineUni ("}");
491                 }
492                 
493                 void GenerateWriteRoot ()
494                 {
495                         WriteLine ("public void " +_result.WriteMethodName + " (object o)");
496                         WriteLineInd ("{");
497                         WriteLine ("WriteStartDocument ();");
498                         
499                         if (_typeMap is XmlTypeMapping)
500                         {
501                                 WriteLine (GetRootTypeName () + " ob = (" + GetRootTypeName () + ") o;");
502                                 XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
503                                 if (mp.TypeData.SchemaType == SchemaTypes.Class || mp.TypeData.SchemaType == SchemaTypes.Array) 
504                                         WriteLine ("TopLevelElement ();");
505
506                                 if (_format == SerializationFormat.Literal) {
507                                         WriteLine (GetWriteObjectName (mp) + " (ob, " + GetLiteral(mp.ElementName) + ", " + GetLiteral(mp.Namespace) + ", true, false, true);");
508                                 }
509                                 else {
510                                         RegisterReferencingMap (mp);
511                                         WriteLine ("WritePotentiallyReferencingElement (" + GetLiteral(mp.ElementName) + ", " + GetLiteral(mp.Namespace) + ", ob, " + GetTypeOf(mp.TypeData) + ", true, false);");
512                                 }
513                         }
514                         else if (_typeMap is XmlMembersMapping) {
515                                 WriteLine ("object[] pars = (object[]) o;");
516                                 GenerateWriteMessage ((XmlMembersMapping) _typeMap);
517                         }
518                         else
519                                 throw new InvalidOperationException ("Unknown type map");
520
521                         if (_format == SerializationFormat.Encoded)
522                                 WriteLine ("WriteReferencedElements ();");
523
524                         WriteLineUni ("}");
525                         WriteLine ("");
526                 }
527                 
528                 void GenerateWriteMessage (XmlMembersMapping membersMap)
529                 {
530                         if (membersMap.HasWrapperElement) {
531                                 WriteLine ("TopLevelElement ();");
532                                 WriteLine ("WriteStartElement (" + GetLiteral (membersMap.ElementName) + ", " + GetLiteral (membersMap.Namespace) + ", (" + GetLiteral(_format == SerializationFormat.Encoded) + "));");
533
534 /*                              WriteLineInd ("if (Writer.LookupPrefix (XmlSchema.Namespace) == null)");
535                                 WriteLine ("WriteAttribute (\"xmlns\",\"xsd\",XmlSchema.Namespace,XmlSchema.Namespace);");
536                                 Unindent ();
537         
538                                 WriteLineInd ("if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)");
539                                 WriteLine ("WriteAttribute (\"xmlns\",\"xsi\",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);");
540                                 Unindent ();
541 */
542                         }
543                         
544                         GenerateWriteObjectElement (membersMap, "pars", true);
545
546                         if (membersMap.HasWrapperElement)
547                                 WriteLine ("WriteEndElement();");
548                 }
549                 
550                 void GenerateGetXmlEnumValue (XmlTypeMapping map)
551                 {
552                         EnumMap emap = (EnumMap) map.ObjectMap;
553
554                         string xmlNamesArray = null;
555                         string valuesArray = null;
556
557                         if (emap.IsFlags) {
558                                 // create static string[] holding XML names of enum constants
559                                 xmlNamesArray = GetUniqueName ("gxe", map, "_xmlNames" + map.XmlType);
560                                 Write ("static readonly string[] " + xmlNamesArray + " = { ");
561                                 for (int i = 0; i < emap.XmlNames.Length; i++) {
562                                         if (i > 0)
563                                                 _writer.Write (',');
564                                         _writer.Write ('"');
565                                         _writer.Write (emap.XmlNames[i]);
566                                         _writer.Write ('\"');
567                                 }
568                                 _writer.WriteLine (" };");
569
570                                 // create const long[] holding values of enum constants
571                                 valuesArray = GetUniqueName ("gve", map, "_values" + map.XmlType);
572                                 Write ("static readonly long[] " + valuesArray + " = { ");
573                                 for (int i = 0; i < emap.Values.Length; i++) {
574                                         if (i > 0)
575                                                 _writer.Write (',');
576                                         _writer.Write (emap.Values[i].ToString (CultureInfo.InvariantCulture));
577                                         _writer.Write ("L");
578                                 }
579                                 _writer.WriteLine (" };");
580                                 WriteLine (string.Empty);
581                         }
582
583                         WriteLine ("string " + GetGetEnumValueName (map) + " (" + GetTypeFullName (map.TypeData) + " val)");
584                         WriteLineInd ("{");
585
586
587                         WriteLineInd ("switch (val) {");
588                         for (int i = 0; i < emap.EnumNames.Length; i++)
589                                 WriteLine ("case " + map.TypeData.CSharpFullName + ".@" + emap.EnumNames[i] + ": return " + GetLiteral (emap.XmlNames[i]) + ";");
590
591                         if (emap.IsFlags) {
592                                 WriteLineInd ("default:");
593                                 // FromEnum actually covers this case too, but we save some cycles here
594                                 WriteLine ("if (val.ToString () == \"0\") return string.Empty;");
595                                 Write ("return FromEnum ((long) val, " + xmlNamesArray + ", " + valuesArray);
596 #if NET_2_0
597                                 _writer.Write (", typeof (");
598                                 _writer.Write (map.TypeData.CSharpFullName);
599                                 _writer.Write (").FullName");
600 #endif
601                                 _writer.Write (')'); // close FromEnum method call
602                                 WriteUni (";"); // end statement
603                         } else {
604 #if NET_2_0
605                                 WriteLine ("default: throw CreateInvalidEnumValueException ((long) val, typeof (" + map.TypeData.CSharpFullName + ").FullName);");
606 #else
607                                 WriteLine ("default: return ((long)val).ToString(CultureInfo.InvariantCulture);");
608 #endif
609                         }
610                         
611                         WriteLineUni ("}");
612                         
613                         WriteLineUni ("}");
614                         WriteLine ("");
615                 }
616                 
617                 void GenerateWriteObject (XmlTypeMapping typeMap)
618                 {
619                         WriteLine ("void " + GetWriteObjectName (typeMap) + " (" + GetTypeFullName (typeMap.TypeData) + " ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)");
620                         WriteLineInd ("{");
621                         
622                         PushHookContext ();
623                         
624                         SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
625                         SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
626                         SetHookVar ("$OBJECT", "ob");
627                         SetHookVar ("$NULLABLE", "isNullable");
628
629                         if (GenerateWriteHook (HookType.type, typeMap.TypeData.Type))
630                         {
631                                 WriteLineUni ("}");
632                                 WriteLine ("");
633                                 PopHookContext ();
634                                 return;
635                         }
636                         
637                         if (!typeMap.TypeData.IsValueType)
638                         {
639                                 WriteLine ("if (((object)ob) == null)");
640                                 WriteLineInd ("{");
641                                 WriteLineInd ("if (isNullable)");
642                                 
643                                 if (_format == SerializationFormat.Literal) 
644                                         WriteLine ("WriteNullTagLiteral(element, namesp);");
645                                 else 
646                                         WriteLine ("WriteNullTagEncoded (element, namesp);");
647                                 
648                                 WriteLineUni ("return;");
649                                 WriteLineUni ("}");
650                                 WriteLine ("");
651                         }
652
653                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode)
654                         {
655                                 if (_format == SerializationFormat.Literal)
656                                         WriteLine ("WriteElementLiteral (ob, \"\", \"\", true, " + GetLiteral(typeMap.IsAny) + ");");
657                                 else 
658                                         WriteLine ("WriteElementEncoded (ob, \"\", \"\", true, " + GetLiteral(typeMap.IsAny) + ");");
659                                         
660                                 GenerateEndHook ();
661                                 WriteLineUni ("}");
662                                 WriteLine ("");
663                                 PopHookContext ();
664                                 return;
665                         }
666
667                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlSerializable)
668                         {
669                                 WriteLine ("WriteSerializable (ob, element, namesp, isNullable, " + GetLiteral(!typeMap.IsAny) + ");");
670                                 
671                                 GenerateEndHook ();
672                                 WriteLineUni ("}");
673                                 WriteLine ("");
674                                 PopHookContext ();
675                                 return;
676                         }
677
678                         ArrayList types = typeMap.DerivedTypes;
679                         
680                         WriteLine ("System.Type type = ob.GetType ();");
681                         WriteLine ("if (type == typeof(" + typeMap.TypeData.CSharpFullName + "))");
682                         WriteLine ("{ }");
683                                 
684                         for (int n=0; n<types.Count; n++)
685                         {
686                                 XmlTypeMapping map = (XmlTypeMapping)types[n];
687                                 
688                                 WriteLineInd ("else if (type == typeof(" + map.TypeData.CSharpFullName + ")) { ");
689                                 WriteLine (GetWriteObjectName (map) + "((" + map.TypeData.CSharpFullName + ")ob, element, namesp, isNullable, true, writeWrappingElem);");
690                                 WriteLine ("return;");
691                                 WriteLineUni ("}");
692                         }
693                         
694                         if (typeMap.TypeData.Type == typeof (object)) {
695                                 WriteLineInd ("else {");
696                                 WriteLineInd ("if (ob.GetType().IsArray && typeof(XmlNode).IsAssignableFrom(ob.GetType().GetElementType())) {");
697                                 WriteLine ("Writer.WriteStartElement (" + GetLiteral (typeMap.ElementName) + ", " + GetLiteral (typeMap.Namespace) + ");");
698                                 WriteLineInd ("foreach (XmlNode node in (System.Collections.IEnumerable) ob)");
699                                 WriteLineUni ("node.WriteTo (Writer);");
700                                 WriteLineUni ("Writer.WriteEndElement ();");
701                                 WriteLine ("}");
702                                 WriteLineInd ("else");
703                                 WriteLineUni ("WriteTypedPrimitive (element, namesp, ob, true);");
704                                 WriteLine ("return;");
705                                 WriteLineUni ("}");
706                         }
707                         else
708                         {
709                                 WriteLineInd ("else {");
710                                 WriteLine ("throw CreateUnknownTypeException (ob);");
711                                 WriteLineUni ("}");
712                                 WriteLine ("");
713                                 
714                                 WriteLineInd ("if (writeWrappingElem) {");
715                                 if (_format == SerializationFormat.Encoded) WriteLine ("needType = true;");
716                                 WriteLine ("WriteStartElement (element, namesp, ob);");
717                                 WriteLineUni ("}");
718                                 WriteLine ("");
719         
720                                 WriteLine ("if (needType) WriteXsiType(" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.XmlTypeNamespace) + ");");
721                                 WriteLine ("");
722         
723                                 switch (typeMap.TypeData.SchemaType)
724                                 {
725                                         case SchemaTypes.Class: GenerateWriteObjectElement (typeMap, "ob", false); break;
726                                         case SchemaTypes.Array: GenerateWriteListElement (typeMap, "ob"); break;
727                                         case SchemaTypes.Primitive: GenerateWritePrimitiveElement (typeMap, "ob"); break;
728                                         case SchemaTypes.Enum: GenerateWriteEnumElement (typeMap, "ob"); break;
729                                 }
730         
731                                 WriteLine ("if (writeWrappingElem) WriteEndElement (ob);");
732                         }
733                         
734                         GenerateEndHook ();
735                         WriteLineUni ("}");
736                         WriteLine ("");
737                         PopHookContext ();
738                 }
739
740                 void GenerateWriteObjectElement (XmlMapping xmlMap, string ob, bool isValueList)
741                 {
742                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
743                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
744                         
745                         ClassMap map = (ClassMap)xmlMap.ObjectMap;
746                         if (!GenerateWriteHook (HookType.attributes, xmlMapType))
747                         {
748                                 if (map.NamespaceDeclarations != null) {
749                                         WriteLine ("WriteNamespaceDeclarations ((XmlSerializerNamespaces) " + ob + ".@" + map.NamespaceDeclarations.Name + ");");
750                                         WriteLine ("");
751                                 }
752         
753                                 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
754                                 if (anyAttrMember != null) 
755                                 {
756                                         if (!GenerateWriteMemberHook (xmlMapType, anyAttrMember))
757                                         {
758                                                 string cond = GenerateMemberHasValueCondition (anyAttrMember, ob, isValueList);
759                                                 if (cond != null) WriteLineInd ("if (" + cond + ") {");
760                 
761                                                 string tmpVar = GetObTempVar ();
762                                                 WriteLine ("ICollection " + tmpVar + " = " + GenerateGetMemberValue (anyAttrMember, ob, isValueList) + ";");
763                                                 WriteLineInd ("if (" + tmpVar + " != null) {");
764                 
765                                                 string tmpVar2 = GetObTempVar ();
766                                                 WriteLineInd ("foreach (XmlAttribute " + tmpVar2 + " in " + tmpVar + ")");
767                                                 WriteLineInd ("if (" + tmpVar2 + ".NamespaceURI != xmlNamespace)");
768                                                 WriteLine ("WriteXmlAttribute (" + tmpVar2 + ", " + ob + ");");
769                                                 Unindent ();
770                                                 Unindent ();
771                                                 WriteLineUni ("}");
772                 
773                                                 if (cond != null) WriteLineUni ("}");
774                                                 WriteLine ("");
775                                                 GenerateEndHook ();
776                                         }
777                                 }
778                                 
779                                 ICollection attributes = map.AttributeMembers;
780                                 if (attributes != null)
781                                 {
782                                         foreach (XmlTypeMapMemberAttribute attr in attributes) 
783                                         {
784                                                 if (GenerateWriteMemberHook (xmlMapType, attr)) continue;
785                                         
786                                                 string val = GenerateGetMemberValue (attr, ob, isValueList);
787                                                 string cond = GenerateMemberHasValueCondition (attr, ob, isValueList);
788                                                 
789                                                 if (cond != null) WriteLineInd ("if (" + cond + ") {");
790                                                 
791                                                 string strVal = GenerateGetStringValue (attr.MappedType, attr.TypeData, val, false);
792                                                 WriteLine ("WriteAttribute (" + GetLiteral(attr.AttributeName) + ", " + GetLiteral(attr.Namespace) + ", " + strVal + ");");
793         
794                                                 if (cond != null) WriteLineUni ("}");
795                                                 GenerateEndHook ();
796                                         }
797                                         WriteLine ("");
798                                 }
799                                 GenerateEndHook ();
800                         }
801                         
802                         if (!GenerateWriteHook (HookType.elements, xmlMapType))
803                         {
804                                 ICollection members = map.ElementMembers;
805                                 if (members != null)
806                                 {
807                                         foreach (XmlTypeMapMemberElement member in members)
808                                         {
809                                                 if (GenerateWriteMemberHook (xmlMapType, member)) continue;
810                                                 
811                                                 string cond = GenerateMemberHasValueCondition (member, ob, isValueList);
812                                                 if (cond != null) WriteLineInd ("if (" + cond + ") {");
813                                                 
814                                                 string memberValue = GenerateGetMemberValue (member, ob, isValueList);
815                                                 Type memType = member.GetType();
816         
817                                                 if (memType == typeof(XmlTypeMapMemberList))
818                                                 {
819                                                         GenerateWriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
820                                                 }
821                                                 else if (memType == typeof(XmlTypeMapMemberFlatList))
822                                                 {
823                                                         WriteLineInd ("if (" + memberValue + " != null) {"); 
824                                                         GenerateWriteListContent (ob, member.TypeData, ((XmlTypeMapMemberFlatList)member).ListMap, memberValue, false);
825                                                         WriteLineUni ("}");
826                                                 }
827                                                 else if (memType == typeof(XmlTypeMapMemberAnyElement))
828                                                 {
829                                                         WriteLineInd ("if (" + memberValue + " != null) {"); 
830                                                         GenerateWriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
831                                                         WriteLineUni ("}");
832                                                 }
833                                                 else if (memType == typeof(XmlTypeMapMemberAnyElement))
834                                                 {
835                                                         WriteLineInd ("if (" + memberValue + " != null) {"); 
836                                                         GenerateWriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
837                                                         WriteLineUni ("}");
838                                                 }
839                                                 else if (memType == typeof(XmlTypeMapMemberAnyAttribute))
840                                                 {
841                                                         // Ignore
842                                                 }
843                                                 else if (memType == typeof(XmlTypeMapMemberElement))
844                                                 {
845                                                         if (member.ElementInfo.Count == 1) {
846                                                                 XmlTypeMapElementInfo elem = (XmlTypeMapElementInfo)member.ElementInfo[0];
847                                                                 GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
848                                                         }
849                                                         else if (member.ChoiceMember != null)
850                                                         {
851                                                                 string choiceValue = ob + ".@" + member.ChoiceMember;
852                                                                 foreach (XmlTypeMapElementInfo elem in member.ElementInfo) {
853                                                                         WriteLineInd ("if (" + choiceValue + " == " + GetLiteral(elem.ChoiceValue) + ") {");
854                                                                         GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
855                                                                         WriteLineUni ("}");
856                                                                 }
857                                                         }
858                                                         else
859                                                         {
860         //                                                      WriteLineInd ("if (" + memberValue + " == null) {");
861         //                                                      GenerateWriteMemberElement ((XmlTypeMapElementInfo)member.ElementInfo[0], memberValue);
862         //                                                      WriteLineUni ("}");
863                                                                         
864                                                                 bool first = true;
865                                                                 foreach (XmlTypeMapElementInfo elem in member.ElementInfo)
866                                                                 {
867                                                                         WriteLineInd ((first?"":"else ") + "if (" + memberValue + " is " + elem.TypeData.CSharpFullName + ") {");
868                                                                         GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
869                                                                         WriteLineUni ("}");
870                                                                         first = false;
871                                                                 }
872                                                         }
873                                                 }
874                                                 else
875                                                         throw new InvalidOperationException ("Unknown member type");
876                                                         
877                                                 if (cond != null)
878                                                         WriteLineUni ("}");
879                                                         
880                                                 GenerateEndHook ();
881                                         }
882                                 }
883                                 GenerateEndHook ();
884                         }
885                 }
886                 
887                 void GenerateWriteMemberElement (XmlTypeMapElementInfo elem, string memberValue)
888                 {
889                         switch (elem.TypeData.SchemaType)
890                         {
891                                 case SchemaTypes.XmlNode:
892                                         string elemName = elem.WrappedElement ? elem.ElementName : "";
893                                         if (_format == SerializationFormat.Literal) 
894                                                 WriteMetCall ("WriteElementLiteral", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
895                                         else 
896                                                 WriteMetCall ("WriteElementEncoded", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
897                                         break;
898
899                                 case SchemaTypes.Enum:
900                                 case SchemaTypes.Primitive:
901                                         if (_format == SerializationFormat.Literal) 
902                                                 GenerateWritePrimitiveValueLiteral (memberValue, elem.ElementName, elem.Namespace, elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
903                                         else
904                                                 GenerateWritePrimitiveValueEncoded (memberValue, elem.ElementName, elem.Namespace, new XmlQualifiedName (elem.TypeData.XmlType, elem.DataTypeNamespace), elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
905                                         break;
906
907                                 case SchemaTypes.Array:
908                                         WriteLineInd ("if (" + memberValue + " != null) {");
909                                         
910                                         if (elem.MappedType.MultiReferenceType) {
911                                                 WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
912                                                 RegisterReferencingMap (elem.MappedType);
913                                         }
914                                         else {
915                                                 WriteMetCall ("WriteStartElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue);
916                                                 GenerateWriteListContent (null, elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue, false);
917                                                 WriteMetCall ("WriteEndElement", memberValue);
918                                         }
919                                         WriteLineUni ("}");
920                                         
921                                         if (elem.IsNullable) {
922                                                 WriteLineInd ("else");
923                                                 if (_format == SerializationFormat.Literal) 
924                                                         WriteMetCall ("WriteNullTagLiteral", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
925                                                 else
926                                                         WriteMetCall ("WriteNullTagEncoded", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
927                                                 Unindent ();
928                                         }
929                                         
930                                         break;
931
932                                 case SchemaTypes.Class:
933                                         if (elem.MappedType.MultiReferenceType) {
934                                                 RegisterReferencingMap (elem.MappedType);
935                                                 if (elem.MappedType.TypeData.Type == typeof(object))
936                                                         WriteMetCall ("WritePotentiallyReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, "null", "false", GetLiteral(elem.IsNullable));
937                                                 else
938                                                         WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
939                                         }
940                                         else 
941                                                 WriteMetCall (GetWriteObjectName(elem.MappedType), memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false", "true");
942                                         break;
943
944                                 case SchemaTypes.XmlSerializable:
945                                         WriteMetCall ("WriteSerializable",  "(" + ToCSharpFullName (elem.MappedType.TypeData.Type) + ") " + memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable));
946                                         break;
947
948                                 default:
949                                         throw new NotSupportedException ("Invalid value type");
950                         }
951                 }               
952
953                 void GenerateWriteListElement (XmlTypeMapping typeMap, string ob)
954                 {
955                         if (_format == SerializationFormat.Encoded)
956                         {
957                                 string n, ns;
958                                 string itemCount = GenerateGetListCount (typeMap.TypeData, ob);
959                                 GenerateGetArrayType ((ListMap) typeMap.ObjectMap, itemCount, out n, out ns);
960                                 
961                                 string arrayType;
962                                 if (ns != string.Empty)
963                                         arrayType = "FromXmlQualifiedName (new XmlQualifiedName(" + n + "," + ns + "))";
964                                 else
965                                         arrayType = GetLiteral (n);
966                                 
967                                 WriteMetCall ("WriteAttribute", GetLiteral("arrayType"), GetLiteral(XmlSerializer.EncodingNamespace), arrayType);
968                         }
969                         GenerateWriteListContent (null, typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob, false);
970                 }
971                 
972                 void GenerateWriteAnyElementContent (XmlTypeMapMemberAnyElement member, string memberValue)
973                 {
974                         bool singleElement = (member.TypeData.Type == typeof (XmlElement) || member.TypeData.Type == typeof (XmlNode));
975                         string var, var2;
976                         
977                         var = GetObTempVar ();
978                         if (singleElement)
979                                 var2 = memberValue;
980                         else {
981                                 var2 = GetObTempVar ();
982                                 WriteLineInd ("foreach (object " + var2 + " in " + memberValue + ") {");
983                         }
984                         WriteLine ("XmlNode " + var + " = " + var2 + " as XmlNode;");
985                         WriteLine ("if (" + var + " == null && " + var2 + "!= null) throw new InvalidOperationException (\"A member with XmlAnyElementAttribute can only serialize and deserialize certain XmlNode types.\");");
986
987                         string elem = GetObTempVar ();
988                         WriteLine ("XmlNode " + elem + " = " + var + ";");
989                         WriteLineInd ("if (" + elem + " is XmlElement) {");
990                         
991                         if (!member.IsDefaultAny) {
992                                 for (int n=0; n<member.ElementInfo.Count; n++) {
993                                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)member.ElementInfo[n];
994                                         string txt = "(" + elem + ".LocalName == " + GetLiteral(info.ElementName) + " && " + elem + ".NamespaceURI == " + GetLiteral(info.Namespace) + ")";
995                                         if (n == member.ElementInfo.Count-1) txt += ") {";
996                                         if (n == 0) WriteLineInd ("if (" + txt);
997                                         else WriteLine ("|| " + txt);
998                                 }                               
999                         }
1000
1001                         if (_format == SerializationFormat.Literal) 
1002                                 WriteLine ("WriteElementLiteral (" + elem + ", \"\", \"\", false, true);");
1003                         else 
1004                                 WriteLine ("WriteElementEncoded (" + elem + ", \"\", \"\", false, true);");
1005
1006                         if (!member.IsDefaultAny) {
1007                                 WriteLineUni ("}");
1008                                 WriteLineInd ("else");
1009                                 WriteLine ("throw CreateUnknownAnyElementException (" + elem + ".Name, " + elem + ".NamespaceURI);");
1010                                 Unindent ();
1011                         }
1012                         WriteLineUni ("}");
1013                         WriteLine ("else " + elem + ".WriteTo (Writer);");
1014                         
1015                         if (!singleElement)
1016                                 WriteLineUni ("}");
1017                 }
1018
1019                 void GenerateWritePrimitiveElement (XmlTypeMapping typeMap, string ob)
1020                 {
1021                         string strVal = GenerateGetStringValue (typeMap, typeMap.TypeData, ob, false);
1022                         WriteLine ("Writer.WriteString (" + strVal + ");");
1023                 }
1024
1025                 void GenerateWriteEnumElement (XmlTypeMapping typeMap, string ob)
1026                 {
1027                         string strVal = GenerateGetEnumXmlValue (typeMap, ob);
1028                         WriteLine ("Writer.WriteString (" + strVal + ");");
1029                 }
1030
1031                 string GenerateGetStringValue (XmlTypeMapping typeMap, TypeData type, string value, bool isNullable)
1032                 {
1033                         if (type.SchemaType == SchemaTypes.Array) {
1034                                 string str = GetStrTempVar ();
1035                                 WriteLine ("string " + str + " = null;");
1036                                 WriteLineInd ("if (" + value + " != null) {");
1037                                 string res = GenerateWriteListContent (null, typeMap.TypeData, (ListMap)typeMap.ObjectMap, value, true);
1038                                 WriteLine (str + " = " + res + ".ToString ().Trim ();");
1039                                 WriteLineUni ("}");
1040                                 return str;
1041                         }
1042                         else if (type.SchemaType == SchemaTypes.Enum) {
1043                                 if (isNullable)
1044                                         return "(" + value + ").HasValue ? " + GenerateGetEnumXmlValue (typeMap, "(" + value + ").Value") + " : null";
1045                                 else
1046                                         return GenerateGetEnumXmlValue (typeMap, value);
1047                         }
1048                         else if (type.Type == typeof (XmlQualifiedName))
1049                                 return "FromXmlQualifiedName (" + value + ")";
1050                         else if (value == null)
1051                                 return null;
1052                         else
1053                                 return XmlCustomFormatter.GenerateToXmlString (type, value);
1054                 }
1055
1056                 string GenerateGetEnumXmlValue (XmlTypeMapping typeMap, string ob)
1057                 {
1058                         return GetGetEnumValueName (typeMap) + " (" + ob + ")";
1059                 }
1060
1061                 string GenerateGetListCount (TypeData listType, string ob)
1062                 {
1063                         if (listType.Type.IsArray)
1064                                 return "ob.Length";
1065                         else
1066                                 return "ob.Count";
1067                 }
1068
1069                 void GenerateGetArrayType (ListMap map, string itemCount, out string localName, out string ns)
1070                 {
1071                         string arrayDim;
1072                         if (itemCount != "") arrayDim = "";
1073                         else arrayDim = "[]";
1074
1075                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) map.ItemInfo[0];
1076                         if (info.TypeData.SchemaType == SchemaTypes.Array)
1077                         {
1078                                 string nm;
1079                                 GenerateGetArrayType ((ListMap)info.MappedType.ObjectMap, "", out nm, out ns);
1080                                 localName = nm + arrayDim;
1081                         }
1082                         else 
1083                         {
1084                                 if (info.MappedType != null)
1085                                 {
1086                                         localName = info.MappedType.XmlType + arrayDim;
1087                                         ns = info.MappedType.Namespace;
1088                                 }
1089                                 else 
1090                                 {
1091                                         localName = info.TypeData.XmlType + arrayDim;
1092                                         ns = info.DataTypeNamespace;
1093                                 }
1094                         }
1095                         if (itemCount != "") {
1096                                 localName = "\"" + localName + "[\" + " + itemCount + " + \"]\"";
1097                                 ns = GetLiteral (ns);
1098                         }
1099                 }
1100
1101                 string GenerateWriteListContent (string container, TypeData listType, ListMap map, string ob, bool writeToString)
1102                 {
1103                         string targetString = null;
1104                         
1105                         if (writeToString)
1106                         {
1107                                 targetString = GetStrTempVar ();
1108                                 WriteLine ("System.Text.StringBuilder " + targetString + " = new System.Text.StringBuilder();");
1109                         }
1110                         
1111                         if (listType.Type.IsArray)
1112                         {
1113                                 string itemVar = GetNumTempVar ();
1114                                 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Length; "+itemVar+"++) {");
1115                                 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1116                                 WriteLineUni ("}");
1117                         }
1118                         else if (typeof(ICollection).IsAssignableFrom (listType.Type))
1119                         {
1120                                 string itemVar = GetNumTempVar ();
1121                                 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Count; "+itemVar+"++) {");
1122                                 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1123                                 WriteLineUni ("}");
1124                         }
1125                         else if (typeof(IEnumerable).IsAssignableFrom (listType.Type))
1126                         {
1127                                 string itemVar = GetObTempVar ();
1128                                 WriteLineInd ("foreach (" + listType.ListItemTypeData.CSharpFullName + " " + itemVar + " in " + ob + ") {");
1129                                 GenerateListLoop (container, map, itemVar, null, listType.ListItemTypeData, targetString);
1130                                 WriteLineUni ("}");
1131                         }
1132                         else
1133                                 throw new Exception ("Unsupported collection type");
1134
1135                         return targetString;
1136                 }
1137                 
1138                 void GenerateListLoop (string container, ListMap map, string item, string index, TypeData itemTypeData, string targetString)
1139                 {
1140                         bool multichoice = (map.ItemInfo.Count > 1);
1141
1142                         if (map.ChoiceMember != null && container != null && index != null) {
1143                                 WriteLineInd ("if ((" + container + ".@" + map.ChoiceMember + " == null) || (" + index + " >= " + container + ".@" + map.ChoiceMember + ".Length))");
1144                                 WriteLine ("throw CreateInvalidChoiceIdentifierValueException (" + container + ".GetType().ToString(), \"" + map.ChoiceMember + "\");");
1145                                 Unindent ();
1146                         }
1147                         
1148                         if (multichoice)
1149                                 WriteLine ("if (((object)" + item + ") == null) { }");
1150                                 
1151                         foreach (XmlTypeMapElementInfo info in map.ItemInfo)
1152                         {
1153                                 if (map.ChoiceMember != null && multichoice)
1154                                         WriteLineInd ("else if (" + container + ".@" + map.ChoiceMember + "[" + index + "] == " + GetLiteral (info.ChoiceValue) + ") {");
1155                                 else if (multichoice)
1156                                         WriteLineInd ("else if (" + item + ".GetType() == typeof(" + info.TypeData.CSharpFullName + ")) {");
1157                                 
1158                                 if (targetString == null) 
1159                                         GenerateWriteMemberElement (info, GetCast (info.TypeData, itemTypeData, item));
1160                                 else
1161                                 {
1162                                         string strVal = GenerateGetStringValue (info.MappedType, info.TypeData, GetCast (info.TypeData, itemTypeData, item), false);
1163                                         WriteLine (targetString + ".Append (" + strVal + ").Append (\" \");");
1164                                 }
1165
1166                                 if (multichoice)
1167                                         WriteLineUni ("}");
1168                         }
1169                         
1170                         if (multichoice)
1171                                 WriteLine ("else throw CreateUnknownTypeException (" + item + ");");
1172                 }
1173
1174                 void GenerateWritePrimitiveValueLiteral (string memberValue, string name, string ns, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1175                 {
1176                         if (!wrapped) {
1177                                 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1178                                 WriteMetCall ("WriteValue", strVal);
1179                         }
1180                         else if (isNullable) {
1181                                 if (typeData.Type == typeof(XmlQualifiedName)) 
1182                                         WriteMetCall ("WriteNullableQualifiedNameLiteral", GetLiteral(name), GetLiteral(ns), memberValue);
1183                                 else  {
1184                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, true);
1185                                         WriteMetCall ("WriteNullableStringLiteral", GetLiteral(name), GetLiteral(ns), strVal);
1186                                 }
1187                         }
1188                         else {
1189                                 if (typeData.Type == typeof(XmlQualifiedName))
1190                                         WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue);
1191                                 else {
1192                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1193                                         WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal);
1194                                 }
1195                         }
1196                 }
1197                 
1198                 void GenerateWritePrimitiveValueEncoded (string memberValue, string name, string ns, XmlQualifiedName xsiType, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1199                 {
1200                         if (!wrapped) {
1201                                 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1202                                 WriteMetCall ("WriteValue", strVal);
1203                         }
1204                         else if (isNullable) {
1205                                 if (typeData.Type == typeof(XmlQualifiedName)) 
1206                                         WriteMetCall ("WriteNullableQualifiedNameEncoded", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1207                                 else  {
1208                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, true);
1209                                         WriteMetCall ("WriteNullableStringEncoded", GetLiteral(name), GetLiteral(ns), strVal, GetLiteral(xsiType));
1210                                 }
1211                         }
1212                         else {
1213                                 if (typeData.Type == typeof(XmlQualifiedName))
1214                                         WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1215                                 else {
1216                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue, false);
1217                                         WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal, GetLiteral(xsiType));
1218                                 }
1219                         }
1220                 }
1221
1222                 string GenerateGetMemberValue (XmlTypeMapMember member, string ob, bool isValueList)
1223                 {
1224                         if (isValueList) return GetCast (member.TypeData, TypeTranslator.GetTypeData (typeof(object)), ob + "[" + member.GlobalIndex + "]");
1225                         else return ob + ".@" + member.Name;
1226                 }
1227                 
1228                 string GenerateMemberHasValueCondition (XmlTypeMapMember member, string ob, bool isValueList)
1229                 {
1230                         if (isValueList) {
1231                                 if (member.IsOptionalValueType)
1232                                         return ob + ".Length > " + Math.Max (member.GlobalIndex, member.SpecifiedGlobalIndex) + " && " + GetCast (typeof(bool), ob + "[" + member.SpecifiedGlobalIndex + "]");
1233                                 else
1234                                         return ob + ".Length > " + member.GlobalIndex;
1235                         }
1236                         else if (member.DefaultValue != System.DBNull.Value) {
1237                                 string mem = ob + ".@" + member.Name;
1238                                 if (member.DefaultValue == null) 
1239                                         return mem + " != null";
1240                                 else if (member.TypeData.SchemaType == SchemaTypes.Enum)
1241                                         return mem + " != " + GetCast (member.TypeData, GetLiteral (member.DefaultValue));
1242                                 else 
1243                                         return mem + " != " + GetLiteral (member.DefaultValue);
1244                         }
1245                         else if (member.HasSpecified) {
1246                                 var sb = new StringBuilder ();
1247                                 sb.AppendFormat ("{0}.@{1}Specified", ob, member.Name);
1248                                 if (member.HasShouldSerialize)
1249                                         sb.AppendFormat (" && {0}.@ShouldSerialize{1} ()", ob, member.Name);
1250                                 return sb.ToString ();
1251                         } else if (member.HasShouldSerialize)
1252                                 return ob + ".@ShouldSerialize" + member.Name + " ()";
1253
1254                         return null;
1255                 }
1256
1257                 void GenerateWriteInitCallbacks ()
1258                 {
1259                         WriteLine ("protected override void InitCallbacks ()");
1260                         WriteLineInd ("{");
1261                         
1262                         if (_format == SerializationFormat.Encoded)
1263                         {
1264                                 foreach (XmlMapping xmap in _mapsToGenerate)  {
1265                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1266                                         if (map != null)
1267                                                 WriteMetCall ("AddWriteCallback", GetTypeOf(map.TypeData), GetLiteral(map.XmlType), GetLiteral(map.Namespace), "new XmlSerializationWriteCallback (" + GetWriteObjectCallbackName (map) + ")");
1268                                 }
1269                         }       
1270                         
1271                         WriteLineUni ("}");
1272                         WriteLine ("");
1273                                 
1274                         if (_format == SerializationFormat.Encoded)
1275                         {
1276                                 foreach (XmlTypeMapping xmap in _mapsToGenerate)  {
1277                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1278                                         if (map == null) continue;
1279                                         if (map.TypeData.SchemaType == SchemaTypes.Enum)
1280                                                 WriteWriteEnumCallback (map);
1281                                         else
1282                                                 WriteWriteObjectCallback (map);
1283                                 }
1284                         }
1285                 }
1286                 
1287                 void WriteWriteEnumCallback (XmlTypeMapping map)
1288                 {
1289                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1290                         WriteLineInd ("{");
1291                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "true", "false");
1292                         WriteLineUni ("}");
1293                         WriteLine ("");
1294                 }
1295                 
1296                 void WriteWriteObjectCallback (XmlTypeMapping map)
1297                 {
1298                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1299                         WriteLineInd ("{");
1300                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "false", "false");
1301                         WriteLineUni ("}");
1302                         WriteLine ("");
1303                 }
1304                 
1305                 #endregion
1306                 
1307                 #region Reader Generation
1308
1309                 //*******************************************************
1310                 // Reader generation
1311                 //
1312                 
1313                 public void GenerateReader (string readerClassName, ArrayList maps)
1314                 {
1315                         if (_config == null || !_config.GenerateAsInternal)
1316                                 WriteLine ("public class " + readerClassName + " : XmlSerializationReader");
1317                         else
1318                                 WriteLine ("internal class " + readerClassName + " : XmlSerializationReader");
1319                         WriteLineInd ("{");
1320                         // FromBinHexString() is not public, so use reflection here.
1321                         WriteLine ("static readonly System.Reflection.MethodInfo fromBinHexStringMethod = typeof (XmlConvert).GetMethod (\"FromBinHexString\", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type [] {typeof (string)}, null);");
1322                         WriteLine ("static byte [] FromBinHexString (string input)");
1323                         WriteLineInd ("{");
1324                         WriteLine ("return input == null ? null : (byte []) fromBinHexStringMethod.Invoke (null, new object [] {input});");
1325                         WriteLineUni ("}");
1326
1327                         _mapsToGenerate = new ArrayList ();
1328                         _fixupCallbacks = new ArrayList ();
1329                         InitHooks ();
1330                         
1331                         for (int n=0; n<maps.Count; n++)
1332                         {
1333                                 GenerationResult res = (GenerationResult) maps [n];
1334                                 _typeMap = res.Mapping;
1335                                 _format = _typeMap.Format;
1336                                 _result = res;
1337                                 
1338                                 GenerateReadRoot ();
1339                         }
1340                         
1341                         for (int n=0; n<_mapsToGenerate.Count; n++)
1342                         {
1343                                 XmlTypeMapping map = _mapsToGenerate [n] as XmlTypeMapping;
1344                                 if (map == null) continue;
1345                                 
1346                                 GenerateReadObject (map);
1347                                 if (map.TypeData.SchemaType == SchemaTypes.Enum)
1348                                         GenerateGetEnumValueMethod (map);
1349                         }
1350                         
1351                         GenerateReadInitCallbacks ();
1352                         
1353                         if (_format == SerializationFormat.Encoded)
1354                         {
1355                                 GenerateFixupCallbacks ();
1356                                 GenerateFillerCallbacks ();
1357                         }
1358                         
1359                         WriteLineUni ("}");
1360                         UpdateGeneratedTypes (_mapsToGenerate);
1361                 }
1362                 
1363                 void GenerateReadRoot ()
1364                 {
1365                         WriteLine ("public object " + _result.ReadMethodName + " ()");
1366                         WriteLineInd ("{");
1367                         WriteLine ("Reader.MoveToContent();");
1368                         
1369                         if (_typeMap is XmlTypeMapping)
1370                         {
1371                                 XmlTypeMapping typeMap = (XmlTypeMapping) _typeMap;
1372
1373                                 if (_format == SerializationFormat.Literal)
1374                                 {
1375                                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode) {
1376                                                 if (typeMap.TypeData.Type == typeof (XmlDocument))
1377                                                         WriteLine ("return ReadXmlDocument (false);");
1378                                                 else
1379                                                         WriteLine ("return ReadXmlNode (false);");
1380                                         } else {
1381                                                 if (!typeMap.IsAny) {
1382                                                         WriteLineInd ("if (Reader.LocalName != " + GetLiteral (typeMap.ElementName) + " || Reader.NamespaceURI != " + GetLiteral (typeMap.Namespace) + ")");
1383                                                         WriteLine ("throw CreateUnknownNodeException();");
1384                                                         Unindent ();
1385                                                 }
1386
1387                                                 WriteLine ("return " + GetReadObjectCall (typeMap, GetLiteral(typeMap.IsNullable), "true") + ";");
1388                                         }
1389                                 }
1390                                 else
1391                                 {
1392                                         WriteLine ("object ob = null;");
1393                                         WriteLine ("Reader.MoveToContent();");
1394                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1395                                         WriteLineInd ("{");
1396                                         if (!typeMap.IsAny)
1397                                                 WriteLineInd ("if (Reader.LocalName == " + GetLiteral(typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
1398                                         WriteLine ("ob = ReadReferencedElement();");
1399                                         Unindent ();
1400                                         if (!typeMap.IsAny) {
1401                                                 WriteLineInd ("else ");
1402                                                 WriteLine ("throw CreateUnknownNodeException();");
1403                                                 Unindent ();
1404                                         }
1405                                         WriteLineUni ("}");
1406                                         WriteLineInd ("else ");
1407                                         WriteLine ("UnknownNode(null);");
1408                                         Unindent ();
1409                                         WriteLine ("");
1410                                         WriteLine ("ReadReferencedElements();");
1411                                         WriteLine ("return ob;");
1412                                         RegisterReferencingMap (typeMap);
1413                                 }
1414                         }
1415                         else {
1416                                 WriteLine ("return " + GenerateReadMessage ((XmlMembersMapping)_typeMap) + ";");
1417                         }
1418
1419                         WriteLineUni ("}");
1420                         WriteLine ("");
1421                 }
1422                 
1423                 string GenerateReadMessage (XmlMembersMapping typeMap)
1424                 {
1425                         WriteLine ("object[] parameters = new object[" + typeMap.Count + "];");
1426                         WriteLine ("");
1427
1428                         if (typeMap.HasWrapperElement)
1429                         {
1430                                 if (_format == SerializationFormat.Encoded)
1431                                 {
1432                                         WriteLine ("while (Reader.NodeType == System.Xml.XmlNodeType.Element)");
1433                                         WriteLineInd ("{");
1434                                         WriteLine ("string root = Reader.GetAttribute (\"root\", " + GetLiteral(XmlSerializer.EncodingNamespace) + ");");
1435                                         WriteLine ("if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break;");
1436                                         WriteLine ("ReadReferencedElement ();");
1437                                         WriteLine ("Reader.MoveToContent ();");
1438                                         WriteLineUni ("}");
1439                                         WriteLine ("");
1440                                         WriteLine ("if (Reader.NodeType != System.Xml.XmlNodeType.EndElement)");
1441                                         WriteLineInd ("{");
1442                                         WriteLineInd ("if (Reader.IsEmptyElement) {");
1443                                         WriteLine ("Reader.Skip();");
1444                                         WriteLine ("Reader.MoveToContent();");
1445                                         WriteLineUni ("}");
1446                                         WriteLineInd ("else {");
1447                                         WriteLine ("Reader.ReadStartElement();");
1448                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1449                                         WriteLine ("ReadEndElement();");
1450                                         WriteLineUni ("}");
1451                                         WriteLine ("");
1452                                         WriteLine ("Reader.MoveToContent();");
1453                                         WriteLineUni ("}");
1454                                 }
1455                                 else
1456                                 {
1457                                         // bug #79988: out parameters need to be initialized if 
1458                                         // they are value types
1459                                         ClassMap classMap = (ClassMap) typeMap.ObjectMap;
1460                                         ArrayList members = classMap.AllMembers;
1461                                         for (int n = 0; n < members.Count; n++) {
1462                                                 XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
1463                                                 if (!mem.IsReturnValue && mem.TypeData.IsValueType)
1464                                                         GenerateSetMemberValueFromAttr (mem, "parameters",
1465                                                                 String.Format ("({0}) Activator.CreateInstance(typeof({0}), true)", mem.TypeData.FullTypeName), true);
1466                                         }
1467
1468                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.ReadState == ReadState.Interactive)");
1469                                         WriteLineInd ("{");
1470                                         WriteLine ("if (Reader.IsStartElement(" + GetLiteral(typeMap.ElementName) + ", " + GetLiteral(typeMap.Namespace) + "))");
1471                                         WriteLineInd ("{");
1472                                         bool dummy = false;
1473                                         GenerateReadAttributeMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, ref dummy);
1474                                         WriteLine ("if (Reader.IsEmptyElement)");
1475                                         WriteLineInd ("{");
1476                                         WriteLine ("Reader.Skip(); Reader.MoveToContent(); continue;");
1477                                         WriteLineUni ("}");
1478                                         WriteLine ("Reader.ReadStartElement();");
1479                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1480                                         WriteLine ("ReadEndElement();");
1481                                         WriteLine ("break;");
1482                                         WriteLineUni ("}");
1483                                         WriteLineInd ("else ");
1484                                         WriteLine ("UnknownNode(null);");
1485                                         Unindent ();
1486                                         WriteLine ("");
1487                                         WriteLine ("Reader.MoveToContent();");
1488                                         WriteLineUni ("}");
1489                                 }
1490                         }
1491                         else
1492                                 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, _format == SerializationFormat.Encoded);
1493
1494                         if (_format == SerializationFormat.Encoded)
1495                                 WriteLine ("ReadReferencedElements();");
1496
1497                         return "parameters";
1498                 }
1499                 
1500                 void GenerateReadObject (XmlTypeMapping typeMap)
1501                 {
1502                         string isNullable;
1503                         if (_format == SerializationFormat.Literal) {
1504                                 WriteLine ("public " + GetTypeFullName(typeMap.TypeData) + " " + GetReadObjectName (typeMap) + " (bool isNullable, bool checkType)");
1505                                 isNullable = "isNullable";
1506                         }
1507                         else {
1508                                 WriteLine ("public object " + GetReadObjectName (typeMap) + " ()");
1509                                 isNullable = "true";
1510                         }
1511                         
1512                         WriteLineInd ("{");
1513
1514                         PushHookContext ();
1515                         
1516                         SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
1517                         SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
1518                         SetHookVar ("$NULLABLE", "isNullable");
1519                         
1520                         switch (typeMap.TypeData.SchemaType)
1521                         {
1522                                 case SchemaTypes.Class: GenerateReadClassInstance (typeMap, isNullable, "checkType"); break;
1523                                 case SchemaTypes.Array: 
1524                                         string list = GenerateReadListElement (typeMap, null, isNullable, true);
1525                                         if (list != null)
1526                                                 WriteLine ("return " + list + ";"); 
1527                                         break;
1528                                 case SchemaTypes.XmlNode: GenerateReadXmlNodeElement (typeMap, isNullable); break;
1529                                 case SchemaTypes.Primitive: GenerateReadPrimitiveElement (typeMap, isNullable); break;
1530                                 case SchemaTypes.Enum: GenerateReadEnumElement (typeMap, isNullable); break;
1531                                 case SchemaTypes.XmlSerializable: GenerateReadXmlSerializableElement (typeMap, isNullable); break;
1532                                 default: throw new Exception ("Unsupported map type");
1533                         }
1534                         
1535                         WriteLineUni ("}");
1536                         WriteLine ("");
1537                         PopHookContext ();
1538                 }
1539                                 
1540                 void GenerateReadClassInstance (XmlTypeMapping typeMap, string isNullable, string checkType)
1541                 {
1542                         SetHookVar ("$OBJECT", "ob");
1543                         if (!typeMap.TypeData.IsValueType)
1544                         {
1545                                 WriteLine (typeMap.TypeData.CSharpFullName + " ob = null;");
1546                         
1547                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1548                                         WriteLine ("return ob;");
1549                                         return;
1550                                 }
1551                                 
1552                                 if (_format == SerializationFormat.Literal) {
1553                                         WriteLine ("if (" + isNullable + " && ReadNull()) return null;");
1554                                         WriteLine ("");
1555                                         WriteLine ("if (checkType) ");
1556                                         WriteLineInd ("{");
1557                                 }
1558                                 else {
1559                                         WriteLine ("if (ReadNull()) return null;");
1560                                         WriteLine ("");
1561                                 }
1562                         }
1563                         else
1564                         {
1565                                 WriteLine (typeMap.TypeData.CSharpFullName + String.Format (" ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1566                         
1567                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1568                                         WriteLine ("return ob;");
1569                                         return;
1570                                 }
1571                         }
1572                         
1573                         WriteLine ("System.Xml.XmlQualifiedName t = GetXsiType();");
1574                         WriteLine ("if (t == null)");
1575                         if (typeMap.TypeData.Type != typeof(object))
1576                                 WriteLine ("{ }");
1577                         else
1578                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (new System.Xml.XmlQualifiedName(\"anyType\", System.Xml.Schema.XmlSchema.Namespace))") + ";");
1579                         
1580                         foreach (XmlTypeMapping realMap in typeMap.DerivedTypes)
1581                         {
1582                                 WriteLineInd ("else if (t.Name == " + GetLiteral (realMap.XmlType) + " && t.Namespace == " + GetLiteral (realMap.XmlTypeNamespace) + ")");
1583                                 WriteLine ("return " + GetReadObjectCall(realMap, isNullable, checkType) + ";");
1584                                 Unindent ();
1585                         }
1586
1587                         WriteLine ("else if (t.Name != " + GetLiteral (typeMap.XmlType) + " || t.Namespace != " + GetLiteral (typeMap.XmlTypeNamespace) + ")");
1588                         if (typeMap.TypeData.Type == typeof(object))
1589                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
1590                         else
1591                                 WriteLine ("\tthrow CreateUnknownTypeException(t);");
1592
1593                         if (!typeMap.TypeData.IsValueType)
1594                         {
1595                                 if (_format == SerializationFormat.Literal)
1596                                         WriteLineUni ("}");
1597
1598                                 if (typeMap.TypeData.Type.IsAbstract) {
1599                                         GenerateEndHook ();
1600                                         WriteLine ("return ob;");
1601                                         return;
1602                                 }
1603         
1604                                 WriteLine ("");
1605                                 WriteLine (String.Format ("ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1606                         }
1607                         
1608                         WriteLine ("");
1609                         
1610                         WriteLine ("Reader.MoveToElement();");
1611                         WriteLine ("");
1612                         
1613                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "ob", false, false);
1614                         
1615                         WriteLine ("");
1616                         
1617                         GenerateEndHook ();
1618                         WriteLine ("return ob;");
1619                 }
1620
1621                 void GenerateReadMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, bool readBySoapOrder)
1622                 {
1623                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1624                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
1625                         
1626                         bool first = false;
1627                         // Read attributes
1628                         GenerateReadAttributeMembers (xmlMap, map, ob, isValueList, ref first);
1629
1630                         if (!isValueList)
1631                         {
1632                                 WriteLine ("Reader.MoveToElement();");
1633                                 WriteLineInd ("if (Reader.IsEmptyElement) {"); 
1634                                 WriteLine ("Reader.Skip ();");
1635                                 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1636                                 WriteLine ("return " + ob + ";");
1637                                 WriteLineUni ("}");
1638                                 WriteLine ("");
1639         
1640                                 WriteLine ("Reader.ReadStartElement();");
1641                         }
1642                         
1643                         // Reads elements
1644
1645                         WriteLine("Reader.MoveToContent();");
1646                         WriteLine ("");
1647
1648                         if (!GenerateReadHook (HookType.elements, xmlMapType))
1649                         {
1650                                 string[] readFlag = null;
1651                                 if (map.ElementMembers != null && !readBySoapOrder)
1652                                 {
1653                                         string readFlagsVars = string.Empty;
1654                                         readFlag = new string[map.ElementMembers.Count];
1655                                         int n=0;
1656                                         foreach (XmlTypeMapMember mem in map.ElementMembers) {
1657                                                 // The text collector doesn't need a flag
1658                                                 if (!((mem is XmlTypeMapMemberElement) && ((XmlTypeMapMemberElement)mem).IsXmlTextCollector)) {
1659                                                         readFlag[n] = GetBoolTempVar ();
1660                                                         if (readFlagsVars.Length > 0) readFlagsVars += ", ";
1661                                                         readFlagsVars += readFlag[n] + "=false";
1662                                                 }
1663                                                 n++;
1664                                         }
1665                                         if (readFlagsVars.Length > 0) {
1666                                                 readFlagsVars = "bool " + readFlagsVars;
1667                                                 WriteLine (readFlagsVars + ";");
1668                                         }
1669                                         foreach (XmlTypeMapElementInfo info in map.AllElementInfos)
1670                                                 if (info.ExplicitOrder >= 0) {
1671                                                         WriteLine ("int idx = -1;");
1672                                                         break;
1673                                                 }
1674                                         WriteLine ("");
1675                                 }
1676                                 
1677                                 string[] indexes = null;
1678                                 string[] flatLists = null;
1679                                 string[] flatListsChoices = null;
1680         
1681                                 if (map.FlatLists != null) 
1682                                 {
1683                                         indexes = new string[map.FlatLists.Count];
1684                                         flatLists = new string[map.FlatLists.Count];
1685                                         
1686                                         string code = "int ";
1687                                         for (int n=0; n<map.FlatLists.Count; n++) 
1688                                         {
1689                                                 XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement)map.FlatLists[n];
1690                                                 indexes[n] = GetNumTempVar ();
1691                                                 if (n > 0) code += ", ";
1692                                                 code += indexes[n] + "=0";
1693                                                 if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
1694                                                         flatLists[n] = GetObTempVar ();
1695                                                         string rval;
1696                                                         WriteLine (mem.TypeData.CSharpFullName + " " + flatLists[n] + ";");
1697                                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList)) {
1698                                                                 rval = GenerateGetMemberValue (mem, ob, isValueList);
1699                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1700                                                         } else if (mem.TypeData.Type.IsArray) {
1701                                                                 rval = GenerateInitializeList (mem.TypeData);
1702                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1703                                                         } else {
1704                                                                 WriteLine (flatLists[n] + " = " + GenerateGetMemberValue (mem, ob, isValueList) + ";");
1705                                                                 WriteLineInd ("if (((object)" + flatLists[n] + ") == null) {");
1706                                                                 WriteLine (flatLists[n] + " = " + GenerateInitializeList (mem.TypeData) + ";");
1707                                                                 GenerateSetMemberValue (mem, ob, flatLists[n], isValueList);
1708                                                                 WriteLineUni ("}");
1709                                                         }
1710                                                 }
1711                                                 
1712                                                 if (mem.ChoiceMember != null) {
1713                                                         if (flatListsChoices == null)
1714                                                                 flatListsChoices = new string [map.FlatLists.Count];
1715                                                         flatListsChoices[n] = GetObTempVar ();
1716                                                         string rval = GenerateInitializeList (mem.ChoiceTypeData);
1717                                                         WriteLine (mem.ChoiceTypeData.CSharpFullName + " " + flatListsChoices[n] + " = " + rval + ";");
1718                                                 }
1719                                         }
1720                                         WriteLine (code + ";");
1721                                         WriteLine ("");
1722                                 }
1723                                 
1724                                 if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
1725                                 {
1726                                         _fixupCallbacks.Add (xmlMap);
1727                                         WriteLine ("Fixup fixup = new Fixup(" + ob + ", new XmlSerializationFixupCallback(" + GetFixupCallbackName (xmlMap) + "), " + map.ElementMembers.Count + ");");
1728                                         WriteLine ("AddFixup (fixup);");
1729                                         WriteLine ("");
1730                                 }
1731         
1732                                 ArrayList infos = null;
1733                                 
1734                                 int maxInd;
1735                                 if (readBySoapOrder) {
1736                                         if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
1737                                         else maxInd = 0;
1738                                 }
1739                                 else
1740                                 {
1741                                         infos = new ArrayList ();
1742                                         infos.AddRange (map.AllElementInfos);
1743                                         maxInd = infos.Count;
1744                                         
1745                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
1746                                         WriteLineInd ("{");
1747                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1748                                         WriteLineInd ("{");
1749                                 }
1750                                 
1751                                 first = true;
1752                                 for (int ind = 0; ind < maxInd; ind++)
1753                                 {
1754                                         XmlTypeMapElementInfo info = readBySoapOrder ? map.GetElement (ind) : (XmlTypeMapElementInfo) infos [ind];
1755                                         
1756                                         if (!readBySoapOrder)
1757                                         {
1758                                                 if (info.IsTextElement || info.IsUnnamedAnyElement) continue;
1759                                                 string elemCond = first ? "" : "else ";
1760                                                 elemCond += "if (";
1761                                                 if (info.ExplicitOrder >= 0)
1762                                                         elemCond += "idx < " + info.ExplicitOrder + "&& ";
1763                                                 if (!(info.Member.IsReturnValue && _format == SerializationFormat.Encoded)) {
1764                                                         elemCond += "Reader.LocalName == " + GetLiteral (info.ElementName);
1765                                                         if (!map.IgnoreMemberNamespace) elemCond += " && Reader.NamespaceURI == " + GetLiteral (info.Namespace);
1766                                                         elemCond += " && ";
1767                                                 }
1768                                                 if (readFlag[info.Member.Index] != null)
1769                                                         elemCond += "!" + readFlag[info.Member.Index] + ") {";
1770                                                 else
1771                                                         elemCond += "true) {";
1772                                                 WriteLineInd (elemCond);
1773                                         }
1774         
1775                                         if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
1776                                         {
1777                                                 if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
1778                                                 {
1779                                                         string list = GetObTempVar ();
1780                                                         WriteLine ("object " + list + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1781                                                         RegisterReferencingMap (info.MappedType);
1782
1783                                                         WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // Already read
1784                                                         if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1785                                                                 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.CSharpFullName) + ");");
1786                                                         else 
1787                                                                 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1788                                                         WriteLineUni ("}");
1789         
1790                                                         if (!info.MappedType.TypeData.Type.IsArray)
1791                                                         {
1792                                                                 WriteLineInd ("else {");
1793                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1794                                                                         WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1795                                                                 else { 
1796                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1797                                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1798                                                                 }
1799                                                                 WriteLine ("AddFixup (new CollectionFixup (" + list + ", new XmlSerializationCollectionFixupCallback (" + GetFillListName(info.Member.TypeData) + "), fixup.Ids[" + info.Member.Index + "]));");
1800                                                                 WriteLine ("fixup.Ids[" + info.Member.Index + "] = null;");             // The member already has the value, no further fix needed.
1801                                                                 WriteLineUni ("}");
1802                                                         }
1803                                                 }
1804                                                 else
1805                                                 {
1806                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1807                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) {
1808                                                                         GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
1809                                                                 } else if (info.MappedType.TypeData.Type.IsArray) {
1810                                                                         if (info.IsNullable)
1811                                                                                 GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
1812                                                                         else {
1813                                                                                 string list = GetObTempVar ();
1814                                                                                 WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true) + ";");
1815                                                                                 WriteLineInd ("if (((object)" + list + ") != null) {");
1816                                                                                 GenerateSetMemberValue (info.Member, ob, list, isValueList);
1817                                                                                 WriteLineUni ("}");
1818                                                                         }
1819                                                                 } else {
1820                                                                         string list = GetObTempVar ();
1821                                                                         WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1822                                                                         WriteLineInd ("if (((object)" + list + ") == null) {");
1823                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1824                                                                         GenerateSetMemberValue (info.Member, ob, list, isValueList);
1825                                                                         WriteLineUni ("}");
1826                                                                         GenerateReadListElement (info.MappedType, list, GetLiteral(info.IsNullable), true);
1827                                                                 }
1828                                                                 GenerateEndHook ();
1829                                                         }
1830                                                 }
1831                                                 if (!readBySoapOrder)
1832                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1833                                         }
1834                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
1835                                         {
1836                                                 XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
1837                                                 if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1838                                                         GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, info.TypeData, isValueList));
1839                                                         if (mem.ChoiceMember != null) {
1840                                                                 GenerateAddListValue (mem.ChoiceTypeData, flatListsChoices[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetLiteral (info.ChoiceValue), true);
1841                                                         }
1842                                                         GenerateEndHook ();
1843                                                 }
1844                                                 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1845                                         }
1846                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
1847                                         {
1848                                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
1849                                                 if (mem.TypeData.IsListType) { 
1850                                                         if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1851                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
1852                                                                 GenerateEndHook ();
1853                                                         }
1854                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1855                                                 }
1856                                                 else {
1857                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1858                                                                 GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1859                                                                 GenerateEndHook ();
1860                                                         }
1861                                                 }
1862                                         }
1863                                         else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
1864                                         {
1865                                                 if (!readBySoapOrder)
1866                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1867                                                 if (info.ExplicitOrder >= 0)
1868                                                         WriteLine ("idx = " + info.ExplicitOrder + ";");
1869                                                 if (_format == SerializationFormat.Encoded)
1870                                                 {
1871                                                         string val = GetObTempVar ();
1872                                                         RegisterReferencingMap (info.MappedType);
1873                                                         
1874                                                         if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
1875                                                                 WriteLine ("object " + val + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1876                                                         else
1877                                                                 WriteLine ("object " + val + " = ReadReferencingElement (" + GetLiteral(info.Member.TypeData.XmlType) + ", " + GetLiteral(System.Xml.Schema.XmlSchema.Namespace) + ", out fixup.Ids[" + info.Member.Index + "]);");
1878                                                         
1879                                                         if (info.MultiReferenceType)
1880                                                                 WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // already read
1881                                                         else
1882                                                                 WriteLineInd ("if (" + val + " != null) {");    // null value
1883                                                                 
1884                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,val), isValueList);
1885                                                         WriteLineUni ("}");
1886                                                 }
1887                                                 else if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1888                                                         if (info.ChoiceValue != null) {
1889                                                                 XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement) info.Member;
1890                                                                 WriteLine (ob + ".@" + imem.ChoiceMember + " = " + GetLiteral(info.ChoiceValue) + ";");
1891                                                         }
1892                                                         GenerateSetMemberValue (info.Member, ob, GenerateReadObjectElement (info), isValueList);
1893                                                         GenerateEndHook ();
1894                                                 }
1895                                         }
1896                                         else
1897                                                 throw new InvalidOperationException ("Unknown member type");
1898         
1899                                         if (!readBySoapOrder)
1900                                                 WriteLineUni ("}");
1901                                         else
1902                                                 WriteLine ("Reader.MoveToContent();");
1903                                         first = false;
1904                                 }
1905                                 
1906                                 if (!readBySoapOrder)
1907                                 {
1908                                         if (!first) WriteLineInd ("else {");
1909                                         
1910                                         if (map.DefaultAnyElementMember != null)
1911                                         {
1912                                                 XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
1913                                                 if (mem.TypeData.IsListType) {
1914                                                         if (!GenerateReadArrayMemberHook (xmlMapType, mem, indexes[mem.FlatArrayIndex])) {
1915                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
1916                                                                 GenerateEndHook ();
1917                                                         }
1918                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1919                                                 }
1920                                                 else if (! GenerateReadMemberHook (xmlMapType, mem)) {
1921                                                         GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1922                                                         GenerateEndHook ();
1923                                                 }
1924                                         }
1925                                         else {
1926                                                 if (!GenerateReadHook (HookType.unknownElement, xmlMapType)) {
1927                                                         WriteLine ("UnknownNode (" + ob + ");");
1928                                                         GenerateEndHook ();
1929                                                 }
1930                                         }
1931                                         
1932                                         if (!first) WriteLineUni ("}");
1933                 
1934                                         WriteLineUni ("}");
1935                                         
1936                                         if (map.XmlTextCollector != null)
1937                                         {
1938                                                 WriteLine ("else if (Reader.NodeType == System.Xml.XmlNodeType.Text || Reader.NodeType == System.Xml.XmlNodeType.CDATA)");
1939                                                 WriteLineInd ("{");
1940                 
1941                                                 if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
1942                                                 {
1943                                                         XmlTypeMapMemberExpandable mem = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
1944                                                         XmlTypeMapMemberFlatList flatl = mem as XmlTypeMapMemberFlatList;
1945                                                         TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;
1946                                                         
1947                                                         if (!GenerateReadArrayMemberHook (xmlMapType, map.XmlTextCollector, indexes[mem.FlatArrayIndex])) {
1948                                                                 string val = (itype.Type == typeof (string)) ? "Reader.ReadString()" : GetReadXmlNode (itype, false);
1949                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], val, true);
1950                                                                 GenerateEndHook ();
1951                                                         }
1952                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1953                                                 }
1954                                                 else if (!GenerateReadMemberHook (xmlMapType, map.XmlTextCollector))
1955                                                 {
1956                                                         XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector;
1957                                                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0];
1958                                                         string str = GetStrTempVar ();
1959                                                         WriteLine ("string " + str + " = Reader.ReadString();");
1960                                                         if (info.TypeData.Type == typeof (string))
1961                                                                 GenerateSetMemberValue (mem, ob, str, isValueList);
1962                                                         else {
1963                                                                 GenerateSetMemberValue (mem, ob, GenerateGetValueFromXmlString (str, info.TypeData, info.MappedType, info.IsNullable), isValueList);
1964                                                         }
1965                                                         GenerateEndHook ();
1966                                                 }
1967                                                 WriteLineUni ("}");
1968                                         }
1969                                                 
1970                                         WriteLine ("else");
1971                                         WriteLine ("\tUnknownNode(" + ob + ");");
1972                                         WriteLine ("");
1973                                         WriteLine ("Reader.MoveToContent();");
1974                                         WriteLineUni ("}");
1975                                 }
1976                                 else
1977                                         WriteLine ("Reader.MoveToContent();");
1978         
1979                                 if (flatLists != null)
1980                                 {
1981                                         WriteLine ("");
1982                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1983                                         {
1984                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1985                                                 
1986                                                 string list = flatLists[mem.FlatArrayIndex];
1987                                                 if (mem.TypeData.Type.IsArray)
1988                                                         WriteLine (list + " = (" + mem.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
1989                                                 if (!IsReadOnly (typeMap, mem, mem.TypeData, isValueList) && mem.TypeData.Type.IsArray)
1990                                                         GenerateSetMemberValue (mem, ob, list, isValueList);
1991                                         }
1992                                 }
1993                                 
1994                                 if (flatListsChoices != null)
1995                                 {
1996                                         WriteLine ("");
1997                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1998                                         {
1999                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
2000                                                 if (mem.ChoiceMember == null) continue;
2001                                                 
2002                                                 string list = flatListsChoices[mem.FlatArrayIndex];
2003                                                 WriteLine (list + " = (" + mem.ChoiceTypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.ChoiceTypeData.Type.GetElementType()) + ", true);");
2004                                                 WriteLine (ob + ".@" + mem.ChoiceMember + " = " + list + ";");
2005                                         }
2006                                 }
2007                                 
2008                                 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
2009                                 
2010                                 GenerateEndHook ();
2011                         }                       
2012
2013                         if (!isValueList)
2014                         {
2015                                 WriteLine ("");
2016                                 WriteLine ("ReadEndElement();");
2017                         }
2018                 }
2019
2020                 void GenerateReadAttributeMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, ref bool first)
2021                 {
2022                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
2023                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
2024
2025                         if (GenerateReadHook (HookType.attributes, xmlMapType))
2026                                 return;
2027
2028                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
2029                         
2030                         if (anyAttrMember != null)
2031                         {
2032                                 WriteLine ("int anyAttributeIndex = 0;");
2033                                 WriteLine (anyAttrMember.TypeData.CSharpFullName + " anyAttributeArray = null;");
2034                         }
2035                         
2036                         WriteLine ("while (Reader.MoveToNextAttribute())");
2037                         WriteLineInd ("{");
2038                         first = true;
2039                         if (map.AttributeMembers != null) {
2040                                 foreach (XmlTypeMapMemberAttribute at in map.AttributeMembers)
2041                                 {
2042                                         WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (at.AttributeName) + " && Reader.NamespaceURI == " + GetLiteral (at.Namespace) + ") {");
2043                                         if (!GenerateReadMemberHook (xmlMapType, at)) {
2044                                                 GenerateSetMemberValue (at, ob, GenerateGetValueFromXmlString ("Reader.Value", at.TypeData, at.MappedType, false), isValueList);
2045                                                 GenerateEndHook ();
2046                                         }
2047                                         WriteLineUni ("}");
2048                                         first = false;
2049                                 }
2050                         }
2051                         WriteLineInd ((first?"":"else ") + "if (IsXmlnsAttribute (Reader.Name)) {");
2052
2053                         // If the map has NamespaceDeclarations,
2054                         // then store this xmlns to the given member.
2055                         // If the instance doesn't exist, then create.
2056                         
2057                         if (map.NamespaceDeclarations != null) {
2058                                 if (!GenerateReadMemberHook (xmlMapType, map.NamespaceDeclarations)) {
2059                                         string nss = ob + ".@" + map.NamespaceDeclarations.Name;
2060                                         WriteLine ("if (" + nss + " == null) " + nss + " = new XmlSerializerNamespaces ();");
2061                                         WriteLineInd ("if (Reader.Prefix == \"xmlns\")");
2062                                         WriteLine (nss + ".Add (Reader.LocalName, Reader.Value);");
2063                                         Unindent ();
2064                                         WriteLineInd ("else");
2065                                         WriteLine (nss + ".Add (\"\", Reader.Value);");
2066                                         Unindent ();
2067                                         GenerateEndHook ();
2068                                 }
2069                         }
2070                         
2071                         WriteLineUni ("}");
2072                         WriteLineInd ("else {");
2073
2074                         if (anyAttrMember != null) 
2075                         {
2076                                 if (!GenerateReadArrayMemberHook (xmlMapType, anyAttrMember, "anyAttributeIndex")) {
2077                                         WriteLine ("System.Xml.XmlAttribute attr = (System.Xml.XmlAttribute) Document.ReadNode(Reader);");
2078                                         if (typeof(System.Xml.Schema.XmlSchemaAnnotated).IsAssignableFrom (xmlMapType)) 
2079                                                 WriteLine ("ParseWsdlArrayType (attr);");
2080                                         GenerateAddListValue (anyAttrMember.TypeData, "anyAttributeArray", "anyAttributeIndex", GetCast (anyAttrMember.TypeData.ListItemTypeData, "attr"), true);
2081                                         GenerateEndHook ();
2082                                 }
2083                                 WriteLine ("anyAttributeIndex++;");
2084                         }
2085                         else {
2086                                 if (!GenerateReadHook (HookType.unknownAttribute, xmlMapType)) {
2087                                         WriteLine ("UnknownNode (" + ob + ");");
2088                                         GenerateEndHook ();
2089                                 }
2090                         }
2091
2092                         WriteLineUni ("}");
2093                         WriteLineUni ("}");
2094
2095                         if (anyAttrMember != null && !MemberHasReadReplaceHook (xmlMapType, anyAttrMember))
2096                         {
2097                                 WriteLine ("");
2098                                 WriteLine("anyAttributeArray = (" + anyAttrMember.TypeData.CSharpFullName + ") ShrinkArray (anyAttributeArray, anyAttributeIndex, " + GetTypeOf(anyAttrMember.TypeData.Type.GetElementType()) + ", true);");
2099                                 GenerateSetMemberValue (anyAttrMember, ob, "anyAttributeArray", isValueList);
2100                         }
2101                         WriteLine ("");
2102                         WriteLine ("Reader.MoveToElement ();");
2103
2104                         GenerateEndHook ();
2105                 }
2106                 
2107                 void GenerateSetListMembersDefaults (XmlTypeMapping typeMap, ClassMap map, string ob, bool isValueList)
2108                 {
2109                         if (map.ListMembers != null)
2110                         {
2111                                 ArrayList members = map.ListMembers;
2112                                 for (int n=0; n<members.Count; n++) {
2113                                         XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
2114                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList))
2115                                                 continue;
2116                                         WriteLineInd ("if (" + GenerateGetMemberValue (mem, ob, isValueList) + " == null) {");
2117                                         GenerateSetMemberValue (mem, ob, GenerateInitializeList (mem.TypeData), isValueList);
2118                                         WriteLineUni ("}");
2119                                 }
2120                         }
2121                 }
2122                 
2123                 bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, TypeData memType, bool isValueList)
2124                 {
2125                         if (isValueList) return !memType.HasPublicConstructor;
2126                         else return member.IsReadOnly (map.TypeData.Type) || !memType.HasPublicConstructor;
2127                 }
2128
2129                 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
2130                 {
2131                         GenerateSetMemberValue (member, ob, value, isValueList, false);
2132                 }
2133                 
2134                 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList, bool initializingMember)
2135                 {
2136                         if (isValueList) {
2137                                 WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
2138                                 if (member.IsOptionalValueType) {
2139                                         string val = initializingMember ? "false" : "true";
2140                                         WriteLine (ob + "[" + member.SpecifiedGlobalIndex + "] = " + val + ";");
2141                                 }
2142                         }
2143                         else {
2144                                 WriteLine (ob + ".@" + member.Name + " = " + value + ";");
2145                                 if (member.IsOptionalValueType && member.IsValueSpecifiedSettable ()) {
2146                                         string val = initializingMember ? "false" : "true";
2147                                         WriteLine (ob + "." + member.Name + "Specified = " + val + ";");
2148                                 }
2149                         }
2150                 }
2151
2152                 void GenerateSetMemberValueFromAttr (XmlTypeMapMember member, string ob, string value, bool isValueList)
2153                 {
2154                         // Enumeration values specified in custom attributes are stored as integer
2155                         // values if the custom attribute property is of type object. So, it is
2156                         // necessary to convert to the enum type before asigning the value to the field.
2157                         
2158                         if (member.TypeData.Type.IsEnum)
2159                                 value = GetCast (member.TypeData.Type, value);
2160                         GenerateSetMemberValue (member, ob, value, isValueList, true);
2161                 }
2162
2163                 string GenerateReadObjectElement (XmlTypeMapElementInfo elem)
2164                 {
2165                         switch (elem.TypeData.SchemaType)
2166                         {
2167                                 case SchemaTypes.XmlNode:
2168                                         return GetReadXmlNode (elem.TypeData, true);
2169
2170                                 case SchemaTypes.Primitive:
2171                                 case SchemaTypes.Enum:
2172                                         return GenerateReadPrimitiveValue (elem);
2173
2174                                 case SchemaTypes.Array:
2175                                         return GenerateReadListElement (elem.MappedType, null, GetLiteral(elem.IsNullable), true);
2176
2177                                 case SchemaTypes.Class:
2178                                         return GetReadObjectCall (elem.MappedType, GetLiteral(elem.IsNullable), "true");
2179
2180                                 case SchemaTypes.XmlSerializable:
2181                                         return GetCast (elem.TypeData, String.Format ("({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true))", elem.TypeData.CSharpFullName));
2182
2183                                 default:
2184                                         throw new NotSupportedException ("Invalid value type");
2185                         }
2186                 }
2187
2188                 string GenerateReadPrimitiveValue (XmlTypeMapElementInfo elem)
2189                 {
2190                         if (elem.TypeData.Type == typeof (XmlQualifiedName)) {
2191                                 if (elem.IsNullable) return "ReadNullableQualifiedName ()";
2192                                 else return "ReadElementQualifiedName ()";
2193                         }
2194                         else if (elem.IsNullable) {
2195                                 string str = GetStrTempVar ();
2196                                 WriteLine ("string " + str + " = ReadNullableString ();");
2197                                 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, true);
2198                         }
2199                         else {
2200                                 string str = GetStrTempVar ();
2201                                 WriteLine ("string " + str + " = Reader.ReadElementString ();");
2202                                 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, false);
2203                         }
2204                 }
2205                 
2206                 string GenerateGetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap, bool isNullable)
2207                 {
2208                         if (typeData.SchemaType == SchemaTypes.Array)
2209                                 return GenerateReadListString (typeMap, value);
2210                         else if (typeData.SchemaType == SchemaTypes.Enum)
2211                                 return GenerateGetEnumValue (typeMap, value, isNullable);
2212                         else if (typeData.Type == typeof (XmlQualifiedName))
2213                                 return "ToXmlQualifiedName (" + value + ")";
2214                         else 
2215                                 return XmlCustomFormatter.GenerateFromXmlString (typeData, value);
2216                 }
2217                 
2218                 string GenerateReadListElement (XmlTypeMapping typeMap, string list, string isNullable, bool canCreateInstance)
2219                 {
2220                         Type listType = typeMap.TypeData.Type;
2221                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2222                         bool doNullCheck = typeMap.TypeData.Type.IsArray;
2223
2224                         if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) 
2225                         {
2226                                 if (list == null) {
2227                                         list = GetObTempVar ();
2228                                         WriteLine (typeMap.TypeData.CSharpFullName + " " + list + " = null;");
2229                                         if (doNullCheck)
2230                                                 WriteLineInd ("if (!ReadNull()) {");
2231                                         WriteLine (list + " = " + GenerateCreateList (listType) + ";");
2232                                 } else {
2233                                         if (doNullCheck)
2234                                                 WriteLineInd ("if (!ReadNull()) {");
2235                                 }
2236                         }
2237                         else
2238                         {
2239                                 if (list != null) {
2240                                         WriteLineInd ("if (((object)" + list + ") == null)");
2241                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2242                                         Unindent ();
2243                                         doNullCheck = false;
2244                                 }
2245                                 else {
2246                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2247                                         return list;
2248                                 }
2249                         }
2250                                 
2251                         WriteLineInd ("if (Reader.IsEmptyElement) {");
2252                         WriteLine ("Reader.Skip();");
2253                         if (listType.IsArray)
2254                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", 0, " + GetTypeOf(listType.GetElementType()) + ", false);");
2255
2256                         Unindent ();
2257                         WriteLineInd ("} else {");
2258
2259                         string index = GetNumTempVar ();
2260                         WriteLine ("int " + index + " = 0;");
2261                         WriteLine ("Reader.ReadStartElement();");
2262                         WriteLine ("Reader.MoveToContent();");
2263                         WriteLine ("");
2264
2265                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
2266                         WriteLineInd ("{");
2267                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
2268                         WriteLineInd ("{");
2269
2270                         bool first = true;
2271                         foreach (XmlTypeMapElementInfo elemInfo in listMap.ItemInfo)
2272                         {
2273                                 WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (elemInfo.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (elemInfo.Namespace) + ") {");
2274                                 GenerateAddListValue (typeMap.TypeData, list, index, GenerateReadObjectElement (elemInfo), false);
2275                                 WriteLine (index + "++;");
2276                                 WriteLineUni ("}");
2277                                 first = false;
2278                         }
2279                         if (!first) WriteLine ("else UnknownNode (null);");
2280                         else WriteLine ("UnknownNode (null);");
2281                         
2282                         WriteLineUni ("}");
2283                         WriteLine ("else UnknownNode (null);");
2284                         WriteLine ("");
2285                         WriteLine ("Reader.MoveToContent();");
2286                         WriteLineUni ("}");
2287                         
2288                         WriteLine ("ReadEndElement();");
2289
2290                         if (listType.IsArray)
2291                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + index + ", " + GetTypeOf(listType.GetElementType()) + ", false);");
2292
2293                         WriteLineUni ("}");
2294                         if (doNullCheck)
2295                                 WriteLineUni ("}");
2296
2297                         return list;
2298                 }
2299
2300                 string GenerateReadListString (XmlTypeMapping typeMap, string values)
2301                 {
2302                         Type listType = typeMap.TypeData.Type;
2303                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2304                         string itemType = ToCSharpFullName (listType.GetElementType());
2305                         
2306                         string list = GetObTempVar ();
2307                         WriteLine (itemType + "[] " + list + ";");
2308                         
2309                         string var = GetStrTempVar ();
2310                         WriteLine ("string " + var + " = " + values + ".Trim();");
2311                         WriteLineInd ("if (" + var + " != string.Empty) {");
2312                         
2313                         string valueArray = GetObTempVar ();
2314                         WriteLine ("string[] " + valueArray + " = " + var + ".Split (' ');");
2315                         
2316                         WriteLine (list + " = new " + GetArrayDeclaration (listType, valueArray + ".Length") + ";");
2317                         
2318                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)listMap.ItemInfo[0];
2319
2320                         string index = GetNumTempVar ();
2321                         WriteLineInd ("for (int " + index + " = 0; " + index + " < " + valueArray + ".Length; " + index + "++)");
2322                         WriteLine (list + "[" + index + "] = " + GenerateGetValueFromXmlString (valueArray + "[" + index + "]", info.TypeData, info.MappedType, info.IsNullable) + ";");
2323                         Unindent ();
2324                         WriteLineUni ("}");
2325                         WriteLine ("else");
2326                         WriteLine ("\t" + list + " = new " + GetArrayDeclaration (listType, "0") + ";");
2327                         
2328                         return list;
2329                 }
2330                 
2331                 string GetArrayDeclaration (Type type, string length)
2332                 {
2333                         Type t = type.GetElementType();
2334                         System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2335                         sb.Append ('[').Append (length).Append (']');
2336                         while (t.IsArray) {
2337                                 sb.Append ("[]");
2338                                 t = t.GetElementType();
2339                         }
2340                         sb.Insert (0, ToCSharpFullName (t));
2341                         return sb.ToString ();
2342                 }
2343
2344                 void GenerateAddListValue (TypeData listType, string list, string index, string value, bool canCreateInstance)
2345                 {
2346                         Type type = listType.Type;
2347                         if (type.IsArray)
2348                         {
2349                                 WriteLine (list + " = (" + ToCSharpFullName (type) + ") EnsureArrayIndex (" + list + ", " + index + ", " + GetTypeOf(type.GetElementType()) + ");");
2350                                 WriteLine (list + "[" + index + "] = " + value + ";");
2351                         }
2352                         else    // Must be IEnumerable
2353                         {
2354                                 WriteLine ("if (((object)" + list + ") == null)");
2355                                 if (canCreateInstance) 
2356                                         WriteLine ("\t" + list + String.Format (" = ({0}) Activator.CreateInstance(typeof({0}), true);", listType.CSharpFullName));
2357                                 else 
2358                                         WriteLine ("\tthrow CreateReadOnlyCollectionException (" + GetLiteral (listType.CSharpFullName) + ");");
2359                                 
2360                                 WriteLine (list + ".Add (" + value + ");");
2361                         }
2362                 }
2363
2364                 string GenerateCreateList (Type listType)
2365                 {
2366                         if (listType.IsArray)
2367                                 return "(" + ToCSharpFullName (listType) + ") EnsureArrayIndex (null, 0, " + GetTypeOf(listType.GetElementType()) + ")";
2368                         else
2369                                 return "new " + ToCSharpFullName (listType) + "()";
2370                 }
2371                 
2372                 string GenerateInitializeList (TypeData listType)
2373                 {
2374                         if (listType.Type.IsArray)
2375                                 return "null";
2376                         else
2377                                 return "new " + listType.CSharpFullName + "()";
2378                 }
2379                 
2380                 void GenerateFillerCallbacks ()
2381                 {
2382                         foreach (TypeData td in _listsToFill)
2383                         {
2384                                 string metName = GetFillListName (td);
2385                                 WriteLine ("void " + metName + " (object list, object source)");
2386                                 WriteLineInd ("{");
2387                                 WriteLine ("if (((object)list) == null) throw CreateReadOnlyCollectionException (" + GetLiteral (td.CSharpFullName) + ");");
2388                                 WriteLine ("");
2389
2390                                 WriteLine (td.CSharpFullName + " dest = (" + td.CSharpFullName + ") list;");
2391                                 WriteLine ("foreach (object ob in (IEnumerable)source)");
2392                                 WriteLine ("\tdest.Add (" + GetCast (td.ListItemTypeData, "ob") + ");");
2393                                 WriteLineUni ("}");
2394                                 WriteLine ("");
2395                         }
2396                 }
2397
2398                 void GenerateReadXmlNodeElement (XmlTypeMapping typeMap, string isNullable)
2399                 {
2400                         WriteLine ("return " + GetReadXmlNode (typeMap.TypeData, false) + ";");
2401                 }
2402
2403                 void GenerateReadPrimitiveElement (XmlTypeMapping typeMap, string isNullable)
2404                 {
2405                         WriteLine ("XmlQualifiedName t = GetXsiType();");
2406                         WriteLine ("if (t == null) t = new XmlQualifiedName (" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.Namespace) + ");");
2407                         WriteLine ("return " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
2408                 }
2409
2410                 void GenerateReadEnumElement (XmlTypeMapping typeMap, string isNullable)
2411                 {
2412                         WriteLine ("Reader.ReadStartElement ();");
2413                         WriteLine (typeMap.TypeData.CSharpFullName + " res = " + GenerateGetEnumValue (typeMap, "Reader.ReadString()", false) + ";");
2414                         WriteLineInd ("if (Reader.NodeType != XmlNodeType.None)");
2415                         WriteLineUni ("Reader.ReadEndElement ();");
2416                         WriteLine ("return res;");
2417                 }
2418
2419                 string GenerateGetEnumValue (XmlTypeMapping typeMap, string val, bool isNullable)
2420                 {
2421                         if (isNullable)
2422                                 return "(" + val + ") != null ? " + GetGetEnumValueName (typeMap) + " (" + val + ") : (" + typeMap.TypeData.CSharpFullName + "?) null";
2423                         else
2424                                 return GetGetEnumValueName (typeMap) + " (" + val + ")";
2425                 }
2426                 
2427                 void GenerateGetEnumValueMethod (XmlTypeMapping typeMap)
2428                 {
2429                         string metName = GetGetEnumValueName (typeMap);
2430                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2431
2432                         if (map.IsFlags)
2433                         {
2434                                 string switchMethod =  metName + "_Switch";
2435                                 WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2436                                 WriteLineInd ("{");
2437                                 WriteLine ("xmlName = xmlName.Trim();");
2438                                 WriteLine ("if (xmlName.Length == 0) return (" + typeMap.TypeData.CSharpFullName + ")0;");
2439                                 WriteLine (typeMap.TypeData.CSharpFullName + " sb = (" + typeMap.TypeData.CSharpFullName + ")0;");
2440                                 WriteLine ("string[] enumNames = xmlName.Split (null);");
2441                                 WriteLine ("foreach (string name in enumNames)");
2442                                 WriteLineInd ("{");
2443                                 WriteLine ("if (name == string.Empty) continue;");
2444                                 WriteLine ("sb |= " + switchMethod + " (name); ");
2445                                 WriteLineUni ("}");
2446                                 WriteLine ("return sb;");
2447                                 WriteLineUni ("}");
2448                                 WriteLine ("");
2449                                 metName = switchMethod;
2450                         }
2451
2452                         WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2453                         WriteLineInd ("{");
2454                         GenerateGetSingleEnumValue (typeMap, "xmlName");
2455                         WriteLineUni ("}");
2456                         WriteLine ("");
2457                 }
2458                 
2459                 void GenerateGetSingleEnumValue (XmlTypeMapping typeMap, string val)
2460                 {
2461                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2462                         WriteLine ("switch (" + val + ")");
2463                         WriteLineInd ("{");
2464                         foreach (EnumMap.EnumMapMember mem in map.Members)
2465                         {
2466                                 WriteLine ("case " + GetLiteral (mem.XmlName) + ": return " + typeMap.TypeData.CSharpFullName + ".@" + mem.EnumName + ";");
2467                         }
2468                         WriteLineInd ("default:");
2469                         WriteLine ("throw CreateUnknownConstantException (" + val + ", typeof(" + typeMap.TypeData.CSharpFullName + "));");
2470                         Unindent ();
2471                         WriteLineUni ("}");
2472                 }
2473                 
2474                 void GenerateReadXmlSerializableElement (XmlTypeMapping typeMap, string isNullable)
2475                 {
2476                         WriteLine ("Reader.MoveToContent ();");
2477                         WriteLine ("if (Reader.NodeType == XmlNodeType.Element)");
2478                         WriteLineInd ("{");
2479                         if (!typeMap.IsAny)
2480                                 WriteLineInd ("if (Reader.LocalName == " + GetLiteral (typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
2481                         WriteLine (String.Format ("\treturn ({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true));", typeMap.TypeData.CSharpFullName));
2482                         Unindent ();
2483                         if (!typeMap.IsAny) {
2484                                 WriteLine ("else");
2485                                 WriteLine ("\tthrow CreateUnknownNodeException ();");
2486                         }
2487                         WriteLineUni ("}");
2488                         WriteLine ("else UnknownNode (null);");
2489                         WriteLine ("");
2490                         WriteLine ("return default (" + typeMap.TypeData.CSharpFullName + ");");
2491                 }
2492
2493                 void GenerateReadInitCallbacks ()
2494                 {
2495                         WriteLine ("protected override void InitCallbacks ()");
2496                         WriteLineInd ("{");
2497
2498                         if (_format == SerializationFormat.Encoded)
2499                         {
2500                                 foreach (XmlMapping xmap in _mapsToGenerate)  
2501                                 {
2502                                         XmlTypeMapping map = xmap as XmlTypeMapping;
2503                                         if (map == null) continue;
2504                                         if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
2505                                                 WriteMetCall ("AddReadCallback", GetLiteral (map.XmlType), GetLiteral(map.Namespace), GetTypeOf(map.TypeData.Type), "new XmlSerializationReadCallback (" + GetReadObjectName (map) + ")");
2506                                 }
2507                         }
2508                         
2509                         WriteLineUni ("}");
2510                         WriteLine ("");
2511
2512                         WriteLine ("protected override void InitIDs ()");
2513                         WriteLine ("{");
2514                         WriteLine ("}");
2515                         WriteLine ("");
2516                 }
2517
2518                 void GenerateFixupCallbacks ()
2519                 {
2520                         foreach (XmlMapping map in _fixupCallbacks)
2521                         {
2522                                 bool isList = map is XmlMembersMapping;
2523                                 string tname = !isList ? ((XmlTypeMapping)map).TypeData.CSharpFullName : "object[]";
2524                                 WriteLine ("void " + GetFixupCallbackName (map) + " (object obfixup)");
2525                                 WriteLineInd ("{");                                     
2526                                 WriteLine ("Fixup fixup = (Fixup)obfixup;");
2527                                 WriteLine (tname + " source = (" + tname + ") fixup.Source;");
2528                                 WriteLine ("string[] ids = fixup.Ids;");
2529                                 WriteLine ("");
2530
2531                                 ClassMap cmap = (ClassMap)map.ObjectMap;
2532                                 ICollection members = cmap.ElementMembers;
2533                                 if (members != null) {
2534                                         foreach (XmlTypeMapMember member in members)
2535                                         {
2536                                                 WriteLineInd ("if (ids[" + member.Index + "] != null)");
2537                                                 string val = "GetTarget(ids[" + member.Index + "])";
2538                                                 if (!isList) val = GetCast (member.TypeData, val);
2539                                                 GenerateSetMemberValue (member, "source", val, isList);
2540                                                 Unindent ();
2541                                         }
2542                                 }
2543                                 WriteLineUni ("}");
2544                                 WriteLine ("");
2545                         }
2546                 }
2547
2548                 string GetReadXmlNode (TypeData type, bool wrapped)
2549                 {
2550                         if (type.Type == typeof (XmlDocument))
2551                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlDocument)), "ReadXmlDocument (" + GetLiteral(wrapped) + ")");
2552                         else
2553                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlNode)), "ReadXmlNode (" + GetLiteral(wrapped) + ")");
2554                 }
2555                 
2556                 #endregion
2557                 
2558                 #region Helper methods
2559
2560                 //*******************************************************
2561                 // Helper methods
2562                 //
2563                 
2564                 ArrayList _listsToFill = new ArrayList ();
2565                 Hashtable _hookVariables;
2566                 Stack _hookContexts;
2567                 Stack _hookOpenHooks;
2568                 
2569                 class HookInfo {
2570                         public HookType HookType;
2571                         public Type Type;
2572                         public string Member;
2573                         public HookDir Direction;
2574                 }
2575
2576                 void InitHooks ()
2577                 {
2578                         _hookContexts = new Stack ();
2579                         _hookOpenHooks = new Stack ();
2580                         _hookVariables = new Hashtable ();
2581                 }
2582                 
2583                 void PushHookContext ()
2584                 {
2585                         _hookContexts.Push (_hookVariables);
2586                         _hookVariables = (Hashtable) _hookVariables.Clone ();
2587                 }
2588                 
2589                 void PopHookContext ()
2590                 {
2591                         _hookVariables = (Hashtable) _hookContexts.Pop ();
2592                 }
2593                 
2594                 void SetHookVar (string var, string value)
2595                 {
2596                         _hookVariables [var] = value;
2597                 }
2598
2599                 bool GenerateReadHook (HookType hookType, Type type)
2600                 {
2601                         return GenerateHook (hookType, HookDir.Read, type, null);
2602                 }
2603
2604                 bool GenerateWriteHook (HookType hookType, Type type)
2605                 {
2606                         return GenerateHook (hookType, HookDir.Write, type, null);
2607                 }
2608                 
2609                 bool GenerateWriteMemberHook (Type type, XmlTypeMapMember member)
2610                 {
2611                         SetHookVar ("$MEMBER", member.Name);
2612                         return GenerateHook (HookType.member, HookDir.Write, type, member.Name);
2613                 }
2614                 
2615                 bool GenerateReadMemberHook (Type type, XmlTypeMapMember member)
2616                 {
2617                         SetHookVar ("$MEMBER", member.Name);
2618                         return GenerateHook (HookType.member, HookDir.Read, type, member.Name);
2619                 }
2620                 
2621                 bool GenerateReadArrayMemberHook (Type type, XmlTypeMapMember member, string index)
2622                 {
2623                         SetHookVar ("$INDEX", index);
2624                         return GenerateReadMemberHook (type, member);
2625                 }
2626         
2627                 bool MemberHasReadReplaceHook (Type type, XmlTypeMapMember member)
2628                 {
2629                         if (_config == null) return false;
2630                         return _config.GetHooks (HookType.member, HookDir.Read, HookAction.Replace, type, member.Name).Count > 0;
2631                 }
2632                 
2633                 bool GenerateHook (HookType hookType, HookDir dir, Type type, string member)
2634                 {
2635                         GenerateHooks (hookType, dir, type, null, HookAction.InsertBefore);
2636                         if (GenerateHooks (hookType, dir, type, null, HookAction.Replace))
2637                         {
2638                                 GenerateHooks (hookType, dir, type, null, HookAction.InsertAfter);
2639                                 return true;
2640                         }
2641                         else
2642                         {
2643                                 HookInfo hi = new HookInfo ();
2644                                 hi.HookType = hookType;
2645                                 hi.Type = type;
2646                                 hi.Member = member;
2647                                 hi.Direction = dir;
2648                                 _hookOpenHooks.Push (hi);
2649                                 return false;
2650                         }
2651                 }
2652                 
2653                 void GenerateEndHook ()
2654                 {
2655                         HookInfo hi = (HookInfo) _hookOpenHooks.Pop();
2656                         GenerateHooks (hi.HookType, hi.Direction, hi.Type, hi.Member, HookAction.InsertAfter);
2657                 }
2658                 
2659                 bool GenerateHooks (HookType hookType, HookDir dir, Type type, string member, HookAction action)
2660                 {
2661                         if (_config == null) return false;
2662                         ArrayList hooks = _config.GetHooks (hookType, dir, action, type, null);
2663                         if (hooks.Count == 0) return false;                     
2664                         foreach (Hook hook in hooks)
2665                         {
2666                                 string code = hook.GetCode (action);
2667                                 foreach (DictionaryEntry de in _hookVariables)
2668                                         code = code.Replace ((string)de.Key, (string)de.Value);
2669                                 WriteMultilineCode (code);
2670                         }
2671                         return true;
2672                 }
2673                 
2674                 string GetRootTypeName ()
2675                 {
2676                         if (_typeMap is XmlTypeMapping) return GetTypeFullName (((XmlTypeMapping)_typeMap).TypeData);
2677                         else return "object[]";
2678                 }
2679
2680                 string GetNumTempVar ()
2681                 {
2682                         return "n" + (_tempVarId++);
2683                 }
2684                 
2685                 string GetObTempVar ()
2686                 {
2687                         return "o" + (_tempVarId++);
2688                 }
2689                 
2690                 string GetStrTempVar ()
2691                 {
2692                         return "s" + (_tempVarId++);
2693                 }
2694                 
2695                 string GetBoolTempVar ()
2696                 {
2697                         return "b" + (_tempVarId++);
2698                 }
2699                 
2700                 string GetUniqueName (string uniqueGroup, object ob, string name)
2701                 {
2702                         name = CodeIdentifier.MakeValid (name.Replace ("[]","_array"));
2703                         Hashtable names = (Hashtable) _uniqueNames [uniqueGroup];
2704                         if (names == null) {
2705                                 names = new Hashtable ();
2706                                 _uniqueNames [uniqueGroup] = names; 
2707                         }
2708                         
2709                         string res = (string) names [ob];
2710                         if (res != null) return res;
2711
2712                         foreach (string n in names.Values)
2713                                 if (n == name) return GetUniqueName (uniqueGroup, ob, name + (_methodId++));
2714                                 
2715                         names [ob] = name;
2716                         return name;
2717                 }
2718                 
2719                 void RegisterReferencingMap (XmlTypeMapping typeMap)
2720                 {
2721                         if (typeMap != null && !_mapsToGenerate.Contains (typeMap))
2722                                 _mapsToGenerate.Add (typeMap);
2723                 }
2724                 
2725                 string GetWriteObjectName (XmlTypeMapping typeMap)
2726                 {
2727                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2728                         return GetUniqueName ("rw", typeMap, "WriteObject_" + typeMap.XmlType);
2729                 }
2730                 
2731                 string GetReadObjectName (XmlTypeMapping typeMap)
2732                 {
2733                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2734                         return GetUniqueName ("rr", typeMap, "ReadObject_" + typeMap.XmlType);
2735                 }
2736                 
2737                 string GetGetEnumValueName (XmlTypeMapping typeMap)
2738                 {
2739                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2740                         return GetUniqueName ("ge", typeMap, "GetEnumValue_" + typeMap.XmlType);
2741                 }
2742
2743                 string GetWriteObjectCallbackName (XmlTypeMapping typeMap)
2744                 {
2745                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2746                         return GetUniqueName ("wc", typeMap, "WriteCallback_" + typeMap.XmlType);
2747                 }
2748                 
2749                 string GetFixupCallbackName (XmlMapping typeMap)
2750                 {
2751                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2752                         
2753                         if (typeMap is XmlTypeMapping)
2754                                 return GetUniqueName ("fc", typeMap, "FixupCallback_" + ((XmlTypeMapping)typeMap).XmlType);
2755                         else
2756                                 return GetUniqueName ("fc", typeMap, "FixupCallback__Message");
2757                 }
2758                 
2759                 string GetUniqueClassName (string s)
2760                 {
2761                         return classNames.AddUnique (CodeIdentifier.MakeValid (s), null);
2762                 }
2763                 
2764                 string GetReadObjectCall (XmlTypeMapping typeMap, string isNullable, string checkType)
2765                 {
2766                         if (_format == SerializationFormat.Literal)
2767                                 return GetReadObjectName (typeMap) + " (" + isNullable + ", " + checkType + ")";
2768                         else
2769                                 return GetCast (typeMap.TypeData, GetReadObjectName (typeMap) + " ()");
2770                 }
2771                 
2772                 string GetFillListName (TypeData td)
2773                 {
2774                         if (!_listsToFill.Contains (td)) _listsToFill.Add (td);
2775                         return GetUniqueName ("fl", td, "Fill_" + CodeIdentifier.MakeValid (td.CSharpName));
2776                 }
2777                 
2778                 string GetCast (TypeData td, TypeData tdval, string val)
2779                 {
2780                         if (td.CSharpFullName == tdval.CSharpFullName) return val;
2781                         else return GetCast (td, val);
2782                 }
2783
2784                 string GetCast (TypeData td, string val)
2785                 {
2786                         return "((" + GetTypeFullName (td) + ") " + val + ")";
2787                 }
2788
2789                 string GetCast (Type td, string val)
2790                 {
2791                         return "((" + ToCSharpFullName (td) + ") " + val + ")";
2792                 }
2793
2794                 string GetTypeOf (TypeData td)
2795                 {
2796                         return "typeof(" + GetTypeFullName (td) + ")";
2797                 }
2798                 
2799                 string GetTypeOf (Type td)
2800                 {
2801                         return "typeof(" + ToCSharpFullName (td) + ")";
2802                 }
2803
2804                 string GetTypeFullName (TypeData td) {
2805                         if (td.IsNullable && td.IsValueType)
2806                                 return td.CSharpFullName + "?";
2807
2808                         return td.CSharpFullName;
2809                 }
2810                 
2811                 string GetLiteral (object ob)
2812                 {
2813                         if (ob == null) return "null";
2814                         if (ob is string) return "\"" + ob.ToString().Replace("\"","\"\"") + "\"";
2815                         if (ob is char) return (char) ob == '\'' ? "'\\''" : "'" + ob.ToString () + "'";
2816                         if (ob is DateTime) return "new DateTime (" + ((DateTime) ob).Ticks + ")";
2817 #if NET_2_0
2818                         if (ob is DateTimeOffset) return "new DateTimeOffset (" + ((DateTimeOffset) ob).Ticks + ")";
2819 #endif
2820                         if (ob is TimeSpan) return "new TimeSpan (" + ((TimeSpan) ob).Ticks + ")";
2821                         if (ob is bool) return ((bool)ob) ? "true" : "false";
2822                         if (ob is XmlQualifiedName) {
2823                                 XmlQualifiedName qn = (XmlQualifiedName)ob;
2824                                 return "new XmlQualifiedName (" + GetLiteral(qn.Name) + "," + GetLiteral(qn.Namespace) + ")";
2825                         }
2826                         if (ob is Enum) {
2827                                 string typeName = ToCSharpFullName (ob.GetType ());
2828                                 StringBuilder sb = new StringBuilder ();
2829                                 string namedValue = Enum.Format (ob.GetType (), ob, "g");
2830                                 string[] names = namedValue.Split (',');
2831                                 foreach (string name in names) {
2832                                         // individual named constants can be seperated by a comma
2833                                         // combined with some additional whitespace characters
2834                                         string cleanName = name.Trim ();
2835                                         if (cleanName.Length == 0)
2836                                                 continue;
2837
2838                                         if (sb.Length > 0)
2839                                                 sb.Append (" | ");
2840
2841                                         sb.Append (typeName);
2842                                         sb.Append ('.');
2843                                         sb.Append (cleanName);
2844                                 }
2845                                 return sb.ToString ();
2846                         }
2847
2848                         return (ob is IFormattable) ? ((IFormattable) ob).ToString (null, CultureInfo.InvariantCulture) : ob.ToString ();
2849                 }
2850                 
2851                 void WriteLineInd (string code)
2852                 {
2853                         WriteLine (code);
2854                         _indent++;
2855                 }
2856                 
2857                 void WriteLineUni (string code)
2858                 {
2859                         if (_indent > 0) _indent--;
2860                         WriteLine (code);
2861                 }
2862
2863                 void Write (string code)
2864                 {
2865                         if (code.Length > 0) 
2866                                 _writer.Write (new String ('\t', _indent));
2867                         _writer.Write (code);
2868                 }
2869
2870                 void WriteUni (string code)
2871                 {
2872                         if (_indent > 0) _indent--;
2873                         _writer.Write (code);
2874                         _writer.WriteLine (string.Empty);
2875                 }
2876
2877                 void WriteLine (string code)
2878                 {
2879                         if (code.Length > 0)
2880                                 _writer.Write (new String ('\t',_indent));
2881                         _writer.WriteLine (code);
2882                 }
2883                 
2884                 void WriteMultilineCode (string code)
2885                 {
2886                         string tabs = new string ('\t',_indent);
2887                         code = code.Replace ("\r","");
2888                         code = code.Replace ("\t","");
2889                         while (code.StartsWith ("\n")) code = code.Substring (1);
2890                         while (code.EndsWith ("\n")) code = code.Substring (0, code.Length - 1);
2891                         code = code.Replace ("\n", "\n" + tabs);
2892                         WriteLine (code);
2893                 }
2894                 
2895                 string Params (params string[] pars)
2896                 {
2897                         string res = "";
2898                         foreach (string p in pars)
2899                         {
2900                                 if (res != "") res += ", ";
2901                                 res += p;
2902                         }
2903                         return res;
2904                 }
2905                 
2906                 void WriteMetCall (string method, params string[] pars)
2907                 {
2908                         WriteLine (method + " (" + Params (pars) + ");");
2909                 }
2910                 
2911                 void Unindent ()
2912                 {
2913                         _indent--;
2914                 }
2915
2916                 #endregion
2917
2918         }
2919         
2920         internal class GenerationResult
2921         {
2922                 public XmlMapping Mapping;
2923                 public string ReaderClassName;
2924                 public string ReadMethodName;
2925                 public string WriterClassName;
2926                 public string WriteMethodName;
2927                 public string Namespace;
2928 #if NET_2_0             
2929                 public string SerializerClassName;
2930 #endif          
2931                 public string BaseSerializerClassName;
2932                 public string ImplementationClassName;
2933         }
2934         
2935 }