[System.Net] Add support for .pac proxy config scripts on mac
[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) + " (" + map.TypeData.CSharpFullName + " 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) + " (" + typeMap.TypeData.CSharpFullName + " 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, false);");
657                                 else 
658                                         WriteLine ("WriteElementEncoded (ob, \"\", \"\", true, false);");
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);");
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));
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.IsOptionalValueType)
1246                                 return ob + ".@" + member.Name + "Specified";
1247                         return null;
1248                 }
1249
1250                 void GenerateWriteInitCallbacks ()
1251                 {
1252                         WriteLine ("protected override void InitCallbacks ()");
1253                         WriteLineInd ("{");
1254                         
1255                         if (_format == SerializationFormat.Encoded)
1256                         {
1257                                 foreach (XmlMapping xmap in _mapsToGenerate)  {
1258                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1259                                         if (map != null)
1260                                                 WriteMetCall ("AddWriteCallback", GetTypeOf(map.TypeData), GetLiteral(map.XmlType), GetLiteral(map.Namespace), "new XmlSerializationWriteCallback (" + GetWriteObjectCallbackName (map) + ")");
1261                                 }
1262                         }       
1263                         
1264                         WriteLineUni ("}");
1265                         WriteLine ("");
1266                                 
1267                         if (_format == SerializationFormat.Encoded)
1268                         {
1269                                 foreach (XmlTypeMapping xmap in _mapsToGenerate)  {
1270                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1271                                         if (map == null) continue;
1272                                         if (map.TypeData.SchemaType == SchemaTypes.Enum)
1273                                                 WriteWriteEnumCallback (map);
1274                                         else
1275                                                 WriteWriteObjectCallback (map);
1276                                 }
1277                         }
1278                 }
1279                 
1280                 void WriteWriteEnumCallback (XmlTypeMapping map)
1281                 {
1282                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1283                         WriteLineInd ("{");
1284                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "true", "false");
1285                         WriteLineUni ("}");
1286                         WriteLine ("");
1287                 }
1288                 
1289                 void WriteWriteObjectCallback (XmlTypeMapping map)
1290                 {
1291                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1292                         WriteLineInd ("{");
1293                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "false", "false");
1294                         WriteLineUni ("}");
1295                         WriteLine ("");
1296                 }
1297                 
1298                 #endregion
1299                 
1300                 #region Reader Generation
1301
1302                 //*******************************************************
1303                 // Reader generation
1304                 //
1305                 
1306                 public void GenerateReader (string readerClassName, ArrayList maps)
1307                 {
1308                         if (_config == null || !_config.GenerateAsInternal)
1309                                 WriteLine ("public class " + readerClassName + " : XmlSerializationReader");
1310                         else
1311                                 WriteLine ("internal class " + readerClassName + " : XmlSerializationReader");
1312                         WriteLineInd ("{");
1313                         // FromBinHexString() is not public, so use reflection here.
1314                         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);");
1315                         WriteLine ("static byte [] FromBinHexString (string input)");
1316                         WriteLineInd ("{");
1317                         WriteLine ("return input == null ? null : (byte []) fromBinHexStringMethod.Invoke (null, new object [] {input});");
1318                         WriteLineUni ("}");
1319
1320                         _mapsToGenerate = new ArrayList ();
1321                         _fixupCallbacks = new ArrayList ();
1322                         InitHooks ();
1323                         
1324                         for (int n=0; n<maps.Count; n++)
1325                         {
1326                                 GenerationResult res = (GenerationResult) maps [n];
1327                                 _typeMap = res.Mapping;
1328                                 _format = _typeMap.Format;
1329                                 _result = res;
1330                                 
1331                                 GenerateReadRoot ();
1332                         }
1333                         
1334                         for (int n=0; n<_mapsToGenerate.Count; n++)
1335                         {
1336                                 XmlTypeMapping map = _mapsToGenerate [n] as XmlTypeMapping;
1337                                 if (map == null) continue;
1338                                 
1339                                 GenerateReadObject (map);
1340                                 if (map.TypeData.SchemaType == SchemaTypes.Enum)
1341                                         GenerateGetEnumValueMethod (map);
1342                         }
1343                         
1344                         GenerateReadInitCallbacks ();
1345                         
1346                         if (_format == SerializationFormat.Encoded)
1347                         {
1348                                 GenerateFixupCallbacks ();
1349                                 GenerateFillerCallbacks ();
1350                         }
1351                         
1352                         WriteLineUni ("}");
1353                         UpdateGeneratedTypes (_mapsToGenerate);
1354                 }
1355                 
1356                 void GenerateReadRoot ()
1357                 {
1358                         WriteLine ("public object " + _result.ReadMethodName + " ()");
1359                         WriteLineInd ("{");
1360                         WriteLine ("Reader.MoveToContent();");
1361                         
1362                         if (_typeMap is XmlTypeMapping)
1363                         {
1364                                 XmlTypeMapping typeMap = (XmlTypeMapping) _typeMap;
1365
1366                                 if (_format == SerializationFormat.Literal)
1367                                 {
1368                                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode) {
1369                                                 if (typeMap.TypeData.Type == typeof (XmlDocument))
1370                                                         WriteLine ("return ReadXmlDocument (false);");
1371                                                 else
1372                                                         WriteLine ("return ReadXmlNode (false);");
1373                                         } else {
1374                                                 WriteLineInd ("if (Reader.LocalName != " + GetLiteral (typeMap.ElementName) + " || Reader.NamespaceURI != " + GetLiteral (typeMap.Namespace) + ")");
1375                                                 WriteLine ("throw CreateUnknownNodeException();");
1376                                                 Unindent ();
1377
1378                                                 WriteLine ("return " + GetReadObjectCall (typeMap, GetLiteral(typeMap.IsNullable), "true") + ";");
1379                                         }
1380                                 }
1381                                 else
1382                                 {
1383                                         WriteLine ("object ob = null;");
1384                                         WriteLine ("Reader.MoveToContent();");
1385                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1386                                         WriteLineInd ("{");
1387                                         WriteLineInd ("if (Reader.LocalName == " + GetLiteral(typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
1388                                         WriteLine ("ob = ReadReferencedElement();");
1389                                         Unindent ();
1390                                         WriteLineInd ("else ");
1391                                         WriteLine ("throw CreateUnknownNodeException();");
1392                                         Unindent ();
1393                                         WriteLineUni ("}");
1394                                         WriteLineInd ("else ");
1395                                         WriteLine ("UnknownNode(null);");
1396                                         Unindent ();
1397                                         WriteLine ("");
1398                                         WriteLine ("ReadReferencedElements();");
1399                                         WriteLine ("return ob;");
1400                                         RegisterReferencingMap (typeMap);
1401                                 }
1402                         }
1403                         else {
1404                                 WriteLine ("return " + GenerateReadMessage ((XmlMembersMapping)_typeMap) + ";");
1405                         }
1406
1407                         WriteLineUni ("}");
1408                         WriteLine ("");
1409                 }
1410                 
1411                 string GenerateReadMessage (XmlMembersMapping typeMap)
1412                 {
1413                         WriteLine ("object[] parameters = new object[" + typeMap.Count + "];");
1414                         WriteLine ("");
1415
1416                         if (typeMap.HasWrapperElement)
1417                         {
1418                                 if (_format == SerializationFormat.Encoded)
1419                                 {
1420                                         WriteLine ("while (Reader.NodeType == System.Xml.XmlNodeType.Element)");
1421                                         WriteLineInd ("{");
1422                                         WriteLine ("string root = Reader.GetAttribute (\"root\", " + GetLiteral(XmlSerializer.EncodingNamespace) + ");");
1423                                         WriteLine ("if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break;");
1424                                         WriteLine ("ReadReferencedElement ();");
1425                                         WriteLine ("Reader.MoveToContent ();");
1426                                         WriteLineUni ("}");
1427                                         WriteLine ("");
1428                                         WriteLine ("if (Reader.NodeType != System.Xml.XmlNodeType.EndElement)");
1429                                         WriteLineInd ("{");
1430                                         WriteLineInd ("if (Reader.IsEmptyElement) {");
1431                                         WriteLine ("Reader.Skip();");
1432                                         WriteLine ("Reader.MoveToContent();");
1433                                         WriteLineUni ("}");
1434                                         WriteLineInd ("else {");
1435                                         WriteLine ("Reader.ReadStartElement();");
1436                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1437                                         WriteLine ("ReadEndElement();");
1438                                         WriteLineUni ("}");
1439                                         WriteLine ("");
1440                                         WriteLine ("Reader.MoveToContent();");
1441                                         WriteLineUni ("}");
1442                                 }
1443                                 else
1444                                 {
1445                                         // bug #79988: out parameters need to be initialized if 
1446                                         // they are value types
1447                                         ClassMap classMap = (ClassMap) typeMap.ObjectMap;
1448                                         ArrayList members = classMap.AllMembers;
1449                                         for (int n = 0; n < members.Count; n++) {
1450                                                 XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
1451                                                 if (!mem.IsReturnValue && mem.TypeData.IsValueType)
1452                                                         GenerateSetMemberValueFromAttr (mem, "parameters",
1453                                                                 String.Format ("({0}) Activator.CreateInstance(typeof({0}), true)", mem.TypeData.FullTypeName), true);
1454                                         }
1455
1456                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.ReadState == ReadState.Interactive)");
1457                                         WriteLineInd ("{");
1458                                         WriteLine ("if (Reader.IsStartElement(" + GetLiteral(typeMap.ElementName) + ", " + GetLiteral(typeMap.Namespace) + "))");
1459                                         WriteLineInd ("{");
1460                                         bool dummy = false;
1461                                         GenerateReadAttributeMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, ref dummy);
1462                                         WriteLine ("if (Reader.IsEmptyElement)");
1463                                         WriteLineInd ("{");
1464                                         WriteLine ("Reader.Skip(); Reader.MoveToContent(); continue;");
1465                                         WriteLineUni ("}");
1466                                         WriteLine ("Reader.ReadStartElement();");
1467                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1468                                         WriteLine ("ReadEndElement();");
1469                                         WriteLine ("break;");
1470                                         WriteLineUni ("}");
1471                                         WriteLineInd ("else ");
1472                                         WriteLine ("UnknownNode(null);");
1473                                         Unindent ();
1474                                         WriteLine ("");
1475                                         WriteLine ("Reader.MoveToContent();");
1476                                         WriteLineUni ("}");
1477                                 }
1478                         }
1479                         else
1480                                 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, _format == SerializationFormat.Encoded);
1481
1482                         if (_format == SerializationFormat.Encoded)
1483                                 WriteLine ("ReadReferencedElements();");
1484
1485                         return "parameters";
1486                 }
1487                 
1488                 void GenerateReadObject (XmlTypeMapping typeMap)
1489                 {
1490                         string isNullable;
1491                         if (_format == SerializationFormat.Literal) {
1492                                 WriteLine ("public " + typeMap.TypeData.CSharpFullName + " " + GetReadObjectName (typeMap) + " (bool isNullable, bool checkType)");
1493                                 isNullable = "isNullable";
1494                         }
1495                         else {
1496                                 WriteLine ("public object " + GetReadObjectName (typeMap) + " ()");
1497                                 isNullable = "true";
1498                         }
1499                         
1500                         WriteLineInd ("{");
1501
1502                         PushHookContext ();
1503                         
1504                         SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
1505                         SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
1506                         SetHookVar ("$NULLABLE", "isNullable");
1507                         
1508                         switch (typeMap.TypeData.SchemaType)
1509                         {
1510                                 case SchemaTypes.Class: GenerateReadClassInstance (typeMap, isNullable, "checkType"); break;
1511                                 case SchemaTypes.Array: 
1512                                         string list = GenerateReadListElement (typeMap, null, isNullable, true);
1513                                         if (list != null)
1514                                                 WriteLine ("return " + list + ";"); 
1515                                         break;
1516                                 case SchemaTypes.XmlNode: GenerateReadXmlNodeElement (typeMap, isNullable); break;
1517                                 case SchemaTypes.Primitive: GenerateReadPrimitiveElement (typeMap, isNullable); break;
1518                                 case SchemaTypes.Enum: GenerateReadEnumElement (typeMap, isNullable); break;
1519                                 case SchemaTypes.XmlSerializable: GenerateReadXmlSerializableElement (typeMap, isNullable); break;
1520                                 default: throw new Exception ("Unsupported map type");
1521                         }
1522                         
1523                         WriteLineUni ("}");
1524                         WriteLine ("");
1525                         PopHookContext ();
1526                 }
1527                                 
1528                 void GenerateReadClassInstance (XmlTypeMapping typeMap, string isNullable, string checkType)
1529                 {
1530                         SetHookVar ("$OBJECT", "ob");
1531                         if (!typeMap.TypeData.IsValueType)
1532                         {
1533                                 WriteLine (typeMap.TypeData.CSharpFullName + " ob = null;");
1534                         
1535                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1536                                         WriteLine ("return ob;");
1537                                         return;
1538                                 }
1539                                 
1540                                 if (_format == SerializationFormat.Literal) {
1541                                         WriteLine ("if (" + isNullable + " && ReadNull()) return null;");
1542                                         WriteLine ("");
1543                                         WriteLine ("if (checkType) ");
1544                                         WriteLineInd ("{");
1545                                 }
1546                                 else {
1547                                         WriteLine ("if (ReadNull()) return null;");
1548                                         WriteLine ("");
1549                                 }
1550                         }
1551                         else
1552                         {
1553                                 WriteLine (typeMap.TypeData.CSharpFullName + String.Format (" ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1554                         
1555                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1556                                         WriteLine ("return ob;");
1557                                         return;
1558                                 }
1559                         }
1560                         
1561                         WriteLine ("System.Xml.XmlQualifiedName t = GetXsiType();");
1562                         WriteLine ("if (t == null)");
1563                         if (typeMap.TypeData.Type != typeof(object))
1564                                 WriteLine ("{ }");
1565                         else
1566                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (new System.Xml.XmlQualifiedName(\"anyType\", System.Xml.Schema.XmlSchema.Namespace))") + ";");
1567                         
1568                         foreach (XmlTypeMapping realMap in typeMap.DerivedTypes)
1569                         {
1570                                 WriteLineInd ("else if (t.Name == " + GetLiteral (realMap.XmlType) + " && t.Namespace == " + GetLiteral (realMap.XmlTypeNamespace) + ")");
1571                                 WriteLine ("return " + GetReadObjectCall(realMap, isNullable, checkType) + ";");
1572                                 Unindent ();
1573                         }
1574
1575                         WriteLine ("else if (t.Name != " + GetLiteral (typeMap.XmlType) + " || t.Namespace != " + GetLiteral (typeMap.XmlTypeNamespace) + ")");
1576                         if (typeMap.TypeData.Type == typeof(object))
1577                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
1578                         else
1579                                 WriteLine ("\tthrow CreateUnknownTypeException(t);");
1580
1581                         if (!typeMap.TypeData.IsValueType)
1582                         {
1583                                 if (_format == SerializationFormat.Literal)
1584                                         WriteLineUni ("}");
1585
1586                                 if (typeMap.TypeData.Type.IsAbstract) {
1587                                         GenerateEndHook ();
1588                                         WriteLine ("return ob;");
1589                                         return;
1590                                 }
1591         
1592                                 WriteLine ("");
1593                                 WriteLine (String.Format ("ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1594                         }
1595                         
1596                         WriteLine ("");
1597                         
1598                         WriteLine ("Reader.MoveToElement();");
1599                         WriteLine ("");
1600                         
1601                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "ob", false, false);
1602                         
1603                         WriteLine ("");
1604                         
1605                         GenerateEndHook ();
1606                         WriteLine ("return ob;");
1607                 }
1608
1609                 void GenerateReadMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, bool readBySoapOrder)
1610                 {
1611                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1612                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
1613                         
1614                         bool first = false;
1615                         // Read attributes
1616                         GenerateReadAttributeMembers (xmlMap, map, ob, isValueList, ref first);
1617
1618                         if (!isValueList)
1619                         {
1620                                 WriteLine ("Reader.MoveToElement();");
1621                                 WriteLineInd ("if (Reader.IsEmptyElement) {"); 
1622                                 WriteLine ("Reader.Skip ();");
1623                                 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1624                                 WriteLine ("return " + ob + ";");
1625                                 WriteLineUni ("}");
1626                                 WriteLine ("");
1627         
1628                                 WriteLine ("Reader.ReadStartElement();");
1629                         }
1630                         
1631                         // Reads elements
1632
1633                         WriteLine("Reader.MoveToContent();");
1634                         WriteLine ("");
1635
1636                         if (!GenerateReadHook (HookType.elements, xmlMapType))
1637                         {
1638                                 string[] readFlag = null;
1639                                 if (map.ElementMembers != null && !readBySoapOrder)
1640                                 {
1641                                         string readFlagsVars = string.Empty;
1642                                         readFlag = new string[map.ElementMembers.Count];
1643                                         int n=0;
1644                                         foreach (XmlTypeMapMember mem in map.ElementMembers) {
1645                                                 // The text collector doesn't need a flag
1646                                                 if (!((mem is XmlTypeMapMemberElement) && ((XmlTypeMapMemberElement)mem).IsXmlTextCollector)) {
1647                                                         readFlag[n] = GetBoolTempVar ();
1648                                                         if (readFlagsVars.Length > 0) readFlagsVars += ", ";
1649                                                         readFlagsVars += readFlag[n] + "=false";
1650                                                 }
1651                                                 n++;
1652                                         }
1653                                         if (readFlagsVars.Length > 0) {
1654                                                 readFlagsVars = "bool " + readFlagsVars;
1655                                                 WriteLine (readFlagsVars + ";");
1656                                         }
1657                                         foreach (XmlTypeMapElementInfo info in map.AllElementInfos)
1658                                                 if (info.ExplicitOrder >= 0) {
1659                                                         WriteLine ("int idx = -1;");
1660                                                         break;
1661                                                 }
1662                                         WriteLine ("");
1663                                 }
1664                                 
1665                                 string[] indexes = null;
1666                                 string[] flatLists = null;
1667                                 string[] flatListsChoices = null;
1668         
1669                                 if (map.FlatLists != null) 
1670                                 {
1671                                         indexes = new string[map.FlatLists.Count];
1672                                         flatLists = new string[map.FlatLists.Count];
1673                                         
1674                                         string code = "int ";
1675                                         for (int n=0; n<map.FlatLists.Count; n++) 
1676                                         {
1677                                                 XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement)map.FlatLists[n];
1678                                                 indexes[n] = GetNumTempVar ();
1679                                                 if (n > 0) code += ", ";
1680                                                 code += indexes[n] + "=0";
1681                                                 if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
1682                                                         flatLists[n] = GetObTempVar ();
1683                                                         string rval;
1684                                                         WriteLine (mem.TypeData.CSharpFullName + " " + flatLists[n] + ";");
1685                                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList)) {
1686                                                                 rval = GenerateGetMemberValue (mem, ob, isValueList);
1687                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1688                                                         } else if (mem.TypeData.Type.IsArray) {
1689                                                                 rval = GenerateInitializeList (mem.TypeData);
1690                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1691                                                         } else {
1692                                                                 WriteLine (flatLists[n] + " = " + GenerateGetMemberValue (mem, ob, isValueList) + ";");
1693                                                                 WriteLineInd ("if (((object)" + flatLists[n] + ") == null) {");
1694                                                                 WriteLine (flatLists[n] + " = " + GenerateInitializeList (mem.TypeData) + ";");
1695                                                                 GenerateSetMemberValue (mem, ob, flatLists[n], isValueList);
1696                                                                 WriteLineUni ("}");
1697                                                         }
1698                                                 }
1699                                                 
1700                                                 if (mem.ChoiceMember != null) {
1701                                                         if (flatListsChoices == null)
1702                                                                 flatListsChoices = new string [map.FlatLists.Count];
1703                                                         flatListsChoices[n] = GetObTempVar ();
1704                                                         string rval = GenerateInitializeList (mem.ChoiceTypeData);
1705                                                         WriteLine (mem.ChoiceTypeData.CSharpFullName + " " + flatListsChoices[n] + " = " + rval + ";");
1706                                                 }
1707                                         }
1708                                         WriteLine (code + ";");
1709                                         WriteLine ("");
1710                                 }
1711                                 
1712                                 if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
1713                                 {
1714                                         _fixupCallbacks.Add (xmlMap);
1715                                         WriteLine ("Fixup fixup = new Fixup(" + ob + ", new XmlSerializationFixupCallback(" + GetFixupCallbackName (xmlMap) + "), " + map.ElementMembers.Count + ");");
1716                                         WriteLine ("AddFixup (fixup);");
1717                                         WriteLine ("");
1718                                 }
1719         
1720                                 ArrayList infos = null;
1721                                 
1722                                 int maxInd;
1723                                 if (readBySoapOrder) {
1724                                         if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
1725                                         else maxInd = 0;
1726                                 }
1727                                 else
1728                                 {
1729                                         infos = new ArrayList ();
1730                                         infos.AddRange (map.AllElementInfos);
1731                                         maxInd = infos.Count;
1732                                         
1733                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
1734                                         WriteLineInd ("{");
1735                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1736                                         WriteLineInd ("{");
1737                                 }
1738                                 
1739                                 first = true;
1740                                 for (int ind = 0; ind < maxInd; ind++)
1741                                 {
1742                                         XmlTypeMapElementInfo info = readBySoapOrder ? map.GetElement (ind) : (XmlTypeMapElementInfo) infos [ind];
1743                                         
1744                                         if (!readBySoapOrder)
1745                                         {
1746                                                 if (info.IsTextElement || info.IsUnnamedAnyElement) continue;
1747                                                 string elemCond = first ? "" : "else ";
1748                                                 elemCond += "if (";
1749                                                 if (info.ExplicitOrder >= 0)
1750                                                         elemCond += "idx < " + info.ExplicitOrder + "&& ";
1751                                                 if (!(info.Member.IsReturnValue && _format == SerializationFormat.Encoded)) {
1752                                                         elemCond += "Reader.LocalName == " + GetLiteral (info.ElementName);
1753                                                         if (!map.IgnoreMemberNamespace) elemCond += " && Reader.NamespaceURI == " + GetLiteral (info.Namespace);
1754                                                         elemCond += " && ";
1755                                                 }
1756                                                 if (readFlag[info.Member.Index] != null)
1757                                                         elemCond += "!" + readFlag[info.Member.Index] + ") {";
1758                                                 else
1759                                                         elemCond += "true) {";
1760                                                 WriteLineInd (elemCond);
1761                                         }
1762         
1763                                         if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
1764                                         {
1765                                                 if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
1766                                                 {
1767                                                         string list = GetObTempVar ();
1768                                                         WriteLine ("object " + list + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1769                                                         RegisterReferencingMap (info.MappedType);
1770
1771                                                         WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // Already read
1772                                                         if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1773                                                                 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.CSharpFullName) + ");");
1774                                                         else 
1775                                                                 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1776                                                         WriteLineUni ("}");
1777         
1778                                                         if (!info.MappedType.TypeData.Type.IsArray)
1779                                                         {
1780                                                                 WriteLineInd ("else {");
1781                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1782                                                                         WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1783                                                                 else { 
1784                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1785                                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1786                                                                 }
1787                                                                 WriteLine ("AddFixup (new CollectionFixup (" + list + ", new XmlSerializationCollectionFixupCallback (" + GetFillListName(info.Member.TypeData) + "), fixup.Ids[" + info.Member.Index + "]));");
1788                                                                 WriteLine ("fixup.Ids[" + info.Member.Index + "] = null;");             // The member already has the value, no further fix needed.
1789                                                                 WriteLineUni ("}");
1790                                                         }
1791                                                 }
1792                                                 else
1793                                                 {
1794                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1795                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) {
1796                                                                         GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
1797                                                                 } else if (info.MappedType.TypeData.Type.IsArray) {
1798                                                                         if (info.IsNullable)
1799                                                                                 GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
1800                                                                         else {
1801                                                                                 string list = GetObTempVar ();
1802                                                                                 WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true) + ";");
1803                                                                                 WriteLineInd ("if (((object)" + list + ") != null) {");
1804                                                                                 GenerateSetMemberValue (info.Member, ob, list, isValueList);
1805                                                                                 WriteLineUni ("}");
1806                                                                         }
1807                                                                 } else {
1808                                                                         string list = GetObTempVar ();
1809                                                                         WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1810                                                                         WriteLineInd ("if (((object)" + list + ") == null) {");
1811                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1812                                                                         GenerateSetMemberValue (info.Member, ob, list, isValueList);
1813                                                                         WriteLineUni ("}");
1814                                                                         GenerateReadListElement (info.MappedType, list, GetLiteral(info.IsNullable), true);
1815                                                                 }
1816                                                                 GenerateEndHook ();
1817                                                         }
1818                                                 }
1819                                                 if (!readBySoapOrder)
1820                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1821                                         }
1822                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
1823                                         {
1824                                                 XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
1825                                                 if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1826                                                         GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, info.TypeData, isValueList));
1827                                                         if (mem.ChoiceMember != null) {
1828                                                                 GenerateAddListValue (mem.ChoiceTypeData, flatListsChoices[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetLiteral (info.ChoiceValue), true);
1829                                                         }
1830                                                         GenerateEndHook ();
1831                                                 }
1832                                                 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1833                                         }
1834                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
1835                                         {
1836                                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
1837                                                 if (mem.TypeData.IsListType) { 
1838                                                         if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1839                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
1840                                                                 GenerateEndHook ();
1841                                                         }
1842                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1843                                                 }
1844                                                 else {
1845                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1846                                                                 GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1847                                                                 GenerateEndHook ();
1848                                                         }
1849                                                 }
1850                                         }
1851                                         else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
1852                                         {
1853                                                 if (!readBySoapOrder)
1854                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1855                                                 if (info.ExplicitOrder >= 0)
1856                                                         WriteLine ("idx = " + info.ExplicitOrder + ";");
1857                                                 if (_format == SerializationFormat.Encoded)
1858                                                 {
1859                                                         string val = GetObTempVar ();
1860                                                         RegisterReferencingMap (info.MappedType);
1861                                                         
1862                                                         if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
1863                                                                 WriteLine ("object " + val + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1864                                                         else
1865                                                                 WriteLine ("object " + val + " = ReadReferencingElement (" + GetLiteral(info.Member.TypeData.XmlType) + ", " + GetLiteral(System.Xml.Schema.XmlSchema.Namespace) + ", out fixup.Ids[" + info.Member.Index + "]);");
1866                                                         
1867                                                         if (info.MultiReferenceType)
1868                                                                 WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // already read
1869                                                         else
1870                                                                 WriteLineInd ("if (" + val + " != null) {");    // null value
1871                                                                 
1872                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,val), isValueList);
1873                                                         WriteLineUni ("}");
1874                                                 }
1875                                                 else if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1876                                                         if (info.ChoiceValue != null) {
1877                                                                 XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement) info.Member;
1878                                                                 WriteLine (ob + ".@" + imem.ChoiceMember + " = " + GetLiteral(info.ChoiceValue) + ";");
1879                                                         }
1880                                                         GenerateSetMemberValue (info.Member, ob, GenerateReadObjectElement (info), isValueList);
1881                                                         GenerateEndHook ();
1882                                                 }
1883                                         }
1884                                         else
1885                                                 throw new InvalidOperationException ("Unknown member type");
1886         
1887                                         if (!readBySoapOrder)
1888                                                 WriteLineUni ("}");
1889                                         else
1890                                                 WriteLine ("Reader.MoveToContent();");
1891                                         first = false;
1892                                 }
1893                                 
1894                                 if (!readBySoapOrder)
1895                                 {
1896                                         if (!first) WriteLineInd ("else {");
1897                                         
1898                                         if (map.DefaultAnyElementMember != null)
1899                                         {
1900                                                 XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
1901                                                 if (mem.TypeData.IsListType) {
1902                                                         if (!GenerateReadArrayMemberHook (xmlMapType, mem, indexes[mem.FlatArrayIndex])) {
1903                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
1904                                                                 GenerateEndHook ();
1905                                                         }
1906                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1907                                                 }
1908                                                 else if (! GenerateReadMemberHook (xmlMapType, mem)) {
1909                                                         GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1910                                                         GenerateEndHook ();
1911                                                 }
1912                                         }
1913                                         else {
1914                                                 if (!GenerateReadHook (HookType.unknownElement, xmlMapType)) {
1915                                                         WriteLine ("UnknownNode (" + ob + ");");
1916                                                         GenerateEndHook ();
1917                                                 }
1918                                         }
1919                                         
1920                                         if (!first) WriteLineUni ("}");
1921                 
1922                                         WriteLineUni ("}");
1923                                         
1924                                         if (map.XmlTextCollector != null)
1925                                         {
1926                                                 WriteLine ("else if (Reader.NodeType == System.Xml.XmlNodeType.Text || Reader.NodeType == System.Xml.XmlNodeType.CDATA)");
1927                                                 WriteLineInd ("{");
1928                 
1929                                                 if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
1930                                                 {
1931                                                         XmlTypeMapMemberExpandable mem = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
1932                                                         XmlTypeMapMemberFlatList flatl = mem as XmlTypeMapMemberFlatList;
1933                                                         TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;
1934                                                         
1935                                                         if (!GenerateReadArrayMemberHook (xmlMapType, map.XmlTextCollector, indexes[mem.FlatArrayIndex])) {
1936                                                                 string val = (itype.Type == typeof (string)) ? "Reader.ReadString()" : GetReadXmlNode (itype, false);
1937                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], val, true);
1938                                                                 GenerateEndHook ();
1939                                                         }
1940                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1941                                                 }
1942                                                 else if (!GenerateReadMemberHook (xmlMapType, map.XmlTextCollector))
1943                                                 {
1944                                                         XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector;
1945                                                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0];
1946                                                         if (info.TypeData.Type == typeof (string))
1947                                                                 GenerateSetMemberValue (mem, ob, "ReadString (" + GenerateGetMemberValue (mem, ob, isValueList) + ")", isValueList);
1948                                                         else {
1949                                                                 WriteLineInd ("{");
1950                                                                 string str = GetStrTempVar ();
1951                                                                 WriteLine ("string " + str + " = Reader.ReadString();");
1952                                                                 GenerateSetMemberValue (mem, ob, GenerateGetValueFromXmlString (str, info.TypeData, info.MappedType, info.IsNullable), isValueList);
1953                                                                 WriteLineUni ("}");
1954                                                         }
1955                                                         GenerateEndHook ();
1956                                                 }
1957                                                 WriteLineUni ("}");
1958                                         }
1959                                                 
1960                                         WriteLine ("else");
1961                                         WriteLine ("\tUnknownNode(" + ob + ");");
1962                                         WriteLine ("");
1963                                         WriteLine ("Reader.MoveToContent();");
1964                                         WriteLineUni ("}");
1965                                 }
1966                                 else
1967                                         WriteLine ("Reader.MoveToContent();");
1968         
1969                                 if (flatLists != null)
1970                                 {
1971                                         WriteLine ("");
1972                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1973                                         {
1974                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1975                                                 
1976                                                 string list = flatLists[mem.FlatArrayIndex];
1977                                                 if (mem.TypeData.Type.IsArray)
1978                                                         WriteLine (list + " = (" + mem.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
1979                                                 if (!IsReadOnly (typeMap, mem, mem.TypeData, isValueList) && mem.TypeData.Type.IsArray)
1980                                                         GenerateSetMemberValue (mem, ob, list, isValueList);
1981                                         }
1982                                 }
1983                                 
1984                                 if (flatListsChoices != null)
1985                                 {
1986                                         WriteLine ("");
1987                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1988                                         {
1989                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1990                                                 if (mem.ChoiceMember == null) continue;
1991                                                 
1992                                                 string list = flatListsChoices[mem.FlatArrayIndex];
1993                                                 WriteLine (list + " = (" + mem.ChoiceTypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.ChoiceTypeData.Type.GetElementType()) + ", true);");
1994                                                 WriteLine (ob + ".@" + mem.ChoiceMember + " = " + list + ";");
1995                                         }
1996                                 }
1997                                 
1998                                 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1999                                 
2000                                 GenerateEndHook ();
2001                         }                       
2002
2003                         if (!isValueList)
2004                         {
2005                                 WriteLine ("");
2006                                 WriteLine ("ReadEndElement();");
2007                         }
2008                 }
2009
2010                 void GenerateReadAttributeMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, ref bool first)
2011                 {
2012                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
2013                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
2014
2015                         if (GenerateReadHook (HookType.attributes, xmlMapType))
2016                                 return;
2017
2018                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
2019                         
2020                         if (anyAttrMember != null)
2021                         {
2022                                 WriteLine ("int anyAttributeIndex = 0;");
2023                                 WriteLine (anyAttrMember.TypeData.CSharpFullName + " anyAttributeArray = null;");
2024                         }
2025                         
2026                         WriteLine ("while (Reader.MoveToNextAttribute())");
2027                         WriteLineInd ("{");
2028                         first = true;
2029                         if (map.AttributeMembers != null) {
2030                                 foreach (XmlTypeMapMemberAttribute at in map.AttributeMembers)
2031                                 {
2032                                         WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (at.AttributeName) + " && Reader.NamespaceURI == " + GetLiteral (at.Namespace) + ") {");
2033                                         if (!GenerateReadMemberHook (xmlMapType, at)) {
2034                                                 GenerateSetMemberValue (at, ob, GenerateGetValueFromXmlString ("Reader.Value", at.TypeData, at.MappedType, false), isValueList);
2035                                                 GenerateEndHook ();
2036                                         }
2037                                         WriteLineUni ("}");
2038                                         first = false;
2039                                 }
2040                         }
2041                         WriteLineInd ((first?"":"else ") + "if (IsXmlnsAttribute (Reader.Name)) {");
2042
2043                         // If the map has NamespaceDeclarations,
2044                         // then store this xmlns to the given member.
2045                         // If the instance doesn't exist, then create.
2046                         
2047                         if (map.NamespaceDeclarations != null) {
2048                                 if (!GenerateReadMemberHook (xmlMapType, map.NamespaceDeclarations)) {
2049                                         string nss = ob + ".@" + map.NamespaceDeclarations.Name;
2050                                         WriteLine ("if (" + nss + " == null) " + nss + " = new XmlSerializerNamespaces ();");
2051                                         WriteLineInd ("if (Reader.Prefix == \"xmlns\")");
2052                                         WriteLine (nss + ".Add (Reader.LocalName, Reader.Value);");
2053                                         Unindent ();
2054                                         WriteLineInd ("else");
2055                                         WriteLine (nss + ".Add (\"\", Reader.Value);");
2056                                         Unindent ();
2057                                         GenerateEndHook ();
2058                                 }
2059                         }
2060                         
2061                         WriteLineUni ("}");
2062                         WriteLineInd ("else {");
2063
2064                         if (anyAttrMember != null) 
2065                         {
2066                                 if (!GenerateReadArrayMemberHook (xmlMapType, anyAttrMember, "anyAttributeIndex")) {
2067                                         WriteLine ("System.Xml.XmlAttribute attr = (System.Xml.XmlAttribute) Document.ReadNode(Reader);");
2068                                         if (typeof(System.Xml.Schema.XmlSchemaAnnotated).IsAssignableFrom (xmlMapType)) 
2069                                                 WriteLine ("ParseWsdlArrayType (attr);");
2070                                         GenerateAddListValue (anyAttrMember.TypeData, "anyAttributeArray", "anyAttributeIndex", GetCast (anyAttrMember.TypeData.ListItemTypeData, "attr"), true);
2071                                         GenerateEndHook ();
2072                                 }
2073                                 WriteLine ("anyAttributeIndex++;");
2074                         }
2075                         else {
2076                                 if (!GenerateReadHook (HookType.unknownAttribute, xmlMapType)) {
2077                                         WriteLine ("UnknownNode (" + ob + ");");
2078                                         GenerateEndHook ();
2079                                 }
2080                         }
2081
2082                         WriteLineUni ("}");
2083                         WriteLineUni ("}");
2084
2085                         if (anyAttrMember != null && !MemberHasReadReplaceHook (xmlMapType, anyAttrMember))
2086                         {
2087                                 WriteLine ("");
2088                                 WriteLine("anyAttributeArray = (" + anyAttrMember.TypeData.CSharpFullName + ") ShrinkArray (anyAttributeArray, anyAttributeIndex, " + GetTypeOf(anyAttrMember.TypeData.Type.GetElementType()) + ", true);");
2089                                 GenerateSetMemberValue (anyAttrMember, ob, "anyAttributeArray", isValueList);
2090                         }
2091                         WriteLine ("");
2092                         WriteLine ("Reader.MoveToElement ();");
2093
2094                         GenerateEndHook ();
2095                 }
2096                 
2097                 void GenerateSetListMembersDefaults (XmlTypeMapping typeMap, ClassMap map, string ob, bool isValueList)
2098                 {
2099                         if (map.ListMembers != null)
2100                         {
2101                                 ArrayList members = map.ListMembers;
2102                                 for (int n=0; n<members.Count; n++) {
2103                                         XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
2104                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList))
2105                                                 continue;
2106                                         WriteLineInd ("if (" + GenerateGetMemberValue (mem, ob, isValueList) + " == null) {");
2107                                         GenerateSetMemberValue (mem, ob, GenerateInitializeList (mem.TypeData), isValueList);
2108                                         WriteLineUni ("}");
2109                                 }
2110                         }
2111                 }
2112                 
2113                 bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, TypeData memType, bool isValueList)
2114                 {
2115                         if (isValueList) return !memType.HasPublicConstructor;
2116                         else return member.IsReadOnly (map.TypeData.Type) || !memType.HasPublicConstructor;
2117                 }
2118
2119                 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
2120                 {
2121                         GenerateSetMemberValue (member, ob, value, isValueList, false);
2122                 }
2123                 
2124                 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList, bool initializingMember)
2125                 {
2126                         if (isValueList) {
2127                                 WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
2128                                 if (member.IsOptionalValueType) {
2129                                         string val = initializingMember ? "false" : "true";
2130                                         WriteLine (ob + "[" + member.SpecifiedGlobalIndex + "] = " + val + ";");
2131                                 }
2132                         }
2133                         else {
2134                                 WriteLine (ob + ".@" + member.Name + " = " + value + ";");
2135                                 if (member.IsOptionalValueType) {
2136                                         string val = initializingMember ? "false" : "true";
2137                                         WriteLine (ob + "." + member.Name + "Specified = " + val + ";");
2138                                 }
2139                         }
2140                 }
2141
2142                 void GenerateSetMemberValueFromAttr (XmlTypeMapMember member, string ob, string value, bool isValueList)
2143                 {
2144                         // Enumeration values specified in custom attributes are stored as integer
2145                         // values if the custom attribute property is of type object. So, it is
2146                         // necessary to convert to the enum type before asigning the value to the field.
2147                         
2148                         if (member.TypeData.Type.IsEnum)
2149                                 value = GetCast (member.TypeData.Type, value);
2150                         GenerateSetMemberValue (member, ob, value, isValueList, true);
2151                 }
2152
2153                 string GenerateReadObjectElement (XmlTypeMapElementInfo elem)
2154                 {
2155                         switch (elem.TypeData.SchemaType)
2156                         {
2157                                 case SchemaTypes.XmlNode:
2158                                         return GetReadXmlNode (elem.TypeData, true);
2159
2160                                 case SchemaTypes.Primitive:
2161                                 case SchemaTypes.Enum:
2162                                         return GenerateReadPrimitiveValue (elem);
2163
2164                                 case SchemaTypes.Array:
2165                                         return GenerateReadListElement (elem.MappedType, null, GetLiteral(elem.IsNullable), true);
2166
2167                                 case SchemaTypes.Class:
2168                                         return GetReadObjectCall (elem.MappedType, GetLiteral(elem.IsNullable), "true");
2169
2170                                 case SchemaTypes.XmlSerializable:
2171                                         return GetCast (elem.TypeData, String.Format ("({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true))", elem.TypeData.CSharpFullName));
2172
2173                                 default:
2174                                         throw new NotSupportedException ("Invalid value type");
2175                         }
2176                 }
2177
2178                 string GenerateReadPrimitiveValue (XmlTypeMapElementInfo elem)
2179                 {
2180                         if (elem.TypeData.Type == typeof (XmlQualifiedName)) {
2181                                 if (elem.IsNullable) return "ReadNullableQualifiedName ()";
2182                                 else return "ReadElementQualifiedName ()";
2183                         }
2184                         else if (elem.IsNullable) {
2185                                 string str = GetStrTempVar ();
2186                                 WriteLine ("string " + str + " = ReadNullableString ();");
2187                                 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, true);
2188                         }
2189                         else {
2190                                 string str = GetStrTempVar ();
2191                                 WriteLine ("string " + str + " = Reader.ReadElementString ();");
2192                                 return GenerateGetValueFromXmlString (str, elem.TypeData, elem.MappedType, false);
2193                         }
2194                 }
2195                 
2196                 string GenerateGetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap, bool isNullable)
2197                 {
2198                         if (typeData.SchemaType == SchemaTypes.Array)
2199                                 return GenerateReadListString (typeMap, value);
2200                         else if (typeData.SchemaType == SchemaTypes.Enum)
2201                                 return GenerateGetEnumValue (typeMap, value, isNullable);
2202                         else if (typeData.Type == typeof (XmlQualifiedName))
2203                                 return "ToXmlQualifiedName (" + value + ")";
2204                         else 
2205                                 return XmlCustomFormatter.GenerateFromXmlString (typeData, value);
2206                 }
2207                 
2208                 string GenerateReadListElement (XmlTypeMapping typeMap, string list, string isNullable, bool canCreateInstance)
2209                 {
2210                         Type listType = typeMap.TypeData.Type;
2211                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2212                         bool doNullCheck = typeMap.TypeData.Type.IsArray;
2213
2214                         if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) 
2215                         {
2216                                 if (list == null) {
2217                                         list = GetObTempVar ();
2218                                         WriteLine (typeMap.TypeData.CSharpFullName + " " + list + " = null;");
2219                                         if (doNullCheck)
2220                                                 WriteLineInd ("if (!ReadNull()) {");
2221                                         WriteLine (list + " = " + GenerateCreateList (listType) + ";");
2222                                 } else {
2223                                         if (doNullCheck)
2224                                                 WriteLineInd ("if (!ReadNull()) {");
2225                                 }
2226                         }
2227                         else
2228                         {
2229                                 if (list != null) {
2230                                         WriteLineInd ("if (((object)" + list + ") == null)");
2231                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2232                                         Unindent ();
2233                                         doNullCheck = false;
2234                                 }
2235                                 else {
2236                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2237                                         return list;
2238                                 }
2239                         }
2240                                 
2241                         WriteLineInd ("if (Reader.IsEmptyElement) {");
2242                         WriteLine ("Reader.Skip();");
2243                         if (listType.IsArray)
2244                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", 0, " + GetTypeOf(listType.GetElementType()) + ", false);");
2245
2246                         Unindent ();
2247                         WriteLineInd ("} else {");
2248
2249                         string index = GetNumTempVar ();
2250                         WriteLine ("int " + index + " = 0;");
2251                         WriteLine ("Reader.ReadStartElement();");
2252                         WriteLine ("Reader.MoveToContent();");
2253                         WriteLine ("");
2254
2255                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
2256                         WriteLineInd ("{");
2257                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
2258                         WriteLineInd ("{");
2259
2260                         bool first = true;
2261                         foreach (XmlTypeMapElementInfo elemInfo in listMap.ItemInfo)
2262                         {
2263                                 WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (elemInfo.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (elemInfo.Namespace) + ") {");
2264                                 GenerateAddListValue (typeMap.TypeData, list, index, GenerateReadObjectElement (elemInfo), false);
2265                                 WriteLine (index + "++;");
2266                                 WriteLineUni ("}");
2267                                 first = false;
2268                         }
2269                         if (!first) WriteLine ("else UnknownNode (null);");
2270                         else WriteLine ("UnknownNode (null);");
2271                         
2272                         WriteLineUni ("}");
2273                         WriteLine ("else UnknownNode (null);");
2274                         WriteLine ("");
2275                         WriteLine ("Reader.MoveToContent();");
2276                         WriteLineUni ("}");
2277                         
2278                         WriteLine ("ReadEndElement();");
2279
2280                         if (listType.IsArray)
2281                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + index + ", " + GetTypeOf(listType.GetElementType()) + ", false);");
2282
2283                         WriteLineUni ("}");
2284                         if (doNullCheck)
2285                                 WriteLineUni ("}");
2286
2287                         return list;
2288                 }
2289
2290                 string GenerateReadListString (XmlTypeMapping typeMap, string values)
2291                 {
2292                         Type listType = typeMap.TypeData.Type;
2293                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2294                         string itemType = ToCSharpFullName (listType.GetElementType());
2295                         
2296                         string list = GetObTempVar ();
2297                         WriteLine (itemType + "[] " + list + ";");
2298                         
2299                         string var = GetStrTempVar ();
2300                         WriteLine ("string " + var + " = " + values + ".Trim();");
2301                         WriteLineInd ("if (" + var + " != string.Empty) {");
2302                         
2303                         string valueArray = GetObTempVar ();
2304                         WriteLine ("string[] " + valueArray + " = " + var + ".Split (' ');");
2305                         
2306                         WriteLine (list + " = new " + GetArrayDeclaration (listType, valueArray + ".Length") + ";");
2307                         
2308                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)listMap.ItemInfo[0];
2309
2310                         string index = GetNumTempVar ();
2311                         WriteLineInd ("for (int " + index + " = 0; " + index + " < " + valueArray + ".Length; " + index + "++)");
2312                         WriteLine (list + "[" + index + "] = " + GenerateGetValueFromXmlString (valueArray + "[" + index + "]", info.TypeData, info.MappedType, info.IsNullable) + ";");
2313                         Unindent ();
2314                         WriteLineUni ("}");
2315                         WriteLine ("else");
2316                         WriteLine ("\t" + list + " = new " + GetArrayDeclaration (listType, "0") + ";");
2317                         
2318                         return list;
2319                 }
2320                 
2321                 string GetArrayDeclaration (Type type, string length)
2322                 {
2323                         Type t = type.GetElementType();
2324                         System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2325                         sb.Append ('[').Append (length).Append (']');
2326                         while (t.IsArray) {
2327                                 sb.Append ("[]");
2328                                 t = t.GetElementType();
2329                         }
2330                         sb.Insert (0, ToCSharpFullName (t));
2331                         return sb.ToString ();
2332                 }
2333
2334                 void GenerateAddListValue (TypeData listType, string list, string index, string value, bool canCreateInstance)
2335                 {
2336                         Type type = listType.Type;
2337                         if (type.IsArray)
2338                         {
2339                                 WriteLine (list + " = (" + ToCSharpFullName (type) + ") EnsureArrayIndex (" + list + ", " + index + ", " + GetTypeOf(type.GetElementType()) + ");");
2340                                 WriteLine (list + "[" + index + "] = " + value + ";");
2341                         }
2342                         else    // Must be IEnumerable
2343                         {
2344                                 WriteLine ("if (((object)" + list + ") == null)");
2345                                 if (canCreateInstance) 
2346                                         WriteLine ("\t" + list + String.Format (" = ({0}) Activator.CreateInstance(typeof({0}), true);", listType.CSharpFullName));
2347                                 else 
2348                                         WriteLine ("\tthrow CreateReadOnlyCollectionException (" + GetLiteral (listType.CSharpFullName) + ");");
2349                                 
2350                                 WriteLine (list + ".Add (" + value + ");");
2351                         }
2352                 }
2353
2354                 string GenerateCreateList (Type listType)
2355                 {
2356                         if (listType.IsArray)
2357                                 return "(" + ToCSharpFullName (listType) + ") EnsureArrayIndex (null, 0, " + GetTypeOf(listType.GetElementType()) + ")";
2358                         else
2359                                 return "new " + ToCSharpFullName (listType) + "()";
2360                 }
2361                 
2362                 string GenerateInitializeList (TypeData listType)
2363                 {
2364                         if (listType.Type.IsArray)
2365                                 return "null";
2366                         else
2367                                 return "new " + listType.CSharpFullName + "()";
2368                 }
2369                 
2370                 void GenerateFillerCallbacks ()
2371                 {
2372                         foreach (TypeData td in _listsToFill)
2373                         {
2374                                 string metName = GetFillListName (td);
2375                                 WriteLine ("void " + metName + " (object list, object source)");
2376                                 WriteLineInd ("{");
2377                                 WriteLine ("if (((object)list) == null) throw CreateReadOnlyCollectionException (" + GetLiteral (td.CSharpFullName) + ");");
2378                                 WriteLine ("");
2379
2380                                 WriteLine (td.CSharpFullName + " dest = (" + td.CSharpFullName + ") list;");
2381                                 WriteLine ("foreach (object ob in (IEnumerable)source)");
2382                                 WriteLine ("\tdest.Add (" + GetCast (td.ListItemTypeData, "ob") + ");");
2383                                 WriteLineUni ("}");
2384                                 WriteLine ("");
2385                         }
2386                 }
2387
2388                 void GenerateReadXmlNodeElement (XmlTypeMapping typeMap, string isNullable)
2389                 {
2390                         WriteLine ("return " + GetReadXmlNode (typeMap.TypeData, false) + ";");
2391                 }
2392
2393                 void GenerateReadPrimitiveElement (XmlTypeMapping typeMap, string isNullable)
2394                 {
2395                         WriteLine ("XmlQualifiedName t = GetXsiType();");
2396                         WriteLine ("if (t == null) t = new XmlQualifiedName (" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.Namespace) + ");");
2397                         WriteLine ("return " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
2398                 }
2399
2400                 void GenerateReadEnumElement (XmlTypeMapping typeMap, string isNullable)
2401                 {
2402                         WriteLine ("Reader.ReadStartElement ();");
2403                         WriteLine (typeMap.TypeData.CSharpFullName + " res = " + GenerateGetEnumValue (typeMap, "Reader.ReadString()", false) + ";");
2404                         WriteLineInd ("if (Reader.NodeType != XmlNodeType.None)");
2405                         WriteLineUni ("Reader.ReadEndElement ();");
2406                         WriteLine ("return res;");
2407                 }
2408
2409                 string GenerateGetEnumValue (XmlTypeMapping typeMap, string val, bool isNullable)
2410                 {
2411                         if (isNullable)
2412                                 return "(" + val + ") != null ? " + GetGetEnumValueName (typeMap) + " (" + val + ") : (" + typeMap.TypeData.CSharpFullName + "?) null";
2413                         else
2414                                 return GetGetEnumValueName (typeMap) + " (" + val + ")";
2415                 }
2416                 
2417                 void GenerateGetEnumValueMethod (XmlTypeMapping typeMap)
2418                 {
2419                         string metName = GetGetEnumValueName (typeMap);
2420                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2421
2422                         if (map.IsFlags)
2423                         {
2424                                 string switchMethod =  metName + "_Switch";
2425                                 WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2426                                 WriteLineInd ("{");
2427                                 WriteLine ("xmlName = xmlName.Trim();");
2428                                 WriteLine ("if (xmlName.Length == 0) return (" + typeMap.TypeData.CSharpFullName + ")0;");
2429                                 WriteLine (typeMap.TypeData.CSharpFullName + " sb = (" + typeMap.TypeData.CSharpFullName + ")0;");
2430                                 WriteLine ("string[] enumNames = xmlName.Split (null);");
2431                                 WriteLine ("foreach (string name in enumNames)");
2432                                 WriteLineInd ("{");
2433                                 WriteLine ("if (name == string.Empty) continue;");
2434                                 WriteLine ("sb |= " + switchMethod + " (name); ");
2435                                 WriteLineUni ("}");
2436                                 WriteLine ("return sb;");
2437                                 WriteLineUni ("}");
2438                                 WriteLine ("");
2439                                 metName = switchMethod;
2440                         }
2441
2442                         WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2443                         WriteLineInd ("{");
2444                         GenerateGetSingleEnumValue (typeMap, "xmlName");
2445                         WriteLineUni ("}");
2446                         WriteLine ("");
2447                 }
2448                 
2449                 void GenerateGetSingleEnumValue (XmlTypeMapping typeMap, string val)
2450                 {
2451                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2452                         WriteLine ("switch (" + val + ")");
2453                         WriteLineInd ("{");
2454                         foreach (EnumMap.EnumMapMember mem in map.Members)
2455                         {
2456                                 WriteLine ("case " + GetLiteral (mem.XmlName) + ": return " + typeMap.TypeData.CSharpFullName + ".@" + mem.EnumName + ";");
2457                         }
2458                         WriteLineInd ("default:");
2459                         WriteLine ("throw CreateUnknownConstantException (" + val + ", typeof(" + typeMap.TypeData.CSharpFullName + "));");
2460                         Unindent ();
2461                         WriteLineUni ("}");
2462                 }
2463                 
2464                 void GenerateReadXmlSerializableElement (XmlTypeMapping typeMap, string isNullable)
2465                 {
2466                         WriteLine ("Reader.MoveToContent ();");
2467                         WriteLine ("if (Reader.NodeType == XmlNodeType.Element)");
2468                         WriteLineInd ("{");
2469                         WriteLine ("if (Reader.LocalName == " + GetLiteral (typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
2470                         WriteLine (String.Format ("\treturn ({0}) ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true));", typeMap.TypeData.CSharpFullName));
2471                         WriteLine ("else");
2472                         WriteLine ("\tthrow CreateUnknownNodeException ();");
2473                         WriteLineUni ("}");
2474                         WriteLine ("else UnknownNode (null);");
2475                         WriteLine ("");
2476                         WriteLine ("return default (" + typeMap.TypeData.CSharpFullName + ");");
2477                 }
2478
2479                 void GenerateReadInitCallbacks ()
2480                 {
2481                         WriteLine ("protected override void InitCallbacks ()");
2482                         WriteLineInd ("{");
2483
2484                         if (_format == SerializationFormat.Encoded)
2485                         {
2486                                 foreach (XmlMapping xmap in _mapsToGenerate)  
2487                                 {
2488                                         XmlTypeMapping map = xmap as XmlTypeMapping;
2489                                         if (map == null) continue;
2490                                         if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
2491                                                 WriteMetCall ("AddReadCallback", GetLiteral (map.XmlType), GetLiteral(map.Namespace), GetTypeOf(map.TypeData.Type), "new XmlSerializationReadCallback (" + GetReadObjectName (map) + ")");
2492                                 }
2493                         }
2494                         
2495                         WriteLineUni ("}");
2496                         WriteLine ("");
2497
2498                         WriteLine ("protected override void InitIDs ()");
2499                         WriteLine ("{");
2500                         WriteLine ("}");
2501                         WriteLine ("");
2502                 }
2503
2504                 void GenerateFixupCallbacks ()
2505                 {
2506                         foreach (XmlMapping map in _fixupCallbacks)
2507                         {
2508                                 bool isList = map is XmlMembersMapping;
2509                                 string tname = !isList ? ((XmlTypeMapping)map).TypeData.CSharpFullName : "object[]";
2510                                 WriteLine ("void " + GetFixupCallbackName (map) + " (object obfixup)");
2511                                 WriteLineInd ("{");                                     
2512                                 WriteLine ("Fixup fixup = (Fixup)obfixup;");
2513                                 WriteLine (tname + " source = (" + tname + ") fixup.Source;");
2514                                 WriteLine ("string[] ids = fixup.Ids;");
2515                                 WriteLine ("");
2516
2517                                 ClassMap cmap = (ClassMap)map.ObjectMap;
2518                                 ICollection members = cmap.ElementMembers;
2519                                 if (members != null) {
2520                                         foreach (XmlTypeMapMember member in members)
2521                                         {
2522                                                 WriteLineInd ("if (ids[" + member.Index + "] != null)");
2523                                                 string val = "GetTarget(ids[" + member.Index + "])";
2524                                                 if (!isList) val = GetCast (member.TypeData, val);
2525                                                 GenerateSetMemberValue (member, "source", val, isList);
2526                                                 Unindent ();
2527                                         }
2528                                 }
2529                                 WriteLineUni ("}");
2530                                 WriteLine ("");
2531                         }
2532                 }
2533
2534                 string GetReadXmlNode (TypeData type, bool wrapped)
2535                 {
2536                         if (type.Type == typeof (XmlDocument))
2537                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlDocument)), "ReadXmlDocument (" + GetLiteral(wrapped) + ")");
2538                         else
2539                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlNode)), "ReadXmlNode (" + GetLiteral(wrapped) + ")");
2540                 }
2541                 
2542                 #endregion
2543                 
2544                 #region Helper methods
2545
2546                 //*******************************************************
2547                 // Helper methods
2548                 //
2549                 
2550                 ArrayList _listsToFill = new ArrayList ();
2551                 Hashtable _hookVariables;
2552                 Stack _hookContexts;
2553                 Stack _hookOpenHooks;
2554                 
2555                 class HookInfo {
2556                         public HookType HookType;
2557                         public Type Type;
2558                         public string Member;
2559                         public HookDir Direction;
2560                 }
2561
2562                 void InitHooks ()
2563                 {
2564                         _hookContexts = new Stack ();
2565                         _hookOpenHooks = new Stack ();
2566                         _hookVariables = new Hashtable ();
2567                 }
2568                 
2569                 void PushHookContext ()
2570                 {
2571                         _hookContexts.Push (_hookVariables);
2572                         _hookVariables = (Hashtable) _hookVariables.Clone ();
2573                 }
2574                 
2575                 void PopHookContext ()
2576                 {
2577                         _hookVariables = (Hashtable) _hookContexts.Pop ();
2578                 }
2579                 
2580                 void SetHookVar (string var, string value)
2581                 {
2582                         _hookVariables [var] = value;
2583                 }
2584
2585                 bool GenerateReadHook (HookType hookType, Type type)
2586                 {
2587                         return GenerateHook (hookType, HookDir.Read, type, null);
2588                 }
2589
2590                 bool GenerateWriteHook (HookType hookType, Type type)
2591                 {
2592                         return GenerateHook (hookType, HookDir.Write, type, null);
2593                 }
2594                 
2595                 bool GenerateWriteMemberHook (Type type, XmlTypeMapMember member)
2596                 {
2597                         SetHookVar ("$MEMBER", member.Name);
2598                         return GenerateHook (HookType.member, HookDir.Write, type, member.Name);
2599                 }
2600                 
2601                 bool GenerateReadMemberHook (Type type, XmlTypeMapMember member)
2602                 {
2603                         SetHookVar ("$MEMBER", member.Name);
2604                         return GenerateHook (HookType.member, HookDir.Read, type, member.Name);
2605                 }
2606                 
2607                 bool GenerateReadArrayMemberHook (Type type, XmlTypeMapMember member, string index)
2608                 {
2609                         SetHookVar ("$INDEX", index);
2610                         return GenerateReadMemberHook (type, member);
2611                 }
2612         
2613                 bool MemberHasReadReplaceHook (Type type, XmlTypeMapMember member)
2614                 {
2615                         if (_config == null) return false;
2616                         return _config.GetHooks (HookType.member, HookDir.Read, HookAction.Replace, type, member.Name).Count > 0;
2617                 }
2618                 
2619                 bool GenerateHook (HookType hookType, HookDir dir, Type type, string member)
2620                 {
2621                         GenerateHooks (hookType, dir, type, null, HookAction.InsertBefore);
2622                         if (GenerateHooks (hookType, dir, type, null, HookAction.Replace))
2623                         {
2624                                 GenerateHooks (hookType, dir, type, null, HookAction.InsertAfter);
2625                                 return true;
2626                         }
2627                         else
2628                         {
2629                                 HookInfo hi = new HookInfo ();
2630                                 hi.HookType = hookType;
2631                                 hi.Type = type;
2632                                 hi.Member = member;
2633                                 hi.Direction = dir;
2634                                 _hookOpenHooks.Push (hi);
2635                                 return false;
2636                         }
2637                 }
2638                 
2639                 void GenerateEndHook ()
2640                 {
2641                         HookInfo hi = (HookInfo) _hookOpenHooks.Pop();
2642                         GenerateHooks (hi.HookType, hi.Direction, hi.Type, hi.Member, HookAction.InsertAfter);
2643                 }
2644                 
2645                 bool GenerateHooks (HookType hookType, HookDir dir, Type type, string member, HookAction action)
2646                 {
2647                         if (_config == null) return false;
2648                         ArrayList hooks = _config.GetHooks (hookType, dir, action, type, null);
2649                         if (hooks.Count == 0) return false;                     
2650                         foreach (Hook hook in hooks)
2651                         {
2652                                 string code = hook.GetCode (action);
2653                                 foreach (DictionaryEntry de in _hookVariables)
2654                                         code = code.Replace ((string)de.Key, (string)de.Value);
2655                                 WriteMultilineCode (code);
2656                         }
2657                         return true;
2658                 }
2659                 
2660                 string GetRootTypeName ()
2661                 {
2662                         if (_typeMap is XmlTypeMapping) return ((XmlTypeMapping)_typeMap).TypeData.CSharpFullName;
2663                         else return "object[]";
2664                 }
2665
2666                 string GetNumTempVar ()
2667                 {
2668                         return "n" + (_tempVarId++);
2669                 }
2670                 
2671                 string GetObTempVar ()
2672                 {
2673                         return "o" + (_tempVarId++);
2674                 }
2675                 
2676                 string GetStrTempVar ()
2677                 {
2678                         return "s" + (_tempVarId++);
2679                 }
2680                 
2681                 string GetBoolTempVar ()
2682                 {
2683                         return "b" + (_tempVarId++);
2684                 }
2685                 
2686                 string GetUniqueName (string uniqueGroup, object ob, string name)
2687                 {
2688                         name = CodeIdentifier.MakeValid (name.Replace ("[]","_array"));
2689                         Hashtable names = (Hashtable) _uniqueNames [uniqueGroup];
2690                         if (names == null) {
2691                                 names = new Hashtable ();
2692                                 _uniqueNames [uniqueGroup] = names; 
2693                         }
2694                         
2695                         string res = (string) names [ob];
2696                         if (res != null) return res;
2697
2698                         foreach (string n in names.Values)
2699                                 if (n == name) return GetUniqueName (uniqueGroup, ob, name + (_methodId++));
2700                                 
2701                         names [ob] = name;
2702                         return name;
2703                 }
2704                 
2705                 void RegisterReferencingMap (XmlTypeMapping typeMap)
2706                 {
2707                         if (typeMap != null && !_mapsToGenerate.Contains (typeMap))
2708                                 _mapsToGenerate.Add (typeMap);
2709                 }
2710                 
2711                 string GetWriteObjectName (XmlTypeMapping typeMap)
2712                 {
2713                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2714                         return GetUniqueName ("rw", typeMap, "WriteObject_" + typeMap.XmlType);
2715                 }
2716                 
2717                 string GetReadObjectName (XmlTypeMapping typeMap)
2718                 {
2719                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2720                         return GetUniqueName ("rr", typeMap, "ReadObject_" + typeMap.XmlType);
2721                 }
2722                 
2723                 string GetGetEnumValueName (XmlTypeMapping typeMap)
2724                 {
2725                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2726                         return GetUniqueName ("ge", typeMap, "GetEnumValue_" + typeMap.XmlType);
2727                 }
2728
2729                 string GetWriteObjectCallbackName (XmlTypeMapping typeMap)
2730                 {
2731                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2732                         return GetUniqueName ("wc", typeMap, "WriteCallback_" + typeMap.XmlType);
2733                 }
2734                 
2735                 string GetFixupCallbackName (XmlMapping typeMap)
2736                 {
2737                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2738                         
2739                         if (typeMap is XmlTypeMapping)
2740                                 return GetUniqueName ("fc", typeMap, "FixupCallback_" + ((XmlTypeMapping)typeMap).XmlType);
2741                         else
2742                                 return GetUniqueName ("fc", typeMap, "FixupCallback__Message");
2743                 }
2744                 
2745                 string GetUniqueClassName (string s)
2746                 {
2747                         return classNames.AddUnique (CodeIdentifier.MakeValid (s), null);
2748                 }
2749                 
2750                 string GetReadObjectCall (XmlTypeMapping typeMap, string isNullable, string checkType)
2751                 {
2752                         if (_format == SerializationFormat.Literal)
2753                                 return GetReadObjectName (typeMap) + " (" + isNullable + ", " + checkType + ")";
2754                         else
2755                                 return GetCast (typeMap.TypeData, GetReadObjectName (typeMap) + " ()");
2756                 }
2757                 
2758                 string GetFillListName (TypeData td)
2759                 {
2760                         if (!_listsToFill.Contains (td)) _listsToFill.Add (td);
2761                         return GetUniqueName ("fl", td, "Fill_" + CodeIdentifier.MakeValid (td.CSharpName));
2762                 }
2763                 
2764                 string GetCast (TypeData td, TypeData tdval, string val)
2765                 {
2766                         if (td.CSharpFullName == tdval.CSharpFullName) return val;
2767                         else return GetCast (td, val);
2768                 }
2769
2770                 string GetCast (TypeData td, string val)
2771                 {
2772                         if (td.IsNullable && td.IsValueType)
2773                                 return "((" + td.CSharpFullName + "?) " + val + ")";
2774                         else
2775                                 return "((" + td.CSharpFullName + ") " + val + ")";
2776                 }
2777
2778                 string GetCast (Type td, string val)
2779                 {
2780                         return "((" + ToCSharpFullName (td) + ") " + val + ")";
2781                 }
2782
2783                 string GetTypeOf (TypeData td)
2784                 {
2785                         return "typeof(" + td.CSharpFullName + ")";
2786                 }
2787                 
2788                 string GetTypeOf (Type td)
2789                 {
2790                         return "typeof(" + ToCSharpFullName (td) + ")";
2791                 }
2792                 
2793                 string GetLiteral (object ob)
2794                 {
2795                         if (ob == null) return "null";
2796                         if (ob is string) return "\"" + ob.ToString().Replace("\"","\"\"") + "\"";
2797                         if (ob is char) return (char) ob == '\'' ? "'\\''" : "'" + ob.ToString () + "'";
2798                         if (ob is DateTime) return "new DateTime (" + ((DateTime) ob).Ticks + ")";
2799 #if NET_2_0
2800                         if (ob is DateTimeOffset) return "new DateTimeOffset (" + ((DateTimeOffset) ob).Ticks + ")";
2801 #endif
2802                         if (ob is TimeSpan) return "new TimeSpan (" + ((TimeSpan) ob).Ticks + ")";
2803                         if (ob is bool) return ((bool)ob) ? "true" : "false";
2804                         if (ob is XmlQualifiedName) {
2805                                 XmlQualifiedName qn = (XmlQualifiedName)ob;
2806                                 return "new XmlQualifiedName (" + GetLiteral(qn.Name) + "," + GetLiteral(qn.Namespace) + ")";
2807                         }
2808                         if (ob is Enum) {
2809                                 string typeName = ToCSharpFullName (ob.GetType ());
2810                                 StringBuilder sb = new StringBuilder ();
2811                                 string namedValue = Enum.Format (ob.GetType (), ob, "g");
2812                                 string[] names = namedValue.Split (',');
2813                                 foreach (string name in names) {
2814                                         // individual named constants can be seperated by a comma
2815                                         // combined with some additional whitespace characters
2816                                         string cleanName = name.Trim ();
2817                                         if (cleanName.Length == 0)
2818                                                 continue;
2819
2820                                         if (sb.Length > 0)
2821                                                 sb.Append (" | ");
2822
2823                                         sb.Append (typeName);
2824                                         sb.Append ('.');
2825                                         sb.Append (cleanName);
2826                                 }
2827                                 return sb.ToString ();
2828                         }
2829
2830                         return (ob is IFormattable) ? ((IFormattable) ob).ToString (null, CultureInfo.InvariantCulture) : ob.ToString ();
2831                 }
2832                 
2833                 void WriteLineInd (string code)
2834                 {
2835                         WriteLine (code);
2836                         _indent++;
2837                 }
2838                 
2839                 void WriteLineUni (string code)
2840                 {
2841                         if (_indent > 0) _indent--;
2842                         WriteLine (code);
2843                 }
2844
2845                 void Write (string code)
2846                 {
2847                         if (code.Length > 0) 
2848                                 _writer.Write (new String ('\t', _indent));
2849                         _writer.Write (code);
2850                 }
2851
2852                 void WriteUni (string code)
2853                 {
2854                         if (_indent > 0) _indent--;
2855                         _writer.Write (code);
2856                         _writer.WriteLine (string.Empty);
2857                 }
2858
2859                 void WriteLine (string code)
2860                 {
2861                         if (code.Length > 0)
2862                                 _writer.Write (new String ('\t',_indent));
2863                         _writer.WriteLine (code);
2864                 }
2865                 
2866                 void WriteMultilineCode (string code)
2867                 {
2868                         string tabs = new string ('\t',_indent);
2869                         code = code.Replace ("\r","");
2870                         code = code.Replace ("\t","");
2871                         while (code.StartsWith ("\n")) code = code.Substring (1);
2872                         while (code.EndsWith ("\n")) code = code.Substring (0, code.Length - 1);
2873                         code = code.Replace ("\n", "\n" + tabs);
2874                         WriteLine (code);
2875                 }
2876                 
2877                 string Params (params string[] pars)
2878                 {
2879                         string res = "";
2880                         foreach (string p in pars)
2881                         {
2882                                 if (res != "") res += ", ";
2883                                 res += p;
2884                         }
2885                         return res;
2886                 }
2887                 
2888                 void WriteMetCall (string method, params string[] pars)
2889                 {
2890                         WriteLine (method + " (" + Params (pars) + ");");
2891                 }
2892                 
2893                 void Unindent ()
2894                 {
2895                         _indent--;
2896                 }
2897
2898                 #endregion
2899
2900         }
2901         
2902         internal class GenerationResult
2903         {
2904                 public XmlMapping Mapping;
2905                 public string ReaderClassName;
2906                 public string ReadMethodName;
2907                 public string WriterClassName;
2908                 public string WriteMethodName;
2909                 public string Namespace;
2910 #if NET_2_0             
2911                 public string SerializerClassName;
2912 #endif          
2913                 public string BaseSerializerClassName;
2914                 public string ImplementationClassName;
2915         }
2916         
2917 }