2007-04-20 Atsushi Enomoto <atsushi@ximian.com>
[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);
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                                                                 GenerateWriteMemberElement ((XmlTypeMapElementInfo)member.ElementInfo[0], memberValue);
847                                                         }
848                                                         else if (member.ChoiceMember != null)
849                                                         {
850                                                                 string choiceValue = ob + ".@" + member.ChoiceMember;
851                                                                 foreach (XmlTypeMapElementInfo elem in member.ElementInfo) {
852                                                                         WriteLineInd ("if (" + choiceValue + " == " + GetLiteral(elem.ChoiceValue) + ") {");
853                                                                         GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
854                                                                         WriteLineUni ("}");
855                                                                 }
856                                                         }
857                                                         else
858                                                         {
859         //                                                      WriteLineInd ("if (" + memberValue + " == null) {");
860         //                                                      GenerateWriteMemberElement ((XmlTypeMapElementInfo)member.ElementInfo[0], memberValue);
861         //                                                      WriteLineUni ("}");
862                                                                         
863                                                                 bool first = true;
864                                                                 foreach (XmlTypeMapElementInfo elem in member.ElementInfo)
865                                                                 {
866                                                                         WriteLineInd ((first?"":"else ") + "if (" + memberValue + " is " + elem.TypeData.CSharpFullName + ") {");
867                                                                         GenerateWriteMemberElement (elem, GetCast(elem.TypeData, member.TypeData, memberValue));
868                                                                         WriteLineUni ("}");
869                                                                         first = false;
870                                                                 }
871                                                         }
872                                                 }
873                                                 else
874                                                         throw new InvalidOperationException ("Unknown member type");
875                                                         
876                                                 if (cond != null)
877                                                         WriteLineUni ("}");
878                                                         
879                                                 GenerateEndHook ();
880                                         }
881                                 }
882                                 GenerateEndHook ();
883                         }
884                 }
885                 
886                 void GenerateWriteMemberElement (XmlTypeMapElementInfo elem, string memberValue)
887                 {
888                         switch (elem.TypeData.SchemaType)
889                         {
890                                 case SchemaTypes.XmlNode:
891                                         string elemName = elem.WrappedElement ? elem.ElementName : "";
892                                         if (_format == SerializationFormat.Literal) 
893                                                 WriteMetCall ("WriteElementLiteral", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
894                                         else 
895                                                 WriteMetCall ("WriteElementEncoded", memberValue, GetLiteral(elemName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false");
896                                         break;
897
898                                 case SchemaTypes.Enum:
899                                 case SchemaTypes.Primitive:
900                                         if (_format == SerializationFormat.Literal) 
901                                                 GenerateWritePrimitiveValueLiteral (memberValue, elem.ElementName, elem.Namespace, elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
902                                         else
903                                                 GenerateWritePrimitiveValueEncoded (memberValue, elem.ElementName, elem.Namespace, new XmlQualifiedName (elem.TypeData.XmlType, elem.DataTypeNamespace), elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
904                                         break;
905
906                                 case SchemaTypes.Array:
907                                         WriteLineInd ("if (" + memberValue + " != null) {");
908                                         
909                                         if (elem.MappedType.MultiReferenceType) {
910                                                 WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
911                                                 RegisterReferencingMap (elem.MappedType);
912                                         }
913                                         else {
914                                                 WriteMetCall ("WriteStartElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue);
915                                                 GenerateWriteListContent (null, elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue, false);
916                                                 WriteMetCall ("WriteEndElement", memberValue);
917                                         }
918                                         WriteLineUni ("}");
919                                         
920                                         if (elem.IsNullable) {
921                                                 WriteLineInd ("else");
922                                                 if (_format == SerializationFormat.Literal) 
923                                                         WriteMetCall ("WriteNullTagLiteral", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
924                                                 else
925                                                         WriteMetCall ("WriteNullTagEncoded", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace));
926                                                 Unindent ();
927                                         }
928                                         
929                                         break;
930
931                                 case SchemaTypes.Class:
932                                         if (elem.MappedType.MultiReferenceType) {
933                                                 RegisterReferencingMap (elem.MappedType);
934                                                 if (elem.MappedType.TypeData.Type == typeof(object))
935                                                         WriteMetCall ("WritePotentiallyReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, "null", "false", GetLiteral(elem.IsNullable));
936                                                 else
937                                                         WriteMetCall ("WriteReferencingElement", GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), memberValue, GetLiteral(elem.IsNullable));
938                                         }
939                                         else 
940                                                 WriteMetCall (GetWriteObjectName(elem.MappedType), memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable), "false", "true");
941                                         break;
942
943                                 case SchemaTypes.XmlSerializable:
944                                         WriteMetCall ("WriteSerializable", memberValue, GetLiteral(elem.ElementName), GetLiteral(elem.Namespace), GetLiteral(elem.IsNullable));
945                                         break;
946
947                                 default:
948                                         throw new NotSupportedException ("Invalid value type");
949                         }
950                 }               
951
952                 void GenerateWriteListElement (XmlTypeMapping typeMap, string ob)
953                 {
954                         if (_format == SerializationFormat.Encoded)
955                         {
956                                 string n, ns;
957                                 string itemCount = GenerateGetListCount (typeMap.TypeData, ob);
958                                 GenerateGetArrayType ((ListMap) typeMap.ObjectMap, itemCount, out n, out ns);
959                                 
960                                 string arrayType;
961                                 if (ns != string.Empty)
962                                         arrayType = "FromXmlQualifiedName (new XmlQualifiedName(" + n + "," + ns + "))";
963                                 else
964                                         arrayType = GetLiteral (n);
965                                 
966                                 WriteMetCall ("WriteAttribute", GetLiteral("arrayType"), GetLiteral(XmlSerializer.EncodingNamespace), arrayType);
967                         }
968                         GenerateWriteListContent (null, typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob, false);
969                 }
970                 
971                 void GenerateWriteAnyElementContent (XmlTypeMapMemberAnyElement member, string memberValue)
972                 {
973                         bool singleElement = (member.TypeData.Type == typeof (XmlElement));
974                         string var;
975                         
976                         if (singleElement)
977                                 var = memberValue;
978                         else {
979                                 var = GetObTempVar ();
980                                 WriteLineInd ("foreach (XmlNode " + var + " in " + memberValue + ") {");
981                         }
982                         
983                         string elem = GetObTempVar ();
984                         WriteLine ("XmlNode " + elem + " = " + var + ";");
985                         WriteLine ("if (" + elem + " is XmlElement) {");
986                         
987                         if (!member.IsDefaultAny) {
988                                 for (int n=0; n<member.ElementInfo.Count; n++) {
989                                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)member.ElementInfo[n];
990                                         string txt = "(" + elem + ".LocalName == " + GetLiteral(info.ElementName) + " && " + elem + ".NamespaceURI == " + GetLiteral(info.Namespace) + ")";
991                                         if (n == member.ElementInfo.Count-1) txt += ") {";
992                                         if (n == 0) WriteLineInd ("if (" + txt);
993                                         else WriteLine ("|| " + txt);
994                                 }                               
995                         }
996                         WriteLine ("}");
997                         WriteLine ("else " + elem + ".WriteTo (Writer);");
998
999                         if (_format == SerializationFormat.Literal) 
1000                                 WriteLine ("WriteElementLiteral (" + elem + ", \"\", \"\", false, true);");
1001                         else 
1002                                 WriteLine ("WriteElementEncoded (" + elem + ", \"\", \"\", false, true);");
1003
1004                         if (!member.IsDefaultAny) {
1005                                 WriteLineUni ("}");
1006                                 WriteLineInd ("else");
1007                                 WriteLine ("throw CreateUnknownAnyElementException (" + elem + ".Name, " + elem + ".NamespaceURI);");
1008                                 Unindent ();
1009                         }
1010                         
1011                         if (!singleElement)
1012                                 WriteLineUni ("}");
1013                 }
1014
1015                 void GenerateWritePrimitiveElement (XmlTypeMapping typeMap, string ob)
1016                 {
1017                         string strVal = GenerateGetStringValue (typeMap, typeMap.TypeData, ob);
1018                         WriteLine ("Writer.WriteString (" + strVal + ");");
1019                 }
1020
1021                 void GenerateWriteEnumElement (XmlTypeMapping typeMap, string ob)
1022                 {
1023                         string strVal = GenerateGetEnumXmlValue (typeMap, ob);
1024                         WriteLine ("Writer.WriteString (" + strVal + ");");
1025                 }
1026
1027                 string GenerateGetStringValue (XmlTypeMapping typeMap, TypeData type, string value)
1028                 {
1029                         if (type.SchemaType == SchemaTypes.Array) {
1030                                 string str = GetStrTempVar ();
1031                                 WriteLine ("string " + str + " = null;");
1032                                 WriteLineInd ("if (" + value + " != null) {");
1033                                 string res = GenerateWriteListContent (null, typeMap.TypeData, (ListMap)typeMap.ObjectMap, value, true);
1034                                 WriteLine (str + " = " + res + ".ToString ().Trim ();");
1035                                 WriteLineUni ("}");
1036                                 return str;
1037                         }
1038                         else if (type.SchemaType == SchemaTypes.Enum) {
1039                                 return GenerateGetEnumXmlValue (typeMap, value);
1040                         }
1041                         else if (type.Type == typeof (XmlQualifiedName))
1042                                 return "FromXmlQualifiedName (" + value + ")";
1043                         else if (value == null)
1044                                 return null;
1045                         else
1046                                 return XmlCustomFormatter.GenerateToXmlString (type, value);
1047                 }
1048
1049                 string GenerateGetEnumXmlValue (XmlTypeMapping typeMap, string ob)
1050                 {
1051                         return GetGetEnumValueName (typeMap) + " (" + ob + ")";
1052                 }
1053
1054                 string GenerateGetListCount (TypeData listType, string ob)
1055                 {
1056                         if (listType.Type.IsArray)
1057                                 return "ob.Length";
1058                         else
1059                                 return "ob.Count";
1060                 }
1061
1062                 void GenerateGetArrayType (ListMap map, string itemCount, out string localName, out string ns)
1063                 {
1064                         string arrayDim;
1065                         if (itemCount != "") arrayDim = "";
1066                         else arrayDim = "[]";
1067
1068                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) map.ItemInfo[0];
1069                         if (info.TypeData.SchemaType == SchemaTypes.Array)
1070                         {
1071                                 string nm;
1072                                 GenerateGetArrayType ((ListMap)info.MappedType.ObjectMap, "", out nm, out ns);
1073                                 localName = nm + arrayDim;
1074                         }
1075                         else 
1076                         {
1077                                 if (info.MappedType != null)
1078                                 {
1079                                         localName = info.MappedType.XmlType + arrayDim;
1080                                         ns = info.MappedType.Namespace;
1081                                 }
1082                                 else 
1083                                 {
1084                                         localName = info.TypeData.XmlType + arrayDim;
1085                                         ns = info.DataTypeNamespace;
1086                                 }
1087                         }
1088                         if (itemCount != "") {
1089                                 localName = "\"" + localName + "[\" + " + itemCount + " + \"]\"";
1090                                 ns = GetLiteral (ns);
1091                         }
1092                 }
1093
1094                 string GenerateWriteListContent (string container, TypeData listType, ListMap map, string ob, bool writeToString)
1095                 {
1096                         string targetString = null;
1097                         
1098                         if (writeToString)
1099                         {
1100                                 targetString = GetStrTempVar ();
1101                                 WriteLine ("System.Text.StringBuilder " + targetString + " = new System.Text.StringBuilder();");
1102                         }
1103                         
1104                         if (listType.Type.IsArray)
1105                         {
1106                                 string itemVar = GetNumTempVar ();
1107                                 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Length; "+itemVar+"++) {");
1108                                 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1109                                 WriteLineUni ("}");
1110                         }
1111                         else if (typeof(ICollection).IsAssignableFrom (listType.Type))
1112                         {
1113                                 string itemVar = GetNumTempVar ();
1114                                 WriteLineInd ("for (int "+itemVar+" = 0; "+itemVar+" < " + ob + ".Count; "+itemVar+"++) {");
1115                                 GenerateListLoop (container, map, ob + "["+itemVar+"]", itemVar, listType.ListItemTypeData, targetString);
1116                                 WriteLineUni ("}");
1117                         }
1118                         else if (typeof(IEnumerable).IsAssignableFrom (listType.Type))
1119                         {
1120                                 string itemVar = GetObTempVar ();
1121                                 WriteLineInd ("foreach (" + listType.ListItemTypeData.CSharpFullName + " " + itemVar + " in " + ob + ") {");
1122                                 GenerateListLoop (container, map, itemVar, null, listType.ListItemTypeData, targetString);
1123                                 WriteLineUni ("}");
1124                         }
1125                         else
1126                                 throw new Exception ("Unsupported collection type");
1127
1128                         return targetString;
1129                 }
1130                 
1131                 void GenerateListLoop (string container, ListMap map, string item, string index, TypeData itemTypeData, string targetString)
1132                 {
1133                         bool multichoice = (map.ItemInfo.Count > 1);
1134
1135                         if (map.ChoiceMember != null && container != null && index != null) {
1136                                 WriteLineInd ("if ((" + container + ".@" + map.ChoiceMember + " == null) || (" + index + " >= " + container + ".@" + map.ChoiceMember + ".Length))");
1137                                 WriteLine ("throw CreateInvalidChoiceIdentifierValueException (" + container + ".GetType().ToString(), \"" + map.ChoiceMember + "\");");
1138                                 Unindent ();
1139                         }
1140                         
1141                         if (multichoice)
1142                                 WriteLine ("if (((object)" + item + ") == null) { }");
1143                                 
1144                         foreach (XmlTypeMapElementInfo info in map.ItemInfo)
1145                         {
1146                                 if (map.ChoiceMember != null && multichoice)
1147                                         WriteLineInd ("else if (" + container + ".@" + map.ChoiceMember + "[" + index + "] == " + GetLiteral (info.ChoiceValue) + ") {");
1148                                 else if (multichoice)
1149                                         WriteLineInd ("else if (" + item + ".GetType() == typeof(" + info.TypeData.CSharpFullName + ")) {");
1150                                 
1151                                 if (targetString == null) 
1152                                         GenerateWriteMemberElement (info, GetCast (info.TypeData, itemTypeData, item));
1153                                 else
1154                                 {
1155                                         string strVal = GenerateGetStringValue (info.MappedType, info.TypeData, GetCast (info.TypeData, itemTypeData, item));
1156                                         WriteLine (targetString + ".Append (" + strVal + ").Append (\" \");");
1157                                 }
1158
1159                                 if (multichoice)
1160                                         WriteLineUni ("}");
1161                         }
1162                         
1163                         if (multichoice)
1164                                 WriteLine ("else throw CreateUnknownTypeException (" + item + ");");
1165                 }
1166
1167                 void GenerateWritePrimitiveValueLiteral (string memberValue, string name, string ns, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1168                 {
1169                         if (!wrapped) {
1170                                 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1171                                 WriteMetCall ("WriteValue", strVal);
1172                         }
1173                         else if (isNullable) {
1174                                 if (typeData.Type == typeof(XmlQualifiedName)) 
1175                                         WriteMetCall ("WriteNullableQualifiedNameLiteral", GetLiteral(name), GetLiteral(ns), memberValue);
1176                                 else  {
1177                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1178                                         WriteMetCall ("WriteNullableStringLiteral", GetLiteral(name), GetLiteral(ns), strVal);
1179                                 }
1180                         }
1181                         else {
1182                                 if (typeData.Type == typeof(XmlQualifiedName))
1183                                         WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue);
1184                                 else {
1185                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1186                                         WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal);
1187                                 }
1188                         }
1189                 }
1190                 
1191                 void GenerateWritePrimitiveValueEncoded (string memberValue, string name, string ns, XmlQualifiedName xsiType, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
1192                 {
1193                         if (!wrapped) {
1194                                 string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1195                                 WriteMetCall ("WriteValue", strVal);
1196                         }
1197                         else if (isNullable) {
1198                                 if (typeData.Type == typeof(XmlQualifiedName)) 
1199                                         WriteMetCall ("WriteNullableQualifiedNameEncoded", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1200                                 else  {
1201                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1202                                         WriteMetCall ("WriteNullableStringEncoded", GetLiteral(name), GetLiteral(ns), strVal, GetLiteral(xsiType));
1203                                 }
1204                         }
1205                         else {
1206                                 if (typeData.Type == typeof(XmlQualifiedName))
1207                                         WriteMetCall ("WriteElementQualifiedName", GetLiteral(name), GetLiteral(ns), memberValue, GetLiteral(xsiType));
1208                                 else {
1209                                         string strVal = GenerateGetStringValue (mappedType, typeData, memberValue);
1210                                         WriteMetCall ("WriteElementString", GetLiteral(name),GetLiteral(ns), strVal, GetLiteral(xsiType));
1211                                 }
1212                         }
1213                 }
1214
1215                 string GenerateGetMemberValue (XmlTypeMapMember member, string ob, bool isValueList)
1216                 {
1217                         if (isValueList) return GetCast (member.TypeData, TypeTranslator.GetTypeData (typeof(object)), ob + "[" + member.GlobalIndex + "]");
1218                         else return ob + ".@" + member.Name;
1219                 }
1220                 
1221                 string GenerateMemberHasValueCondition (XmlTypeMapMember member, string ob, bool isValueList)
1222                 {
1223                         if (isValueList) {
1224                                 return ob + ".Length > " + member.GlobalIndex;
1225                         }
1226                         else if (member.DefaultValue != System.DBNull.Value) {
1227                                 string mem = ob + ".@" + member.Name;
1228                                 if (member.DefaultValue == null) 
1229                                         return mem + " != null";
1230                                 else if (member.TypeData.SchemaType == SchemaTypes.Enum)
1231                                         return mem + " != " + GetCast (member.TypeData, GetLiteral (member.DefaultValue));
1232                                 else 
1233                                         return mem + " != " + GetLiteral (member.DefaultValue);
1234                         }
1235                         else if (member.IsOptionalValueType)
1236                                 return ob + ".@" + member.Name + "Specified";
1237                         return null;
1238                 }
1239
1240                 void GenerateWriteInitCallbacks ()
1241                 {
1242                         WriteLine ("protected override void InitCallbacks ()");
1243                         WriteLineInd ("{");
1244                         
1245                         if (_format == SerializationFormat.Encoded)
1246                         {
1247                                 foreach (XmlMapping xmap in _mapsToGenerate)  {
1248                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1249                                         if (map != null)
1250                                                 WriteMetCall ("AddWriteCallback", GetTypeOf(map.TypeData), GetLiteral(map.XmlType), GetLiteral(map.Namespace), "new XmlSerializationWriteCallback (" + GetWriteObjectCallbackName (map) + ")");
1251                                 }
1252                         }       
1253                         
1254                         WriteLineUni ("}");
1255                         WriteLine ("");
1256                                 
1257                         if (_format == SerializationFormat.Encoded)
1258                         {
1259                                 foreach (XmlTypeMapping xmap in _mapsToGenerate)  {
1260                                         XmlTypeMapping map = xmap as XmlTypeMapping;
1261                                         if (map == null) continue;
1262                                         if (map.TypeData.SchemaType == SchemaTypes.Enum)
1263                                                 WriteWriteEnumCallback (map);
1264                                         else
1265                                                 WriteWriteObjectCallback (map);
1266                                 }
1267                         }
1268                 }
1269                 
1270                 void WriteWriteEnumCallback (XmlTypeMapping map)
1271                 {
1272                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1273                         WriteLineInd ("{");
1274                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "true", "false");
1275                         WriteLineUni ("}");
1276                         WriteLine ("");
1277                 }
1278                 
1279                 void WriteWriteObjectCallback (XmlTypeMapping map)
1280                 {
1281                         WriteLine ("void " + GetWriteObjectCallbackName (map) + " (object ob)");
1282                         WriteLineInd ("{");
1283                         WriteMetCall (GetWriteObjectName(map), GetCast (map.TypeData, "ob"), GetLiteral(map.ElementName), GetLiteral(map.Namespace), "false", "false", "false");
1284                         WriteLineUni ("}");
1285                         WriteLine ("");
1286                 }
1287                 
1288                 #endregion
1289                 
1290                 #region Reader Generation
1291
1292                 //*******************************************************
1293                 // Reader generation
1294                 //
1295                 
1296                 public void GenerateReader (string readerClassName, ArrayList maps)
1297                 {
1298                         if (_config == null || !_config.GenerateAsInternal)
1299                                 WriteLine ("public class " + readerClassName + " : XmlSerializationReader");
1300                         else
1301                                 WriteLine ("internal class " + readerClassName + " : XmlSerializationReader");
1302                         WriteLineInd ("{");
1303                         // FromBinHexString() is not public, so use reflection here.
1304                         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);");
1305                         WriteLine ("static byte [] FromBinHexString (string input)");
1306                         WriteLineInd ("{");
1307                         WriteLine ("return input == null ? null : (byte []) fromBinHexStringMethod.Invoke (null, new object [] {input});");
1308                         WriteLineUni ("}");
1309
1310                         _mapsToGenerate = new ArrayList ();
1311                         _fixupCallbacks = new ArrayList ();
1312                         InitHooks ();
1313                         
1314                         for (int n=0; n<maps.Count; n++)
1315                         {
1316                                 GenerationResult res = (GenerationResult) maps [n];
1317                                 _typeMap = res.Mapping;
1318                                 _format = _typeMap.Format;
1319                                 _result = res;
1320                                 
1321                                 GenerateReadRoot ();
1322                         }
1323                         
1324                         for (int n=0; n<_mapsToGenerate.Count; n++)
1325                         {
1326                                 XmlTypeMapping map = _mapsToGenerate [n] as XmlTypeMapping;
1327                                 if (map == null) continue;
1328                                 
1329                                 GenerateReadObject (map);
1330                                 if (map.TypeData.SchemaType == SchemaTypes.Enum)
1331                                         GenerateGetEnumValue (map);
1332                         }
1333                         
1334                         GenerateReadInitCallbacks ();
1335                         
1336                         if (_format == SerializationFormat.Encoded)
1337                         {
1338                                 GenerateFixupCallbacks ();
1339                                 GenerateFillerCallbacks ();
1340                         }
1341                         
1342                         WriteLineUni ("}");
1343                         UpdateGeneratedTypes (_mapsToGenerate);
1344                 }
1345                 
1346                 void GenerateReadRoot ()
1347                 {
1348                         WriteLine ("public object " + _result.ReadMethodName + " ()");
1349                         WriteLineInd ("{");
1350                         WriteLine ("Reader.MoveToContent();");
1351                         
1352                         if (_typeMap is XmlTypeMapping)
1353                         {
1354                                 XmlTypeMapping typeMap = (XmlTypeMapping) _typeMap;
1355
1356                                 if (_format == SerializationFormat.Literal)
1357                                 {
1358                                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlNode) {
1359                                                 if (typeMap.TypeData.Type == typeof (XmlDocument))
1360                                                         WriteLine ("return ReadXmlDocument (false);");
1361                                                 else
1362                                                         WriteLine ("return ReadXmlNode (false);");
1363                                         } else {
1364                                                 WriteLineInd ("if (Reader.LocalName != " + GetLiteral (typeMap.ElementName) + " || Reader.NamespaceURI != " + GetLiteral (typeMap.Namespace) + ")");
1365                                                 WriteLine ("throw CreateUnknownNodeException();");
1366                                                 Unindent ();
1367
1368                                                 WriteLine ("return " + GetReadObjectCall (typeMap, GetLiteral(typeMap.IsNullable), "true") + ";");
1369                                         }
1370                                 }
1371                                 else
1372                                 {
1373                                         WriteLine ("object ob = null;");
1374                                         WriteLine ("Reader.MoveToContent();");
1375                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1376                                         WriteLineInd ("{");
1377                                         WriteLineInd ("if (Reader.LocalName == " + GetLiteral(typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
1378                                         WriteLine ("ob = ReadReferencedElement();");
1379                                         Unindent ();
1380                                         WriteLineInd ("else ");
1381                                         WriteLine ("throw CreateUnknownNodeException();");
1382                                         Unindent ();
1383                                         WriteLineUni ("}");
1384                                         WriteLineInd ("else ");
1385                                         WriteLine ("UnknownNode(null);");
1386                                         Unindent ();
1387                                         WriteLine ("");
1388                                         WriteLine ("ReadReferencedElements();");
1389                                         WriteLine ("return ob;");
1390                                         RegisterReferencingMap (typeMap);
1391                                 }
1392                         }
1393                         else {
1394                                 WriteLine ("return " + GenerateReadMessage ((XmlMembersMapping)_typeMap) + ";");
1395                         }
1396
1397                         WriteLineUni ("}");
1398                         WriteLine ("");
1399                 }
1400                 
1401                 string GenerateReadMessage (XmlMembersMapping typeMap)
1402                 {
1403                         WriteLine ("object[] parameters = new object[" + typeMap.Count + "];");
1404                         WriteLine ("");
1405
1406                         if (typeMap.HasWrapperElement)
1407                         {
1408                                 if (_format == SerializationFormat.Encoded)
1409                                 {
1410                                         WriteLine ("while (Reader.NodeType == System.Xml.XmlNodeType.Element)");
1411                                         WriteLineInd ("{");
1412                                         WriteLine ("string root = Reader.GetAttribute (\"root\", " + GetLiteral(XmlSerializer.EncodingNamespace) + ");");
1413                                         WriteLine ("if (root == null || System.Xml.XmlConvert.ToBoolean(root)) break;");
1414                                         WriteLine ("ReadReferencedElement ();");
1415                                         WriteLine ("Reader.MoveToContent ();");
1416                                         WriteLineUni ("}");
1417                                         WriteLine ("");
1418                                         WriteLine ("if (Reader.NodeType != System.Xml.XmlNodeType.EndElement)");
1419                                         WriteLineInd ("{");
1420                                         WriteLineInd ("if (Reader.IsEmptyElement) {");
1421                                         WriteLine ("Reader.Skip();");
1422                                         WriteLine ("Reader.MoveToContent();");
1423                                         WriteLineUni ("}");
1424                                         WriteLineInd ("else {");
1425                                         WriteLine ("Reader.ReadStartElement();");
1426                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1427                                         WriteLine ("ReadEndElement();");
1428                                         WriteLineUni ("}");
1429                                         WriteLine ("");
1430                                         WriteLine ("Reader.MoveToContent();");
1431                                         WriteLineUni ("}");
1432                                 }
1433                                 else
1434                                 {
1435                                         // bug #79988: out parameters need to be initialized if 
1436                                         // they are value types
1437                                         ClassMap classMap = (ClassMap) typeMap.ObjectMap;
1438                                         ArrayList members = classMap.AllMembers;
1439                                         for (int n = 0; n < members.Count; n++) {
1440                                                 XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
1441                                                 if (!mem.IsReturnValue && mem.TypeData.IsValueType)
1442                                                         GenerateSetMemberValueFromAttr (mem, "parameters",
1443                                                                 String.Format ("({0}) Activator.CreateInstance(typeof({0}), true)", mem.TypeData.FullTypeName), true);
1444                                         }
1445
1446                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.ReadState == ReadState.Interactive)");
1447                                         WriteLineInd ("{");
1448                                         WriteLine ("if (Reader.IsStartElement(" + GetLiteral(typeMap.ElementName) + ", " + GetLiteral(typeMap.Namespace) + "))");
1449                                         WriteLineInd ("{");
1450                                         bool dummy = false;
1451                                         GenerateReadAttributeMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, ref dummy);
1452                                         WriteLine ("if (Reader.IsEmptyElement)");
1453                                         WriteLineInd ("{");
1454                                         WriteLine ("Reader.Skip(); Reader.MoveToContent(); continue;");
1455                                         WriteLineUni ("}");
1456                                         WriteLine ("Reader.ReadStartElement();");
1457                                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, false);
1458                                         WriteLine ("ReadEndElement();");
1459                                         WriteLine ("break;");
1460                                         WriteLineUni ("}");
1461                                         WriteLineInd ("else ");
1462                                         WriteLine ("UnknownNode(null);");
1463                                         Unindent ();
1464                                         WriteLine ("");
1465                                         WriteLine ("Reader.MoveToContent();");
1466                                         WriteLineUni ("}");
1467                                 }
1468                         }
1469                         else
1470                                 GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "parameters", true, _format == SerializationFormat.Encoded);
1471
1472                         if (_format == SerializationFormat.Encoded)
1473                                 WriteLine ("ReadReferencedElements();");
1474
1475                         return "parameters";
1476                 }
1477                 
1478                 void GenerateReadObject (XmlTypeMapping typeMap)
1479                 {
1480                         string isNullable;
1481                         if (_format == SerializationFormat.Literal) {
1482                                 WriteLine ("public " + typeMap.TypeData.CSharpFullName + " " + GetReadObjectName (typeMap) + " (bool isNullable, bool checkType)");
1483                                 isNullable = "isNullable";
1484                         }
1485                         else {
1486                                 WriteLine ("public object " + GetReadObjectName (typeMap) + " ()");
1487                                 isNullable = "true";
1488                         }
1489                         
1490                         WriteLineInd ("{");
1491
1492                         PushHookContext ();
1493                         
1494                         SetHookVar ("$TYPE", typeMap.TypeData.CSharpName);
1495                         SetHookVar ("$FULLTYPE", typeMap.TypeData.CSharpFullName);
1496                         SetHookVar ("$NULLABLE", "isNullable");
1497                         
1498                         switch (typeMap.TypeData.SchemaType)
1499                         {
1500                                 case SchemaTypes.Class: GenerateReadClassInstance (typeMap, isNullable, "checkType"); break;
1501                                 case SchemaTypes.Array: 
1502                                         string list = GenerateReadListElement (typeMap, null, isNullable, true);
1503                                         if (list != null)
1504                                                 WriteLine ("return " + list + ";"); 
1505                                         break;
1506                                 case SchemaTypes.XmlNode: GenerateReadXmlNodeElement (typeMap, isNullable); break;
1507                                 case SchemaTypes.Primitive: GenerateReadPrimitiveElement (typeMap, isNullable); break;
1508                                 case SchemaTypes.Enum: GenerateReadEnumElement (typeMap, isNullable); break;
1509                                 case SchemaTypes.XmlSerializable: GenerateReadXmlSerializableElement (typeMap, isNullable); break;
1510                                 default: throw new Exception ("Unsupported map type");
1511                         }
1512                         
1513                         WriteLineUni ("}");
1514                         WriteLine ("");
1515                         PopHookContext ();
1516                 }
1517                                 
1518                 void GenerateReadClassInstance (XmlTypeMapping typeMap, string isNullable, string checkType)
1519                 {
1520                         SetHookVar ("$OBJECT", "ob");
1521                         if (!typeMap.TypeData.IsValueType)
1522                         {
1523                                 WriteLine (typeMap.TypeData.CSharpFullName + " ob = null;");
1524                         
1525                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1526                                         WriteLine ("return ob;");
1527                                         return;
1528                                 }
1529                                 
1530                                 if (_format == SerializationFormat.Literal) {
1531                                         WriteLine ("if (" + isNullable + " && ReadNull()) return null;");
1532                                         WriteLine ("");
1533                                         WriteLine ("if (checkType) ");
1534                                         WriteLineInd ("{");
1535                                 }
1536                                 else {
1537                                         WriteLine ("if (ReadNull()) return null;");
1538                                         WriteLine ("");
1539                                 }
1540                         }
1541                         else
1542                         {
1543                                 WriteLine (typeMap.TypeData.CSharpFullName + String.Format (" ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1544                         
1545                                 if (GenerateReadHook (HookType.type, typeMap.TypeData.Type)) {
1546                                         WriteLine ("return ob;");
1547                                         return;
1548                                 }
1549                         }
1550                         
1551                         WriteLine ("System.Xml.XmlQualifiedName t = GetXsiType();");
1552                         WriteLine ("if (t == null)");
1553                         if (typeMap.TypeData.Type != typeof(object))
1554                                 WriteLine ("{ }");
1555                         else
1556                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (new System.Xml.XmlQualifiedName(\"anyType\", System.Xml.Schema.XmlSchema.Namespace))") + ";");
1557                         
1558                         foreach (XmlTypeMapping realMap in typeMap.DerivedTypes)
1559                         {
1560                                 WriteLineInd ("else if (t.Name == " + GetLiteral (realMap.XmlType) + " && t.Namespace == " + GetLiteral (realMap.XmlTypeNamespace) + ")");
1561                                 WriteLine ("return " + GetReadObjectCall(realMap, isNullable, checkType) + ";");
1562                                 Unindent ();
1563                         }
1564
1565                         WriteLine ("else if (t.Name != " + GetLiteral (typeMap.XmlType) + " || t.Namespace != " + GetLiteral (typeMap.XmlTypeNamespace) + ")");
1566                         if (typeMap.TypeData.Type == typeof(object))
1567                                 WriteLine ("\treturn " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
1568                         else
1569                                 WriteLine ("\tthrow CreateUnknownTypeException(t);");
1570
1571                         if (!typeMap.TypeData.IsValueType)
1572                         {
1573                                 if (_format == SerializationFormat.Literal)
1574                                         WriteLineUni ("}");
1575
1576                                 if (typeMap.TypeData.Type.IsAbstract) {
1577                                         GenerateEndHook ();
1578                                         WriteLine ("return ob;");
1579                                         return;
1580                                 }
1581         
1582                                 WriteLine ("");
1583                                 WriteLine (String.Format ("ob = ({0}) Activator.CreateInstance(typeof({0}), true);", typeMap.TypeData.CSharpFullName));
1584                         }
1585                         
1586                         WriteLine ("");
1587                         
1588                         WriteLine ("Reader.MoveToElement();");
1589                         WriteLine ("");
1590                         
1591                         GenerateReadMembers (typeMap, (ClassMap)typeMap.ObjectMap, "ob", false, false);
1592                         
1593                         WriteLine ("");
1594                         
1595                         GenerateEndHook ();
1596                         WriteLine ("return ob;");
1597                 }
1598
1599                 void GenerateReadMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, bool readByOrder)
1600                 {
1601                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1602                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
1603                         
1604                         // Load the default value of members
1605                         if (map.MembersWithDefault != null)
1606                         {
1607                                 ArrayList members = map.MembersWithDefault;
1608                                 for (int n=0; n<members.Count; n++) {
1609                                         XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
1610                                         GenerateSetMemberValueFromAttr (mem, ob, GetLiteral (mem.DefaultValue), isValueList);
1611                                 }
1612                         }
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 && !readByOrder)
1640                                 {
1641                                         string readFlagsVars = "bool ";
1642                                         readFlag = new string[map.ElementMembers.Count];
1643                                         for (int n=0; n<map.ElementMembers.Count; n++) {
1644                                                 readFlag[n] = GetBoolTempVar ();
1645                                                 if (n > 0) readFlagsVars += ", ";
1646                                                 readFlagsVars += readFlag[n] + "=false";
1647                                         }
1648                                         if (map.ElementMembers.Count > 0) WriteLine (readFlagsVars + ";");
1649                                         WriteLine ("");
1650                                 }
1651                                 
1652                                 string[] indexes = null;
1653                                 string[] flatLists = null;
1654                                 string[] flatListsChoices = null;
1655         
1656                                 if (map.FlatLists != null) 
1657                                 {
1658                                         indexes = new string[map.FlatLists.Count];
1659                                         flatLists = new string[map.FlatLists.Count];
1660                                         
1661                                         string code = "int ";
1662                                         for (int n=0; n<map.FlatLists.Count; n++) 
1663                                         {
1664                                                 XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement)map.FlatLists[n];
1665                                                 indexes[n] = GetNumTempVar ();
1666                                                 if (n > 0) code += ", ";
1667                                                 code += indexes[n] + "=0";
1668                                                 if (!MemberHasReadReplaceHook (xmlMapType, mem)) {
1669                                                         flatLists[n] = GetObTempVar ();
1670                                                         string rval;
1671                                                         WriteLine (mem.TypeData.CSharpFullName + " " + flatLists[n] + ";");
1672                                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList)) {
1673                                                                 rval = GenerateGetMemberValue (mem, ob, isValueList);
1674                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1675                                                         } else if (mem.TypeData.Type.IsArray) {
1676                                                                 rval = GenerateInitializeList (mem.TypeData);
1677                                                                 WriteLine (flatLists[n] + " = " + rval + ";");
1678                                                         } else {
1679                                                                 WriteLine (flatLists[n] + " = " + GenerateGetMemberValue (mem, ob, isValueList) + ";");
1680                                                                 WriteLineInd ("if (((object)" + flatLists[n] + ") == null) {");
1681                                                                 WriteLine (flatLists[n] + " = " + GenerateInitializeList (mem.TypeData) + ";");
1682                                                                 GenerateSetMemberValue (mem, ob, flatLists[n], isValueList);
1683                                                                 WriteLineUni ("}");
1684                                                         }
1685                                                 }
1686                                                 
1687                                                 if (mem.ChoiceMember != null) {
1688                                                         if (flatListsChoices == null)
1689                                                                 flatListsChoices = new string [map.FlatLists.Count];
1690                                                         flatListsChoices[n] = GetObTempVar ();
1691                                                         string rval = GenerateInitializeList (mem.ChoiceTypeData);
1692                                                         WriteLine (mem.ChoiceTypeData.CSharpFullName + " " + flatListsChoices[n] + " = " + rval + ";");
1693                                                 }
1694                                         }
1695                                         WriteLine (code + ";");
1696                                         WriteLine ("");
1697                                 }
1698                                 
1699                                 if (_format == SerializationFormat.Encoded && map.ElementMembers != null)
1700                                 {
1701                                         _fixupCallbacks.Add (xmlMap);
1702                                         WriteLine ("Fixup fixup = new Fixup(" + ob + ", new XmlSerializationFixupCallback(" + GetFixupCallbackName (xmlMap) + "), " + map.ElementMembers.Count + ");");
1703                                         WriteLine ("AddFixup (fixup);");
1704                                         WriteLine ("");
1705                                 }
1706         
1707                                 ArrayList infos = null;
1708                                 
1709                                 int maxInd;
1710                                 if (readByOrder) {
1711                                         if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
1712                                         else maxInd = 0;
1713                                 }
1714                                 else
1715                                 {
1716                                         infos = new ArrayList ();
1717                                         infos.AddRange (map.AllElementInfos);
1718                                         maxInd = infos.Count;
1719                                         
1720                                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
1721                                         WriteLineInd ("{");
1722                                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
1723                                         WriteLineInd ("{");
1724                                 }
1725                                 
1726                                 first = true;
1727                                 for (int ind = 0; ind < maxInd; ind++)
1728                                 {
1729                                         XmlTypeMapElementInfo info = readByOrder ? map.GetElement (ind) : (XmlTypeMapElementInfo) infos [ind];
1730                                         
1731                                         if (!readByOrder)
1732                                         {
1733                                                 if (info.IsTextElement || info.IsUnnamedAnyElement) continue;
1734                                                 string elemCond = first ? "" : "else ";
1735                                                 elemCond += "if (";
1736                                                 if (!(info.Member.IsReturnValue && _format == SerializationFormat.Encoded)) {
1737                                                         elemCond += "Reader.LocalName == " + GetLiteral (info.ElementName);
1738                                                         if (!map.IgnoreMemberNamespace) elemCond += " && Reader.NamespaceURI == " + GetLiteral (info.Namespace);
1739                                                         elemCond += " && ";
1740                                                 }
1741                                                 elemCond += "!" + readFlag[info.Member.Index] + ") {";
1742                                                 WriteLineInd (elemCond);
1743                                         }
1744         
1745                                         if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
1746                                         {
1747                                                 if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
1748                                                 {
1749                                                         string list = GetObTempVar ();
1750                                                         WriteLine ("object " + list + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1751                                                         RegisterReferencingMap (info.MappedType);
1752
1753                                                         WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // Already read
1754                                                         if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1755                                                                 WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral(info.TypeData.CSharpFullName) + ");");
1756                                                         else 
1757                                                                 GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1758                                                         WriteLineUni ("}");
1759         
1760                                                         if (!info.MappedType.TypeData.Type.IsArray)
1761                                                         {
1762                                                                 WriteLineInd ("else {");
1763                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) 
1764                                                                         WriteLine (list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1765                                                                 else { 
1766                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1767                                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,list), isValueList);
1768                                                                 }
1769                                                                 WriteLine ("AddFixup (new CollectionFixup (" + list + ", new XmlSerializationCollectionFixupCallback (" + GetFillListName(info.Member.TypeData) + "), fixup.Ids[" + info.Member.Index + "]));");
1770                                                                 WriteLine ("fixup.Ids[" + info.Member.Index + "] = null;");             // The member already has the value, no further fix needed.
1771                                                                 WriteLineUni ("}");
1772                                                         }
1773                                                 }
1774                                                 else
1775                                                 {
1776                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1777                                                                 if (IsReadOnly (typeMap, info.Member, info.TypeData, isValueList)) {
1778                                                                         GenerateReadListElement (info.MappedType, GenerateGetMemberValue (info.Member, ob, isValueList), GetLiteral(info.IsNullable), false);
1779                                                                 } else if (info.MappedType.TypeData.Type.IsArray) {
1780                                                                         if (info.IsNullable)
1781                                                                                 GenerateSetMemberValue (info.Member, ob, GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true), isValueList);
1782                                                                         else {
1783                                                                                 string list = GetObTempVar ();
1784                                                                                 WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateReadListElement (info.MappedType, null, GetLiteral(info.IsNullable), true) + ";");
1785                                                                                 WriteLineInd ("if (((object)" + list + ") != null) {");
1786                                                                                 GenerateSetMemberValue (info.Member, ob, list, isValueList);
1787                                                                                 WriteLineUni ("}");
1788                                                                         }
1789                                                                 } else {
1790                                                                         string list = GetObTempVar ();
1791                                                                         WriteLine (info.MappedType.TypeData.CSharpFullName + " " + list + " = " + GenerateGetMemberValue (info.Member, ob, isValueList) + ";");
1792                                                                         WriteLineInd ("if (((object)" + list + ") == null) {");
1793                                                                         WriteLine (list + " = " + GenerateCreateList (info.MappedType.TypeData.Type) + ";");
1794                                                                         GenerateSetMemberValue (info.Member, ob, list, isValueList);
1795                                                                         WriteLineUni ("}");
1796                                                                         GenerateReadListElement (info.MappedType, list, GetLiteral(info.IsNullable), true);
1797                                                                 }
1798                                                                 GenerateEndHook ();
1799                                                         }
1800                                                 }
1801                                                 if (!readByOrder)
1802                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1803                                         }
1804                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
1805                                         {
1806                                                 XmlTypeMapMemberFlatList mem = (XmlTypeMapMemberFlatList)info.Member;
1807                                                 if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1808                                                         GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GenerateReadObjectElement (info), !IsReadOnly (typeMap, info.Member, info.TypeData, isValueList));
1809                                                         if (mem.ChoiceMember != null) {
1810                                                                 GenerateAddListValue (mem.ChoiceTypeData, flatListsChoices[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetLiteral (info.ChoiceValue), true);
1811                                                         }
1812                                                         GenerateEndHook ();
1813                                                 }
1814                                                 WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1815                                         }
1816                                         else if (info.Member.GetType() == typeof (XmlTypeMapMemberAnyElement))
1817                                         {
1818                                                 XmlTypeMapMemberAnyElement mem = (XmlTypeMapMemberAnyElement)info.Member;
1819                                                 if (mem.TypeData.IsListType) { 
1820                                                         if (!GenerateReadArrayMemberHook (xmlMapType, info.Member, indexes[mem.FlatArrayIndex])) {
1821                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode (mem.TypeData.ListItemTypeData, false), true);
1822                                                                 GenerateEndHook ();
1823                                                         }
1824                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1825                                                 }
1826                                                 else {
1827                                                         if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1828                                                                 GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1829                                                                 GenerateEndHook ();
1830                                                         }
1831                                                 }
1832                                         }
1833                                         else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
1834                                         {
1835                                                 if (!readByOrder)
1836                                                         WriteLine (readFlag[info.Member.Index] + " = true;");
1837                                                 if (_format == SerializationFormat.Encoded)
1838                                                 {
1839                                                         string val = GetObTempVar ();
1840                                                         RegisterReferencingMap (info.MappedType);
1841                                                         
1842                                                         if (info.Member.TypeData.SchemaType != SchemaTypes.Primitive)
1843                                                                 WriteLine ("object " + val + " = ReadReferencingElement (out fixup.Ids[" + info.Member.Index + "]);");
1844                                                         else
1845                                                                 WriteLine ("object " + val + " = ReadReferencingElement (" + GetLiteral(info.Member.TypeData.XmlType) + ", " + GetLiteral(System.Xml.Schema.XmlSchema.Namespace) + ", out fixup.Ids[" + info.Member.Index + "]);");
1846                                                         
1847                                                         if (info.MultiReferenceType)
1848                                                                 WriteLineInd ("if (fixup.Ids[" + info.Member.Index + "] == null) {");   // already read
1849                                                         else
1850                                                                 WriteLineInd ("if (" + val + " != null) {");    // null value
1851                                                                 
1852                                                         GenerateSetMemberValue (info.Member, ob, GetCast (info.Member.TypeData,val), isValueList);
1853                                                         WriteLineUni ("}");
1854                                                 }
1855                                                 else if (!GenerateReadMemberHook (xmlMapType, info.Member)) {
1856                                                         if (info.ChoiceValue != null) {
1857                                                                 XmlTypeMapMemberElement imem = (XmlTypeMapMemberElement) info.Member;
1858                                                                 WriteLine (ob + ".@" + imem.ChoiceMember + " = " + GetLiteral(info.ChoiceValue) + ";");
1859                                                         }
1860                                                         GenerateSetMemberValue (info.Member, ob, GenerateReadObjectElement (info), isValueList);
1861                                                         GenerateEndHook ();
1862                                                 }
1863                                         }
1864                                         else
1865                                                 throw new InvalidOperationException ("Unknown member type");
1866         
1867                                         if (!readByOrder)
1868                                                 WriteLineUni ("}");
1869                                         else
1870                                                 WriteLine ("Reader.MoveToContent();");
1871                                         first = false;
1872                                 }
1873                                 
1874                                 if (!readByOrder)
1875                                 {
1876                                         if (!first) WriteLineInd ("else {");
1877                                         
1878                                         if (map.DefaultAnyElementMember != null)
1879                                         {
1880                                                 XmlTypeMapMemberAnyElement mem = map.DefaultAnyElementMember;
1881                                                 if (mem.TypeData.IsListType) {
1882                                                         if (!GenerateReadArrayMemberHook (xmlMapType, mem, indexes[mem.FlatArrayIndex])) {
1883                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], GetReadXmlNode(mem.TypeData.ListItemTypeData, false), true);
1884                                                                 GenerateEndHook ();
1885                                                         }
1886                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1887                                                 }
1888                                                 else if (! GenerateReadMemberHook (xmlMapType, mem)) {
1889                                                         GenerateSetMemberValue (mem, ob, GetReadXmlNode(mem.TypeData, false), isValueList);
1890                                                         GenerateEndHook ();
1891                                                 }
1892                                         }
1893                                         else {
1894                                                 if (!GenerateReadHook (HookType.unknownElement, xmlMapType)) {
1895                                                         WriteLine ("UnknownNode (" + ob + ");");
1896                                                         GenerateEndHook ();
1897                                                 }
1898                                         }
1899                                         
1900                                         if (!first) WriteLineUni ("}");
1901                 
1902                                         WriteLineUni ("}");
1903                                         
1904                                         if (map.XmlTextCollector != null)
1905                                         {
1906                                                 WriteLine ("else if (Reader.NodeType == System.Xml.XmlNodeType.Text || Reader.NodeType == System.Xml.XmlNodeType.CDATA)");
1907                                                 WriteLineInd ("{");
1908                 
1909                                                 if (map.XmlTextCollector is XmlTypeMapMemberExpandable)
1910                                                 {
1911                                                         XmlTypeMapMemberExpandable mem = (XmlTypeMapMemberExpandable)map.XmlTextCollector;
1912                                                         XmlTypeMapMemberFlatList flatl = mem as XmlTypeMapMemberFlatList;
1913                                                         TypeData itype = (flatl == null) ? mem.TypeData.ListItemTypeData : flatl.ListMap.FindTextElement().TypeData;
1914                                                         
1915                                                         if (!GenerateReadArrayMemberHook (xmlMapType, map.XmlTextCollector, indexes[mem.FlatArrayIndex])) {
1916                                                                 string val = (itype.Type == typeof (string)) ? "Reader.ReadString()" : GetReadXmlNode (itype, false);
1917                                                                 GenerateAddListValue (mem.TypeData, flatLists[mem.FlatArrayIndex], indexes[mem.FlatArrayIndex], val, true);
1918                                                                 GenerateEndHook ();
1919                                                         }
1920                                                         WriteLine (indexes[mem.FlatArrayIndex] + "++;");
1921                                                 }
1922                                                 else if (!GenerateReadMemberHook (xmlMapType, map.XmlTextCollector))
1923                                                 {
1924                                                         XmlTypeMapMemberElement mem = (XmlTypeMapMemberElement) map.XmlTextCollector;
1925                                                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) mem.ElementInfo [0];
1926                                                         if (info.TypeData.Type == typeof (string))
1927                                                                 GenerateSetMemberValue (mem, ob, "ReadString (" + GenerateGetMemberValue (mem, ob, isValueList) + ")", isValueList);
1928                                                         else
1929                                                                 GenerateSetMemberValue (mem, ob, GenerateGetValueFromXmlString ("Reader.ReadString()", info.TypeData, info.MappedType), isValueList);
1930                                                         GenerateEndHook ();
1931                                                 }
1932                                                 WriteLineUni ("}");
1933                                         }
1934                                                 
1935                                         WriteLine ("else");
1936                                         WriteLine ("\tUnknownNode(" + ob + ");");
1937                                         WriteLine ("");
1938                                         WriteLine ("Reader.MoveToContent();");
1939                                         WriteLineUni ("}");
1940                                 }
1941                                 else
1942                                         WriteLine ("Reader.MoveToContent();");
1943         
1944                                 if (flatLists != null)
1945                                 {
1946                                         WriteLine ("");
1947                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1948                                         {
1949                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1950                                                 
1951                                                 string list = flatLists[mem.FlatArrayIndex];
1952                                                 if (mem.TypeData.Type.IsArray)
1953                                                         WriteLine (list + " = (" + mem.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.TypeData.Type.GetElementType()) + ", true);");
1954                                                 if (!IsReadOnly (typeMap, mem, mem.TypeData, isValueList) && mem.TypeData.Type.IsArray)
1955                                                         GenerateSetMemberValue (mem, ob, list, isValueList);
1956                                         }
1957                                 }
1958                                 
1959                                 if (flatListsChoices != null)
1960                                 {
1961                                         WriteLine ("");
1962                                         foreach (XmlTypeMapMemberExpandable mem in map.FlatLists)
1963                                         {
1964                                                 if (MemberHasReadReplaceHook (xmlMapType, mem)) continue;
1965                                                 if (mem.ChoiceMember == null) continue;
1966                                                 
1967                                                 string list = flatListsChoices[mem.FlatArrayIndex];
1968                                                 WriteLine (list + " = (" + mem.ChoiceTypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + indexes[mem.FlatArrayIndex] + ", " + GetTypeOf(mem.ChoiceTypeData.Type.GetElementType()) + ", true);");
1969                                                 WriteLine (ob + ".@" + mem.ChoiceMember + " = " + list + ";");
1970                                         }
1971                                 }
1972                                 
1973                                 GenerateSetListMembersDefaults (typeMap, map, ob, isValueList);
1974                                 
1975                                 GenerateEndHook ();
1976                         }                       
1977
1978                         if (!isValueList)
1979                         {
1980                                 WriteLine ("");
1981                                 WriteLine ("ReadEndElement();");
1982                         }
1983                 }
1984
1985                 void GenerateReadAttributeMembers (XmlMapping xmlMap, ClassMap map, string ob, bool isValueList, ref bool first)
1986                 {
1987                         XmlTypeMapping typeMap = xmlMap as XmlTypeMapping;
1988                         Type xmlMapType = (typeMap != null) ? typeMap.TypeData.Type : typeof(object[]);
1989
1990                         if (GenerateReadHook (HookType.attributes, xmlMapType))
1991                                 return;
1992
1993                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
1994                         
1995                         if (anyAttrMember != null)
1996                         {
1997                                 WriteLine ("int anyAttributeIndex = 0;");
1998                                 WriteLine (anyAttrMember.TypeData.CSharpFullName + " anyAttributeArray = null;");
1999                         }
2000                         
2001                         WriteLine ("while (Reader.MoveToNextAttribute())");
2002                         WriteLineInd ("{");
2003                         first = true;
2004                         if (map.AttributeMembers != null) {
2005                                 foreach (XmlTypeMapMemberAttribute at in map.AttributeMembers)
2006                                 {
2007                                         WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (at.AttributeName) + " && Reader.NamespaceURI == " + GetLiteral (at.Namespace) + ") {");
2008                                         if (!GenerateReadMemberHook (xmlMapType, at)) {
2009                                                 GenerateSetMemberValue (at, ob, GenerateGetValueFromXmlString ("Reader.Value", at.TypeData, at.MappedType), isValueList);
2010                                                 GenerateEndHook ();
2011                                         }
2012                                         WriteLineUni ("}");
2013                                         first = false;
2014                                 }
2015                         }
2016                         WriteLineInd ((first?"":"else ") + "if (IsXmlnsAttribute (Reader.Name)) {");
2017
2018                         // If the map has NamespaceDeclarations,
2019                         // then store this xmlns to the given member.
2020                         // If the instance doesn't exist, then create.
2021                         
2022                         if (map.NamespaceDeclarations != null) {
2023                                 if (!GenerateReadMemberHook (xmlMapType, map.NamespaceDeclarations)) {
2024                                         string nss = ob + ".@" + map.NamespaceDeclarations.Name;
2025                                         WriteLine ("if (" + nss + " == null) " + nss + " = new XmlSerializerNamespaces ();");
2026                                         WriteLineInd ("if (Reader.Prefix == \"xmlns\")");
2027                                         WriteLine (nss + ".Add (Reader.LocalName, Reader.Value);");
2028                                         Unindent ();
2029                                         WriteLineInd ("else");
2030                                         WriteLine (nss + ".Add (\"\", Reader.Value);");
2031                                         Unindent ();
2032                                         GenerateEndHook ();
2033                                 }
2034                         }
2035                         
2036                         WriteLineUni ("}");
2037                         WriteLineInd ("else {");
2038
2039                         if (anyAttrMember != null) 
2040                         {
2041                                 if (!GenerateReadArrayMemberHook (xmlMapType, anyAttrMember, "anyAttributeIndex")) {
2042                                         WriteLine ("System.Xml.XmlAttribute attr = (System.Xml.XmlAttribute) Document.ReadNode(Reader);");
2043                                         if (typeof(System.Xml.Schema.XmlSchemaAnnotated).IsAssignableFrom (xmlMapType)) 
2044                                                 WriteLine ("ParseWsdlArrayType (attr);");
2045                                         GenerateAddListValue (anyAttrMember.TypeData, "anyAttributeArray", "anyAttributeIndex", GetCast (anyAttrMember.TypeData.ListItemTypeData, "attr"), true);
2046                                         GenerateEndHook ();
2047                                 }
2048                                 WriteLine ("anyAttributeIndex++;");
2049                         }
2050                         else {
2051                                 if (!GenerateReadHook (HookType.unknownAttribute, xmlMapType)) {
2052                                         WriteLine ("UnknownNode (" + ob + ");");
2053                                         GenerateEndHook ();
2054                                 }
2055                         }
2056
2057                         WriteLineUni ("}");
2058                         WriteLineUni ("}");
2059
2060                         if (anyAttrMember != null && !MemberHasReadReplaceHook (xmlMapType, anyAttrMember))
2061                         {
2062                                 WriteLine ("");
2063                                 WriteLine("anyAttributeArray = (" + anyAttrMember.TypeData.CSharpFullName + ") ShrinkArray (anyAttributeArray, anyAttributeIndex, " + GetTypeOf(anyAttrMember.TypeData.Type.GetElementType()) + ", true);");
2064                                 GenerateSetMemberValue (anyAttrMember, ob, "anyAttributeArray", isValueList);
2065                         }
2066                         WriteLine ("");
2067                         WriteLine ("Reader.MoveToElement ();");
2068
2069                         GenerateEndHook ();
2070                 }
2071                 
2072                 void GenerateSetListMembersDefaults (XmlTypeMapping typeMap, ClassMap map, string ob, bool isValueList)
2073                 {
2074                         if (map.ListMembers != null)
2075                         {
2076                                 ArrayList members = map.ListMembers;
2077                                 for (int n=0; n<members.Count; n++) {
2078                                         XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
2079                                         if (IsReadOnly (typeMap, mem, mem.TypeData, isValueList))
2080                                                 continue;
2081                                         WriteLineInd ("if (" + GenerateGetMemberValue (mem, ob, isValueList) + " == null) {");
2082                                         GenerateSetMemberValue (mem, ob, GenerateInitializeList (mem.TypeData), isValueList);
2083                                         WriteLineUni ("}");
2084                                 }
2085                         }
2086                 }
2087                 
2088                 bool IsReadOnly (XmlTypeMapping map, XmlTypeMapMember member, TypeData memType, bool isValueList)
2089                 {
2090                         if (isValueList) return !memType.HasPublicConstructor;
2091                         else return member.IsReadOnly (map.TypeData.Type) || !memType.HasPublicConstructor;
2092                 }
2093
2094                 void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
2095                 {
2096                         if (isValueList) WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
2097                         else {
2098                                 WriteLine (ob + ".@" + member.Name + " = " + value + ";");
2099                                 if (member.IsOptionalValueType)
2100                                         WriteLine (ob + "." + member.Name + "Specified = true;");
2101                         }
2102                 }
2103
2104                 void GenerateSetMemberValueFromAttr (XmlTypeMapMember member, string ob, string value, bool isValueList)
2105                 {
2106                         // Enumeration values specified in custom attributes are stored as integer
2107                         // values if the custom attribute property is of type object. So, it is
2108                         // necessary to convert to the enum type before asigning the value to the field.
2109                         
2110                         if (member.TypeData.Type.IsEnum)
2111                                 value = GetCast (member.TypeData.Type, value);
2112                         GenerateSetMemberValue (member, ob, value, isValueList);
2113                 }
2114
2115                 string GenerateReadObjectElement (XmlTypeMapElementInfo elem)
2116                 {
2117                         switch (elem.TypeData.SchemaType)
2118                         {
2119                                 case SchemaTypes.XmlNode:
2120                                         return GetReadXmlNode (elem.TypeData, true);
2121
2122                                 case SchemaTypes.Primitive:
2123                                 case SchemaTypes.Enum:
2124                                         return GenerateReadPrimitiveValue (elem);
2125
2126                                 case SchemaTypes.Array:
2127                                         return GenerateReadListElement (elem.MappedType, null, GetLiteral(elem.IsNullable), true);
2128
2129                                 case SchemaTypes.Class:
2130                                         return GetReadObjectCall (elem.MappedType, GetLiteral(elem.IsNullable), "true");
2131
2132                                 case SchemaTypes.XmlSerializable:
2133                                         return GetCast (elem.TypeData, String.Format ("ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true))", elem.TypeData.CSharpFullName));
2134
2135                                 default:
2136                                         throw new NotSupportedException ("Invalid value type");
2137                         }
2138                 }
2139
2140                 string GenerateReadPrimitiveValue (XmlTypeMapElementInfo elem)
2141                 {
2142                         if (elem.TypeData.Type == typeof (XmlQualifiedName)) {
2143                                 if (elem.IsNullable) return "ReadNullableQualifiedName ()";
2144                                 else return "ReadElementQualifiedName ()";
2145                         }
2146                         else if (elem.IsNullable)
2147                                 return GenerateGetValueFromXmlString ("ReadNullableString ()", elem.TypeData, elem.MappedType);
2148                         else
2149                                 return GenerateGetValueFromXmlString ("Reader.ReadElementString ()", elem.TypeData, elem.MappedType);
2150                 }
2151                 
2152                 string GenerateGetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap)
2153                 {
2154                         if (typeData.SchemaType == SchemaTypes.Array)
2155                                 return GenerateReadListString (typeMap, value);
2156                         else if (typeData.SchemaType == SchemaTypes.Enum)
2157                                 return GenerateGetEnumValue (typeMap, value);
2158                         else if (typeData.Type == typeof (XmlQualifiedName))
2159                                 return "ToXmlQualifiedName (" + value + ")";
2160                         else 
2161                                 return XmlCustomFormatter.GenerateFromXmlString (typeData, value);
2162                 }
2163                 
2164                 string GenerateReadListElement (XmlTypeMapping typeMap, string list, string isNullable, bool canCreateInstance)
2165                 {
2166                         Type listType = typeMap.TypeData.Type;
2167                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2168                         bool doNullCheck = typeMap.TypeData.Type.IsArray;
2169
2170                         if (canCreateInstance && typeMap.TypeData.HasPublicConstructor) 
2171                         {
2172                                 if (list == null) {
2173                                         list = GetObTempVar ();
2174                                         WriteLine (typeMap.TypeData.CSharpFullName + " " + list + " = null;");
2175                                         if (doNullCheck)
2176                                                 WriteLineInd ("if (!ReadNull()) {");
2177                                         WriteLine (list + " = " + GenerateCreateList (listType) + ";");
2178                                 } else {
2179                                         if (doNullCheck)
2180                                                 WriteLineInd ("if (!ReadNull()) {");
2181                                 }
2182                         }
2183                         else
2184                         {
2185                                 if (list != null) {
2186                                         WriteLineInd ("if (((object)" + list + ") == null)");
2187                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2188                                         Unindent ();
2189                                         doNullCheck = false;
2190                                 }
2191                                 else {
2192                                         WriteLine ("throw CreateReadOnlyCollectionException (" + GetLiteral (typeMap.TypeData.CSharpFullName) + ");");
2193                                         return list;
2194                                 }
2195                         }
2196                                 
2197                         WriteLineInd ("if (Reader.IsEmptyElement) {");
2198                         WriteLine ("Reader.Skip();");
2199                         if (listType.IsArray)
2200                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", 0, " + GetTypeOf(listType.GetElementType()) + ", false);");
2201
2202                         Unindent ();
2203                         WriteLineInd ("} else {");
2204
2205                         string index = GetNumTempVar ();
2206                         WriteLine ("int " + index + " = 0;");
2207                         WriteLine ("Reader.ReadStartElement();");
2208                         WriteLine ("Reader.MoveToContent();");
2209                         WriteLine ("");
2210
2211                         WriteLine ("while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) ");
2212                         WriteLineInd ("{");
2213                         WriteLine ("if (Reader.NodeType == System.Xml.XmlNodeType.Element) ");
2214                         WriteLineInd ("{");
2215
2216                         bool first = true;
2217                         foreach (XmlTypeMapElementInfo elemInfo in listMap.ItemInfo)
2218                         {
2219                                 WriteLineInd ((first?"":"else ") + "if (Reader.LocalName == " + GetLiteral (elemInfo.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (elemInfo.Namespace) + ") {");
2220                                 GenerateAddListValue (typeMap.TypeData, list, index, GenerateReadObjectElement (elemInfo), false);
2221                                 WriteLine (index + "++;");
2222                                 WriteLineUni ("}");
2223                                 first = false;
2224                         }
2225                         if (!first) WriteLine ("else UnknownNode (null);");
2226                         else WriteLine ("UnknownNode (null);");
2227                         
2228                         WriteLineUni ("}");
2229                         WriteLine ("else UnknownNode (null);");
2230                         WriteLine ("");
2231                         WriteLine ("Reader.MoveToContent();");
2232                         WriteLineUni ("}");
2233                         
2234                         WriteLine ("ReadEndElement();");
2235
2236                         if (listType.IsArray)
2237                                 WriteLine (list + " = (" + typeMap.TypeData.CSharpFullName + ") ShrinkArray (" + list + ", " + index + ", " + GetTypeOf(listType.GetElementType()) + ", false);");
2238
2239                         WriteLineUni ("}");
2240                         if (doNullCheck)
2241                                 WriteLineUni ("}");
2242
2243                         return list;
2244                 }
2245
2246                 string GenerateReadListString (XmlTypeMapping typeMap, string values)
2247                 {
2248                         Type listType = typeMap.TypeData.Type;
2249                         ListMap listMap = (ListMap)typeMap.ObjectMap;
2250                         string itemType = ToCSharpFullName (listType.GetElementType());
2251                         
2252                         string list = GetObTempVar ();
2253                         WriteLine (itemType + "[] " + list + ";");
2254                         
2255                         string var = GetStrTempVar ();
2256                         WriteLine ("string " + var + " = " + values + ".Trim();");
2257                         WriteLineInd ("if (" + var + " != string.Empty) {");
2258                         
2259                         string valueArray = GetObTempVar ();
2260                         WriteLine ("string[] " + valueArray + " = " + var + ".Split (' ');");
2261                         
2262                         WriteLine (list + " = new " + GetArrayDeclaration (listType, valueArray + ".Length") + ";");
2263                         
2264                         XmlTypeMapElementInfo info = (XmlTypeMapElementInfo)listMap.ItemInfo[0];
2265
2266                         string index = GetNumTempVar ();
2267                         WriteLineInd ("for (int " + index + " = 0; " + index + " < " + valueArray + ".Length; " + index + "++)");
2268                         WriteLine (list + "[" + index + "] = " + GenerateGetValueFromXmlString (valueArray + "[" + index + "]", info.TypeData, info.MappedType) + ";");
2269                         Unindent ();
2270                         WriteLineUni ("}");
2271                         WriteLine ("else");
2272                         WriteLine ("\t" + list + " = new " + GetArrayDeclaration (listType, "0") + ";");
2273                         
2274                         return list;
2275                 }
2276                 
2277                 string GetArrayDeclaration (Type type, string length)
2278                 {
2279                         Type t = type.GetElementType();
2280                         System.Text.StringBuilder sb = new System.Text.StringBuilder ();
2281                         sb.Append ('[').Append (length).Append (']');
2282                         while (t.IsArray) {
2283                                 sb.Append ("[]");
2284                                 t = t.GetElementType();
2285                         }
2286                         sb.Insert (0, ToCSharpFullName (t));
2287                         return sb.ToString ();
2288                 }
2289
2290                 void GenerateAddListValue (TypeData listType, string list, string index, string value, bool canCreateInstance)
2291                 {
2292                         Type type = listType.Type;
2293                         if (type.IsArray)
2294                         {
2295                                 WriteLine (list + " = (" + ToCSharpFullName (type) + ") EnsureArrayIndex (" + list + ", " + index + ", " + GetTypeOf(type.GetElementType()) + ");");
2296                                 WriteLine (list + "[" + index + "] = " + value + ";");
2297                         }
2298                         else    // Must be IEnumerable
2299                         {
2300                                 WriteLine ("if (((object)" + list + ") == null)");
2301                                 if (canCreateInstance) 
2302                                         WriteLine ("\t" + list + String.Format (" = ({0}) Activator.CreateInstance(typeof({0}), true);", listType.CSharpFullName));
2303                                 else 
2304                                         WriteLine ("\tthrow CreateReadOnlyCollectionException (" + GetLiteral (listType.CSharpFullName) + ");");
2305                                 
2306                                 WriteLine (list + ".Add (" + value + ");");
2307                         }
2308                 }
2309
2310                 string GenerateCreateList (Type listType)
2311                 {
2312                         if (listType.IsArray)
2313                                 return "(" + ToCSharpFullName (listType) + ") EnsureArrayIndex (null, 0, " + GetTypeOf(listType.GetElementType()) + ")";
2314                         else
2315                                 return "new " + ToCSharpFullName (listType) + "()";
2316                 }
2317                 
2318                 string GenerateInitializeList (TypeData listType)
2319                 {
2320                         if (listType.Type.IsArray)
2321                                 return "null";
2322                         else
2323                                 return "new " + listType.CSharpFullName + "()";
2324                 }
2325                 
2326                 void GenerateFillerCallbacks ()
2327                 {
2328                         foreach (TypeData td in _listsToFill)
2329                         {
2330                                 string metName = GetFillListName (td);
2331                                 WriteLine ("void " + metName + " (object list, object source)");
2332                                 WriteLineInd ("{");
2333                                 WriteLine ("if (((object)list) == null) throw CreateReadOnlyCollectionException (" + GetLiteral (td.CSharpFullName) + ");");
2334                                 WriteLine ("");
2335
2336                                 WriteLine (td.CSharpFullName + " dest = (" + td.CSharpFullName + ") list;");
2337                                 WriteLine ("foreach (object ob in (IEnumerable)source)");
2338                                 WriteLine ("\tdest.Add (" + GetCast (td.ListItemTypeData, "ob") + ");");
2339                                 WriteLineUni ("}");
2340                                 WriteLine ("");
2341                         }
2342                 }
2343
2344                 void GenerateReadXmlNodeElement (XmlTypeMapping typeMap, string isNullable)
2345                 {
2346                         WriteLine ("return " + GetReadXmlNode (typeMap.TypeData, false) + ";");
2347                 }
2348
2349                 void GenerateReadPrimitiveElement (XmlTypeMapping typeMap, string isNullable)
2350                 {
2351                         WriteLine ("XmlQualifiedName t = GetXsiType();");
2352                         WriteLine ("if (t == null) t = new XmlQualifiedName (" + GetLiteral(typeMap.XmlType) + ", " + GetLiteral(typeMap.Namespace) + ");");
2353                         WriteLine ("return " + GetCast (typeMap.TypeData, "ReadTypedPrimitive (t)") + ";");
2354                 }
2355
2356                 void GenerateReadEnumElement (XmlTypeMapping typeMap, string isNullable)
2357                 {
2358                         WriteLine ("Reader.ReadStartElement ();");
2359                         WriteLine (typeMap.TypeData.CSharpFullName + " res = " + GenerateGetEnumValue (typeMap, "Reader.ReadString()") + ";");
2360                         WriteLineInd ("if (Reader.NodeType != XmlNodeType.None)");
2361                         WriteLineUni ("Reader.ReadEndElement ();");
2362                         WriteLine ("return res;");
2363                 }
2364
2365                 string GenerateGetEnumValue (XmlTypeMapping typeMap, string val)
2366                 {
2367                         return GetGetEnumValueName (typeMap) + " (" + val + ")";
2368                 }
2369                 
2370                 void GenerateGetEnumValue (XmlTypeMapping typeMap)
2371                 {
2372                         string metName = GetGetEnumValueName (typeMap);
2373                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2374
2375                         if (map.IsFlags)
2376                         {
2377                                 string switchMethod =  metName + "_Switch";
2378                                 WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2379                                 WriteLineInd ("{");
2380                                 WriteLine ("xmlName = xmlName.Trim();");
2381                                 WriteLine ("if (xmlName.Length == 0) return (" + typeMap.TypeData.CSharpFullName + ")0;");
2382                                 WriteLine (typeMap.TypeData.CSharpFullName + " sb = (" + typeMap.TypeData.CSharpFullName + ")0;");
2383                                 WriteLine ("string[] enumNames = xmlName.Split (null);");
2384                                 WriteLine ("foreach (string name in enumNames)");
2385                                 WriteLineInd ("{");
2386                                 WriteLine ("if (name == string.Empty) continue;");
2387                                 WriteLine ("sb |= " + switchMethod + " (name); ");
2388                                 WriteLineUni ("}");
2389                                 WriteLine ("return sb;");
2390                                 WriteLineUni ("}");
2391                                 WriteLine ("");
2392                                 metName = switchMethod;
2393                         }
2394
2395                         WriteLine (typeMap.TypeData.CSharpFullName + " " + metName + " (string xmlName)");
2396                         WriteLineInd ("{");
2397                         GenerateGetSingleEnumValue (typeMap, "xmlName");
2398                         WriteLineUni ("}");
2399                         WriteLine ("");
2400                 }
2401                 
2402                 void GenerateGetSingleEnumValue (XmlTypeMapping typeMap, string val)
2403                 {
2404                         EnumMap map = (EnumMap) typeMap.ObjectMap;
2405                         WriteLine ("switch (" + val + ")");
2406                         WriteLineInd ("{");
2407                         foreach (EnumMap.EnumMapMember mem in map.Members)
2408                         {
2409                                 WriteLine ("case " + GetLiteral (mem.XmlName) + ": return " + typeMap.TypeData.CSharpFullName + "." + mem.EnumName + ";");
2410                         }
2411                         WriteLineInd ("default:");
2412                         WriteLine ("throw CreateUnknownConstantException (" + val + ", typeof(" + typeMap.TypeData.CSharpFullName + "));");
2413                         Unindent ();
2414                         WriteLineUni ("}");
2415                 }
2416                 
2417                 void GenerateReadXmlSerializableElement (XmlTypeMapping typeMap, string isNullable)
2418                 {
2419                         WriteLine ("Reader.MoveToContent ();");
2420                         WriteLine ("if (Reader.NodeType == XmlNodeType.Element)");
2421                         WriteLineInd ("{");
2422                         WriteLine ("if (Reader.LocalName == " + GetLiteral (typeMap.ElementName) + " && Reader.NamespaceURI == " + GetLiteral (typeMap.Namespace) + ")");
2423                         WriteLine (String.Format ("\treturn ReadSerializable (({0}) Activator.CreateInstance(typeof({0}), true));", typeMap.TypeData.CSharpFullName));
2424                         WriteLine ("else");
2425                         WriteLine ("\tthrow CreateUnknownNodeException ();");
2426                         WriteLineUni ("}");
2427                         WriteLine ("else UnknownNode (null);");
2428                         WriteLine ("");
2429                         WriteLine ("return null;");
2430                 }
2431
2432                 void GenerateReadInitCallbacks ()
2433                 {
2434                         WriteLine ("protected override void InitCallbacks ()");
2435                         WriteLineInd ("{");
2436
2437                         if (_format == SerializationFormat.Encoded)
2438                         {
2439                                 foreach (XmlMapping xmap in _mapsToGenerate)  
2440                                 {
2441                                         XmlTypeMapping map = xmap as XmlTypeMapping;
2442                                         if (map == null) continue;
2443                                         if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
2444                                                 WriteMetCall ("AddReadCallback", GetLiteral (map.XmlType), GetLiteral(map.Namespace), GetTypeOf(map.TypeData.Type), "new XmlSerializationReadCallback (" + GetReadObjectName (map) + ")");
2445                                 }
2446                         }
2447                         
2448                         WriteLineUni ("}");
2449                         WriteLine ("");
2450
2451                         WriteLine ("protected override void InitIDs ()");
2452                         WriteLine ("{");
2453                         WriteLine ("}");
2454                         WriteLine ("");
2455                 }
2456
2457                 void GenerateFixupCallbacks ()
2458                 {
2459                         foreach (XmlMapping map in _fixupCallbacks)
2460                         {
2461                                 bool isList = map is XmlMembersMapping;
2462                                 string tname = !isList ? ((XmlTypeMapping)map).TypeData.CSharpFullName : "object[]";
2463                                 WriteLine ("void " + GetFixupCallbackName (map) + " (object obfixup)");
2464                                 WriteLineInd ("{");                                     
2465                                 WriteLine ("Fixup fixup = (Fixup)obfixup;");
2466                                 WriteLine (tname + " source = (" + tname + ") fixup.Source;");
2467                                 WriteLine ("string[] ids = fixup.Ids;");
2468                                 WriteLine ("");
2469
2470                                 ClassMap cmap = (ClassMap)map.ObjectMap;
2471                                 ICollection members = cmap.ElementMembers;
2472                                 if (members != null) {
2473                                         foreach (XmlTypeMapMember member in members)
2474                                         {
2475                                                 WriteLineInd ("if (ids[" + member.Index + "] != null)");
2476                                                 string val = "GetTarget(ids[" + member.Index + "])";
2477                                                 if (!isList) val = GetCast (member.TypeData, val);
2478                                                 GenerateSetMemberValue (member, "source", val, isList);
2479                                                 Unindent ();
2480                                         }
2481                                 }
2482                                 WriteLineUni ("}");
2483                                 WriteLine ("");
2484                         }
2485                 }
2486
2487                 string GetReadXmlNode (TypeData type, bool wrapped)
2488                 {
2489                         if (type.Type == typeof (XmlDocument))
2490                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlDocument)), "ReadXmlDocument (" + GetLiteral(wrapped) + ")");
2491                         else
2492                                 return GetCast (type, TypeTranslator.GetTypeData (typeof(XmlNode)), "ReadXmlNode (" + GetLiteral(wrapped) + ")");
2493                 }
2494                 
2495                 #endregion
2496                 
2497                 #region Helper methods
2498
2499                 //*******************************************************
2500                 // Helper methods
2501                 //
2502                 
2503                 ArrayList _listsToFill = new ArrayList ();
2504                 Hashtable _hookVariables;
2505                 Stack _hookContexts;
2506                 Stack _hookOpenHooks;
2507                 
2508                 class HookInfo {
2509                         public HookType HookType;
2510                         public Type Type;
2511                         public string Member;
2512                         public HookDir Direction;
2513                 }
2514
2515                 void InitHooks ()
2516                 {
2517                         _hookContexts = new Stack ();
2518                         _hookOpenHooks = new Stack ();
2519                         _hookVariables = new Hashtable ();
2520                 }
2521                 
2522                 void PushHookContext ()
2523                 {
2524                         _hookContexts.Push (_hookVariables);
2525                         _hookVariables = (Hashtable) _hookVariables.Clone ();
2526                 }
2527                 
2528                 void PopHookContext ()
2529                 {
2530                         _hookVariables = (Hashtable) _hookContexts.Pop ();
2531                 }
2532                 
2533                 void SetHookVar (string var, string value)
2534                 {
2535                         _hookVariables [var] = value;
2536                 }
2537
2538                 bool GenerateReadHook (HookType hookType, Type type)
2539                 {
2540                         return GenerateHook (hookType, HookDir.Read, type, null);
2541                 }
2542
2543                 bool GenerateWriteHook (HookType hookType, Type type)
2544                 {
2545                         return GenerateHook (hookType, HookDir.Write, type, null);
2546                 }
2547                 
2548                 bool GenerateWriteMemberHook (Type type, XmlTypeMapMember member)
2549                 {
2550                         SetHookVar ("$MEMBER", member.Name);
2551                         return GenerateHook (HookType.member, HookDir.Write, type, member.Name);
2552                 }
2553                 
2554                 bool GenerateReadMemberHook (Type type, XmlTypeMapMember member)
2555                 {
2556                         SetHookVar ("$MEMBER", member.Name);
2557                         return GenerateHook (HookType.member, HookDir.Read, type, member.Name);
2558                 }
2559                 
2560                 bool GenerateReadArrayMemberHook (Type type, XmlTypeMapMember member, string index)
2561                 {
2562                         SetHookVar ("$INDEX", index);
2563                         return GenerateReadMemberHook (type, member);
2564                 }
2565         
2566                 bool MemberHasReadReplaceHook (Type type, XmlTypeMapMember member)
2567                 {
2568                         if (_config == null) return false;
2569                         return _config.GetHooks (HookType.member, HookDir.Read, HookAction.Replace, type, member.Name).Count > 0;
2570                 }
2571                 
2572                 bool GenerateHook (HookType hookType, HookDir dir, Type type, string member)
2573                 {
2574                         GenerateHooks (hookType, dir, type, null, HookAction.InsertBefore);
2575                         if (GenerateHooks (hookType, dir, type, null, HookAction.Replace))
2576                         {
2577                                 GenerateHooks (hookType, dir, type, null, HookAction.InsertAfter);
2578                                 return true;
2579                         }
2580                         else
2581                         {
2582                                 HookInfo hi = new HookInfo ();
2583                                 hi.HookType = hookType;
2584                                 hi.Type = type;
2585                                 hi.Member = member;
2586                                 hi.Direction = dir;
2587                                 _hookOpenHooks.Push (hi);
2588                                 return false;
2589                         }
2590                 }
2591                 
2592                 void GenerateEndHook ()
2593                 {
2594                         HookInfo hi = (HookInfo) _hookOpenHooks.Pop();
2595                         GenerateHooks (hi.HookType, hi.Direction, hi.Type, hi.Member, HookAction.InsertAfter);
2596                 }
2597                 
2598                 bool GenerateHooks (HookType hookType, HookDir dir, Type type, string member, HookAction action)
2599                 {
2600                         if (_config == null) return false;
2601                         ArrayList hooks = _config.GetHooks (hookType, dir, action, type, null);
2602                         if (hooks.Count == 0) return false;                     
2603                         foreach (Hook hook in hooks)
2604                         {
2605                                 string code = hook.GetCode (action);
2606                                 foreach (DictionaryEntry de in _hookVariables)
2607                                         code = code.Replace ((string)de.Key, (string)de.Value);
2608                                 WriteMultilineCode (code);
2609                         }
2610                         return true;
2611                 }
2612                 
2613                 string GetRootTypeName ()
2614                 {
2615                         if (_typeMap is XmlTypeMapping) return ((XmlTypeMapping)_typeMap).TypeData.CSharpFullName;
2616                         else return "object[]";
2617                 }
2618
2619                 string GetNumTempVar ()
2620                 {
2621                         return "n" + (_tempVarId++);
2622                 }
2623                 
2624                 string GetObTempVar ()
2625                 {
2626                         return "o" + (_tempVarId++);
2627                 }
2628                 
2629                 string GetStrTempVar ()
2630                 {
2631                         return "s" + (_tempVarId++);
2632                 }
2633                 
2634                 string GetBoolTempVar ()
2635                 {
2636                         return "b" + (_tempVarId++);
2637                 }
2638                 
2639                 string GetUniqueName (string uniqueGroup, object ob, string name)
2640                 {
2641                         name = name.Replace ("[]","_array");
2642                         Hashtable names = (Hashtable) _uniqueNames [uniqueGroup];
2643                         if (names == null) {
2644                                 names = new Hashtable ();
2645                                 _uniqueNames [uniqueGroup] = names; 
2646                         }
2647                         
2648                         string res = (string) names [ob];
2649                         if (res != null) return res;
2650
2651                         foreach (string n in names.Values)
2652                                 if (n == name) return GetUniqueName (uniqueGroup, ob, name + (_methodId++));
2653                                 
2654                         names [ob] = name;
2655                         return name;
2656                 }
2657                 
2658                 void RegisterReferencingMap (XmlTypeMapping typeMap)
2659                 {
2660                         if (typeMap != null && !_mapsToGenerate.Contains (typeMap))
2661                                 _mapsToGenerate.Add (typeMap);
2662                 }
2663                 
2664                 string GetWriteObjectName (XmlTypeMapping typeMap)
2665                 {
2666                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2667                         return GetUniqueName ("rw", typeMap, "WriteObject_" + typeMap.XmlType);
2668                 }
2669                 
2670                 string GetReadObjectName (XmlTypeMapping typeMap)
2671                 {
2672                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2673                         return GetUniqueName ("rr", typeMap, "ReadObject_" + typeMap.XmlType);
2674                 }
2675                 
2676                 string GetGetEnumValueName (XmlTypeMapping typeMap)
2677                 {
2678                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2679                         return GetUniqueName ("ge", typeMap, "GetEnumValue_" + typeMap.XmlType);
2680                 }
2681
2682                 string GetWriteObjectCallbackName (XmlTypeMapping typeMap)
2683                 {
2684                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2685                         return GetUniqueName ("wc", typeMap, "WriteCallback_" + typeMap.XmlType);
2686                 }
2687                 
2688                 string GetFixupCallbackName (XmlMapping typeMap)
2689                 {
2690                         if (!_mapsToGenerate.Contains (typeMap)) _mapsToGenerate.Add (typeMap);
2691                         
2692                         if (typeMap is XmlTypeMapping)
2693                                 return GetUniqueName ("fc", typeMap, "FixupCallback_" + ((XmlTypeMapping)typeMap).XmlType);
2694                         else
2695                                 return GetUniqueName ("fc", typeMap, "FixupCallback__Message");
2696                 }
2697                 
2698                 string GetUniqueClassName (string s)
2699                 {
2700                         return classNames.AddUnique (s, null);
2701                 }
2702                 
2703                 string GetReadObjectCall (XmlTypeMapping typeMap, string isNullable, string checkType)
2704                 {
2705                         if (_format == SerializationFormat.Literal)
2706                                 return GetReadObjectName (typeMap) + " (" + isNullable + ", " + checkType + ")";
2707                         else
2708                                 return GetCast (typeMap.TypeData, GetReadObjectName (typeMap) + " ()");
2709                 }
2710                 
2711                 string GetFillListName (TypeData td)
2712                 {
2713                         if (!_listsToFill.Contains (td)) _listsToFill.Add (td);
2714                         return GetUniqueName ("fl", td, "Fill_" + CodeIdentifier.MakeValid (td.CSharpName));
2715                 }
2716                 
2717                 string GetCast (TypeData td, TypeData tdval, string val)
2718                 {
2719                         if (td.CSharpFullName == tdval.CSharpFullName) return val;
2720                         else return GetCast (td, val);
2721                 }
2722
2723                 string GetCast (TypeData td, string val)
2724                 {
2725                         return "((" + td.CSharpFullName + ") " + val + ")";
2726                 }
2727
2728                 string GetCast (Type td, string val)
2729                 {
2730                         return "((" + ToCSharpFullName (td) + ") " + val + ")";
2731                 }
2732
2733                 string GetTypeOf (TypeData td)
2734                 {
2735                         return "typeof(" + td.CSharpFullName + ")";
2736                 }
2737                 
2738                 string GetTypeOf (Type td)
2739                 {
2740                         return "typeof(" + ToCSharpFullName (td) + ")";
2741                 }
2742                 
2743                 string GetLiteral (object ob)
2744                 {
2745                         if (ob == null) return "null";
2746                         if (ob is string) return "\"" + ob.ToString().Replace("\"","\"\"") + "\"";
2747                         if (ob is bool) return ((bool)ob) ? "true" : "false";
2748                         if (ob is XmlQualifiedName) {
2749                                 XmlQualifiedName qn = (XmlQualifiedName)ob;
2750                                 return "new XmlQualifiedName (" + GetLiteral(qn.Name) + "," + GetLiteral(qn.Namespace) + ")";
2751                         }
2752                         if (ob is Enum) {
2753                                 string typeName = ToCSharpFullName (ob.GetType ());
2754                                 StringBuilder sb = new StringBuilder ();
2755                                 string namedValue = Enum.Format (ob.GetType (), ob, "g");
2756                                 string[] names = namedValue.Split (',');
2757                                 foreach (string name in names) {
2758                                         // individual named constants can be seperated by a comma
2759                                         // combined with some additional whitespace characters
2760                                         string cleanName = name.Trim ();
2761                                         if (cleanName.Length == 0)
2762                                                 continue;
2763
2764                                         if (sb.Length > 0)
2765                                                 sb.Append (" | ");
2766
2767                                         sb.Append (typeName);
2768                                         sb.Append ('.');
2769                                         sb.Append (cleanName);
2770                                 }
2771                                 return sb.ToString ();
2772                         }
2773
2774                         return (ob is IFormattable) ? ((IFormattable) ob).ToString (null, CultureInfo.InvariantCulture) : ob.ToString ();
2775                 }
2776                 
2777                 void WriteLineInd (string code)
2778                 {
2779                         WriteLine (code);
2780                         _indent++;
2781                 }
2782                 
2783                 void WriteLineUni (string code)
2784                 {
2785                         if (_indent > 0) _indent--;
2786                         WriteLine (code);
2787                 }
2788
2789                 void Write (string code)
2790                 {
2791                         if (code.Length > 0) 
2792                                 _writer.Write (new String ('\t', _indent));
2793                         _writer.Write (code);
2794                 }
2795
2796                 void WriteUni (string code)
2797                 {
2798                         if (_indent > 0) _indent--;
2799                         _writer.Write (code);
2800                         _writer.WriteLine (string.Empty);
2801                 }
2802
2803                 void WriteLine (string code)
2804                 {
2805                         if (code.Length > 0)
2806                                 _writer.Write (new String ('\t',_indent));
2807                         _writer.WriteLine (code);
2808                 }
2809                 
2810                 void WriteMultilineCode (string code)
2811                 {
2812                         string tabs = new string ('\t',_indent);
2813                         code = code.Replace ("\r","");
2814                         code = code.Replace ("\t","");
2815                         while (code.StartsWith ("\n")) code = code.Substring (1);
2816                         while (code.EndsWith ("\n")) code = code.Substring (0, code.Length - 1);
2817                         code = code.Replace ("\n", "\n" + tabs);
2818                         WriteLine (code);
2819                 }
2820                 
2821                 string Params (params string[] pars)
2822                 {
2823                         string res = "";
2824                         foreach (string p in pars)
2825                         {
2826                                 if (res != "") res += ", ";
2827                                 res += p;
2828                         }
2829                         return res;
2830                 }
2831                 
2832                 void WriteMetCall (string method, params string[] pars)
2833                 {
2834                         WriteLine (method + " (" + Params (pars) + ");");
2835                 }
2836                 
2837                 void Unindent ()
2838                 {
2839                         _indent--;
2840                 }
2841
2842                 #endregion
2843
2844         }
2845         
2846         internal class GenerationResult
2847         {
2848                 public XmlMapping Mapping;
2849                 public string ReaderClassName;
2850                 public string ReadMethodName;
2851                 public string WriterClassName;
2852                 public string WriteMethodName;
2853                 public string Namespace;
2854                 public string SerializerClassName;
2855                 public string BaseSerializerClassName;
2856                 public string ImplementationClassName;
2857         }
2858         
2859 }