Merge pull request #309 from i59/patch-1
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializer.cs
1 //
2 // XmlSerializer.cs: 
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Threading;
33 using System.Collections;
34 using System.Globalization;
35 using System.IO;
36 using System.Reflection;
37 using System.Xml;
38 using System.Xml.Schema;
39 using System.Text;
40 #if !TARGET_JVM && !NET_2_1
41 using System.CodeDom;
42 using System.CodeDom.Compiler;
43 using Microsoft.CSharp;
44 #endif
45 using System.Configuration;
46 using System.Security.Policy;
47
48 namespace System.Xml.Serialization
49 {
50
51         public class XmlSerializer
52         {
53                 internal const string WsdlNamespace = "http://schemas.xmlsoap.org/wsdl/";
54                 internal const string EncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
55                 internal const string WsdlTypesNamespace = "http://microsoft.com/wsdl/types/";
56                 static int generationThreshold;
57                 static bool backgroundGeneration = true;
58                 static bool deleteTempFiles = true;
59                 static bool generatorFallback = true;
60
61                 bool customSerializer;
62                 XmlMapping typeMapping;
63                 
64                 SerializerData serializerData;
65                 
66                 static Hashtable serializerTypes = new Hashtable ();
67                 
68                 internal class SerializerData
69                 {
70                         public int UsageCount;
71                         public Type ReaderType;
72                         public MethodInfo ReaderMethod;
73                         public Type WriterType;
74                         public MethodInfo WriterMethod;
75                         public GenerationBatch Batch;
76                         public XmlSerializerImplementation Implementation = null;
77                         
78                         public XmlSerializationReader CreateReader () {
79                                 if (ReaderType != null)
80                                         return (XmlSerializationReader) Activator.CreateInstance (ReaderType);
81                                 else if (Implementation != null)
82                                         return Implementation.Reader;
83                                 else
84                                         return null;
85                         }
86                         
87                         public XmlSerializationWriter CreateWriter () {
88                                 if (WriterType != null)
89                                         return (XmlSerializationWriter) Activator.CreateInstance (WriterType);
90                                 else if (Implementation != null)
91                                         return Implementation.Writer;
92                                 else
93                                         return null;
94                         }
95                 }
96                 
97                 internal class GenerationBatch
98                 {
99                         public bool Done;
100                         public XmlMapping[] Maps;
101                         public SerializerData[] Datas;
102                 }
103                 
104                 static XmlSerializer ()
105                 {
106                         // The following options are available:
107                         // MONO_XMLSERIALIZER_DEBUG: when set to something != "no", it will
108                         //       it will print the name of the generated file, and it won't
109                         //       be deleted.
110                         // MONO_XMLSERIALIZER_THS: The code generator threshold. It can be:
111                         //       no: does not use the generator, always the interpreter.
112                         //       0: always use the generator, wait until the generation is done.
113                         //       any number: use the interpreted serializer until the specified
114                         //       number of serializations is reached. At this point the generation
115                         //       of the serializer will start in the background. The interpreter
116                         //       will be used while the serializer is being generated.
117                         //
118                         //       XmlSerializer will fall back to the interpreted serializer if
119                         //       the code generation somehow fails. This can be avoided for
120                         //       debugging pourposes by adding the "nofallback" option.
121                         //       For example: MONO_XMLSERIALIZER_THS=0,nofallback
122                         
123 #if TARGET_JVM || NET_2_1
124                         string db = null;
125                         string th = null;
126                         generationThreshold = -1;
127                         backgroundGeneration = false;
128 #else
129                         string db = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_DEBUG");
130                         string th = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_THS");
131                         
132                         if (th == null) {
133                                 generationThreshold = 50;
134                                 backgroundGeneration = true;
135                         } else {
136                                 int i = th.IndexOf (',');
137                                 if (i != -1) {
138                                         if (th.Substring (i+1) == "nofallback")
139                                                 generatorFallback = false;
140                                         th = th.Substring (0, i);
141                                 }
142                                 
143                                 if (th.ToLower(CultureInfo.InvariantCulture) == "no") 
144                                         generationThreshold = -1;
145                                 else {
146                                         generationThreshold = int.Parse (th, CultureInfo.InvariantCulture);
147                                         backgroundGeneration = (generationThreshold != 0);
148                                         if (generationThreshold < 1) generationThreshold = 1;
149                                 }
150                         }
151 #endif
152                         deleteTempFiles = (db == null || db == "no");
153 #if !NET_2_1
154                         IDictionary table = (IDictionary) ConfigurationSettings.GetConfig("system.diagnostics");
155                         if (table != null) 
156                         {
157                                 table = (IDictionary) table["switches"];
158                                 if (table != null) 
159                                 {
160                                         string val = (string) table ["XmlSerialization.Compilation"];
161                                         if (val == "1") deleteTempFiles = false;
162                                 }
163                         }
164 #endif
165                 }
166
167 #region Constructors
168
169                 protected XmlSerializer ()
170                 {
171                         customSerializer = true;
172                 }
173
174                 public XmlSerializer (Type type)
175                         : this (type, null, null, null, null)
176                 {
177                 }
178
179                 public XmlSerializer (XmlTypeMapping xmlTypeMapping)
180                 {
181                         typeMapping = xmlTypeMapping;
182                 }
183
184                 internal XmlSerializer (XmlMapping mapping, SerializerData data)
185                 {
186                         typeMapping = mapping;
187                         serializerData = data;
188                 }
189
190                 public XmlSerializer (Type type, string defaultNamespace)
191                         : this (type, null, null, null, defaultNamespace)
192                 {
193                 }
194
195                 public XmlSerializer (Type type, Type[] extraTypes)
196                         : this (type, null, extraTypes, null, null)
197                 {
198                 }
199
200                 public XmlSerializer (Type type, XmlAttributeOverrides overrides)
201                         : this (type, overrides, null, null, null)
202                 {
203                 }
204
205                 public XmlSerializer (Type type, XmlRootAttribute root)
206                         : this (type, null, null, root, null)
207                 {
208                 }
209
210                 public XmlSerializer (Type type,
211                         XmlAttributeOverrides overrides,
212                         Type [] extraTypes,
213                         XmlRootAttribute root,
214                         string defaultNamespace)
215                 {
216                         if (type == null)
217                                 throw new ArgumentNullException ("type");
218
219                         XmlReflectionImporter importer = new XmlReflectionImporter (overrides, defaultNamespace);
220
221                         if (extraTypes != null) 
222                         {
223                                 foreach (Type intype in extraTypes)
224                                         importer.IncludeType (intype);
225                         }
226
227                         typeMapping = importer.ImportTypeMapping (type, root, defaultNamespace);
228                 }
229                 
230                 internal XmlMapping Mapping
231                 {
232                         get { return typeMapping; }
233                 }
234
235 #if NET_2_0
236
237                 [MonoTODO]
238                 public XmlSerializer (Type type,
239                         XmlAttributeOverrides overrides,
240                         Type [] extraTypes,
241                         XmlRootAttribute root,
242                         string defaultNamespace,
243                         string location,
244                         Evidence evidence)
245                 {
246                 }
247 #endif
248
249 #endregion // Constructors
250
251 #region Events
252                 private UnreferencedObjectEventHandler onUnreferencedObject;
253 #if !MOONLIGHT
254                 private XmlAttributeEventHandler onUnknownAttribute;
255                 private XmlElementEventHandler onUnknownElement;
256                 private XmlNodeEventHandler onUnknownNode;
257
258                 public event XmlAttributeEventHandler UnknownAttribute 
259                 {
260                         add { onUnknownAttribute += value; } remove { onUnknownAttribute -= value; }
261                 }
262
263                 public event XmlElementEventHandler UnknownElement 
264                 {
265                         add { onUnknownElement += value; } remove { onUnknownElement -= value; }
266                 }
267
268                 public event XmlNodeEventHandler UnknownNode 
269                 {
270                         add { onUnknownNode += value; } remove { onUnknownNode -= value; }
271                 }
272
273
274                 internal virtual void OnUnknownAttribute (XmlAttributeEventArgs e) 
275                 {
276                         if (onUnknownAttribute != null) onUnknownAttribute(this, e);
277                 }
278
279                 internal virtual void OnUnknownElement (XmlElementEventArgs e) 
280                 {
281                         if (onUnknownElement != null) onUnknownElement(this, e);
282                 }
283
284                 internal virtual void OnUnknownNode (XmlNodeEventArgs e) 
285                 {
286                         if (onUnknownNode != null) onUnknownNode(this, e);
287                 }
288
289 #endif
290
291                 internal virtual void OnUnreferencedObject (UnreferencedObjectEventArgs e) 
292                 {
293                         if (onUnreferencedObject != null) onUnreferencedObject(this, e);
294                 }
295
296                 public event UnreferencedObjectEventHandler UnreferencedObject 
297                 {
298                         add { onUnreferencedObject += value; } remove { onUnreferencedObject -= value; }
299                 }
300
301 #endregion // Events
302
303 #region Methods
304
305                 public virtual bool CanDeserialize (XmlReader xmlReader)
306                 {
307                         xmlReader.MoveToContent ();
308                         if (typeMapping is XmlMembersMapping) 
309                                 return true;
310                         else
311                                 return ((XmlTypeMapping)typeMapping).ElementName == xmlReader.LocalName;
312                 }
313
314                 protected virtual XmlSerializationReader CreateReader ()
315                 {
316                         // Must be implemented in derived class
317                         throw new NotImplementedException ();
318                 }
319
320                 protected virtual XmlSerializationWriter CreateWriter ()
321                 {
322                         // Must be implemented in derived class
323                         throw new NotImplementedException ();
324                 }
325
326                 public object Deserialize (Stream stream)
327                 {
328                         XmlTextReader xmlReader = new XmlTextReader(stream);
329                         xmlReader.Normalization = true;
330                         xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
331                         return Deserialize(xmlReader);
332                 }
333
334                 public object Deserialize (TextReader textReader)
335                 {
336                         XmlTextReader xmlReader = new XmlTextReader(textReader);
337                         xmlReader.Normalization = true;
338                         xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
339                         return Deserialize(xmlReader);
340                 }
341
342                 public object Deserialize (XmlReader xmlReader)
343                 {
344                         XmlSerializationReader xsReader;
345                         if (customSerializer)
346                                 xsReader = CreateReader ();
347                         else
348                                 xsReader = CreateReader (typeMapping);
349                                 
350                         xsReader.Initialize (xmlReader, this);
351                         return Deserialize (xsReader);
352                 }
353
354                 protected virtual object Deserialize (XmlSerializationReader reader)
355                 {
356                         if (customSerializer)
357                                 // Must be implemented in derived class
358                                 throw new NotImplementedException ();
359                         
360                         try {
361                                 if (reader is XmlSerializationReaderInterpreter)
362                                         return ((XmlSerializationReaderInterpreter) reader).ReadRoot ();
363                                 else {
364                                         try {
365                                                 return serializerData.ReaderMethod.Invoke (reader, null);
366                                         } catch (TargetInvocationException ex) {
367                                                 throw ex.InnerException;
368                                         }
369                                 }
370                         } catch (Exception ex) {
371                                 if (ex is InvalidOperationException || ex is InvalidCastException)
372                                         throw new InvalidOperationException ("There is an error in"
373                                                 + " XML document.", ex);
374                                 throw;
375                         }
376                 }
377
378                 public static XmlSerializer [] FromMappings (XmlMapping [] mappings)
379                 {
380                         XmlSerializer[] sers = new XmlSerializer [mappings.Length];
381                         SerializerData[] datas = new SerializerData [mappings.Length];
382                         GenerationBatch batch = new GenerationBatch ();
383                         batch.Maps = mappings;
384                         batch.Datas = datas;
385                         
386                         for (int n=0; n<mappings.Length; n++)
387                         {
388                                 if (mappings[n] != null)
389                                 {
390                                         SerializerData data = new SerializerData ();
391                                         data.Batch = batch;
392                                         sers[n] = new XmlSerializer (mappings[n], data);
393                                         datas[n] = data;
394                                 }
395                         }
396                         
397                         return sers;
398                 }
399
400                 public static XmlSerializer [] FromTypes (Type [] types)
401                 {
402                         XmlSerializer [] sers = new XmlSerializer [types.Length];
403                         for (int n=0; n<types.Length; n++)
404                                 sers[n] = new XmlSerializer (types[n]);
405                         return sers;
406                 }
407
408                 protected virtual void Serialize (object o, XmlSerializationWriter writer)
409                 {
410                         if (customSerializer)
411                                 // Must be implemented in derived class
412                                 throw new NotImplementedException ();
413                                 
414                         if (writer is XmlSerializationWriterInterpreter)
415                                 ((XmlSerializationWriterInterpreter)writer).WriteRoot (o);
416                         else {
417                                 try {
418                                         serializerData.WriterMethod.Invoke (writer, new object[] {o});
419                                 } catch (TargetInvocationException ex) {
420                                         throw ex.InnerException;
421                                 }
422                         }
423                 }
424
425 #if MOONLIGHT
426                 static Encoding DefaultEncoding = Encoding.UTF8;
427 #else
428                 static Encoding DefaultEncoding = Encoding.Default;
429 #endif
430
431                 public void Serialize (Stream stream, object o)
432                 {
433                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, DefaultEncoding);
434                         xmlWriter.Formatting = Formatting.Indented;
435                         Serialize (xmlWriter, o, null);
436                 }
437
438                 public void Serialize (TextWriter textWriter, object o)
439                 {
440                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
441                         xmlWriter.Formatting = Formatting.Indented;
442                         Serialize (xmlWriter, o, null);
443                 }
444
445                 public void Serialize (XmlWriter xmlWriter, object o)
446                 {
447                         Serialize (xmlWriter, o, null);
448                 }
449
450                 public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
451                 {
452                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, DefaultEncoding);
453                         xmlWriter.Formatting = Formatting.Indented;
454                         Serialize (xmlWriter, o, namespaces);
455                 }
456
457                 public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
458                 {
459                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
460                         xmlWriter.Formatting = Formatting.Indented;
461                         Serialize (xmlWriter, o, namespaces);
462                         xmlWriter.Flush();
463                 }
464
465                 public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces)
466                 {
467                         XmlSerializationWriter xsWriter;
468
469                         try {
470                                 if (customSerializer)
471                                         xsWriter = CreateWriter ();
472                                 else
473                                         xsWriter = CreateWriter (typeMapping);
474
475                                 if (namespaces == null || namespaces.Count == 0) {
476                                         namespaces = new XmlSerializerNamespaces ();
477 #if NET_2_0
478                                         namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
479                                         namespaces.Add ("xsd", XmlSchema.Namespace);
480 #else
481                                         namespaces.Add ("xsd", XmlSchema.Namespace);
482                                         namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
483 #endif
484                                 }
485
486                                 xsWriter.Initialize (xmlWriter, namespaces);
487                                 Serialize (o, xsWriter);
488                                 xmlWriter.Flush ();
489                         } catch (Exception ex) {
490                                 if (ex is TargetInvocationException)
491                                         ex = ex.InnerException;
492
493                                 if (ex is InvalidOperationException || ex is InvalidCastException)
494                                         throw new InvalidOperationException ("There was an error generating" +
495                                                 " the XML document.", ex);
496
497                                 throw;
498                         }
499                 }
500                 
501 #if !NET_2_1
502                 
503                 [MonoTODO]
504                 public object Deserialize (XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
505                 {
506                         throw new NotImplementedException ();
507                 }
508
509                 [MonoTODO]
510                 public object Deserialize (XmlReader xmlReader, string encodingStyle)
511                 {
512                         throw new NotImplementedException ();
513                 }
514
515                 [MonoTODO]
516                 public object Deserialize (XmlReader xmlReader, XmlDeserializationEvents events)
517                 {
518                         throw new NotImplementedException ();
519                 }
520                 
521                 [MonoTODO]
522                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Evidence evidence)
523                 {
524                         throw new NotImplementedException ();
525                 }
526
527                 [MonoTODO]
528                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Type type)
529                 {
530                         throw new NotImplementedException ();
531                 }
532
533 #if !TARGET_JVM && !MOBILE
534                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings)
535                 {
536                         return GenerateSerializer (types, mappings, null);
537                 }
538                 
539                 [MonoTODO]
540                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings, CompilerParameters parameters)
541                 {
542                         GenerationBatch batch = new GenerationBatch ();
543                         batch.Maps = mappings;
544                         batch.Datas = new SerializerData [mappings.Length];
545                         
546                         for (int n=0; n<mappings.Length; n++) {
547                                 SerializerData data = new SerializerData ();
548                                 data.Batch = batch;
549                                 batch.Datas [n] = data;
550                         }
551                         
552                         return GenerateSerializers (batch, parameters);
553                 }
554 #endif
555
556                 public static string GetXmlSerializerAssemblyName (Type type)
557                 {
558                         return type.Assembly.GetName().Name + ".XmlSerializers";
559                 }
560
561                 public static string GetXmlSerializerAssemblyName (Type type, string defaultNamespace)
562                 {
563                         return GetXmlSerializerAssemblyName (type) + "." + defaultNamespace.GetHashCode ();
564                 }
565                 
566                 [MonoTODO]
567                 public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle)
568                 {
569                         throw new NotImplementedException ();
570                 }
571
572                 [MonoNotSupported("")]
573                 public void Serialize (XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, string encodingStyle, string id)
574                 {
575                         throw new NotImplementedException ();
576                 }
577 #endif
578                 
579                 XmlSerializationWriter CreateWriter (XmlMapping typeMapping)
580                 {
581                         XmlSerializationWriter writer;
582                         
583                         lock (this) {
584                                 if (serializerData != null) {
585                                         lock (serializerData) {
586                                                 writer = serializerData.CreateWriter ();
587                                         }
588                                         if (writer != null) return writer;
589                                 }
590                         }
591                         
592 #if !NET_2_1
593                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
594                                 return new XmlSerializationWriterInterpreter (typeMapping);
595
596                         CheckGeneratedTypes (typeMapping);
597                         
598                         lock (this) {
599                                 lock (serializerData) {
600                                         writer = serializerData.CreateWriter ();
601                                 }
602                                 if (writer != null) return writer;
603                                 if (!generatorFallback)
604                                         throw new InvalidOperationException ("Error while generating serializer");
605                         }
606                         
607 #endif
608                         return new XmlSerializationWriterInterpreter (typeMapping);
609                 }
610                 
611                 XmlSerializationReader CreateReader (XmlMapping typeMapping)
612                 {
613 #if !NET_2_1
614                         XmlSerializationReader reader;
615                         
616                         lock (this) {
617                                 if (serializerData != null) {
618                                         lock (serializerData) {
619                                                 reader = serializerData.CreateReader ();
620                                         }
621                                         if (reader != null) return reader;
622                                 }
623                         }
624                         
625                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
626                                 return new XmlSerializationReaderInterpreter (typeMapping);
627
628                         CheckGeneratedTypes (typeMapping);
629                         
630                         lock (this) {
631                                 lock (serializerData) {
632                                         reader = serializerData.CreateReader ();
633                                 }
634                                 if (reader != null) return reader;
635                                 if (!generatorFallback)
636                                         throw new InvalidOperationException ("Error while generating serializer");
637                         }
638
639 #endif
640                         return new XmlSerializationReaderInterpreter (typeMapping);
641                 }
642                 
643 #if TARGET_JVM || NET_2_1
644                 void CheckGeneratedTypes (XmlMapping typeMapping)
645                 {
646                         throw new NotImplementedException();
647                 }
648                 void GenerateSerializersAsync (GenerationBatch batch)
649                 {
650                         throw new NotImplementedException();
651                 }
652                 void RunSerializerGeneration (object obj)
653                 {
654                         throw new NotImplementedException();
655                 }
656 #else
657                 void CheckGeneratedTypes (XmlMapping typeMapping)
658                 {
659                         lock (this)
660                         {
661                                 if (serializerData == null) 
662                                 {
663                                         lock (serializerTypes)
664                                         {
665                                                 serializerData = (SerializerData) serializerTypes [typeMapping.Source];
666                                                 if (serializerData == null) {
667                                                         serializerData = new SerializerData();
668                                                         serializerTypes [typeMapping.Source] = serializerData;
669                                                 }
670                                         }
671                                 }
672                         }
673                         
674                         bool generate = false;
675                         lock (serializerData)
676                         {
677                                 generate = (++serializerData.UsageCount == generationThreshold);
678                         }
679                         
680                         if (generate)
681                         {
682                                 if (serializerData.Batch != null)
683                                         GenerateSerializersAsync (serializerData.Batch);
684                                 else
685                                 {
686                                         GenerationBatch batch = new GenerationBatch ();
687                                         batch.Maps = new XmlMapping[] {typeMapping};
688                                         batch.Datas = new SerializerData[] {serializerData};
689                                         GenerateSerializersAsync (batch);
690                                 }
691                         }
692                 }
693                 
694                 void GenerateSerializersAsync (GenerationBatch batch)
695                 {
696                         if (batch.Maps.Length != batch.Datas.Length)
697                                 throw new ArgumentException ("batch");
698
699                         lock (batch)
700                         {
701                                 if (batch.Done) return;
702                                 batch.Done = true;
703                         }
704                         
705                         if (backgroundGeneration)
706                                 ThreadPool.QueueUserWorkItem (new WaitCallback (RunSerializerGeneration), batch);
707                         else
708                                 RunSerializerGeneration (batch);
709                 }
710                 
711                 void RunSerializerGeneration (object obj)
712                 {
713                         try
714                         {
715                                 GenerationBatch batch = (GenerationBatch) obj;
716                                 batch = LoadFromSatelliteAssembly (batch);
717                                 
718                                 if (batch != null)
719                                         GenerateSerializers (batch, null);
720                         }
721                         catch (Exception ex)
722                         {
723                                 Console.WriteLine (ex);
724                         }
725                 }
726                 
727                 static Assembly GenerateSerializers (GenerationBatch batch, CompilerParameters cp)
728                 {
729                         DateTime tim = DateTime.Now;
730                         
731                         XmlMapping[] maps = batch.Maps;
732                         
733                         if (cp == null) {
734                                 cp = new CompilerParameters();
735                                 cp.IncludeDebugInformation = false;
736                                 cp.GenerateInMemory = true;
737                                 cp.TempFiles.KeepFiles = !deleteTempFiles;
738                         }
739                         
740                         string file = cp.TempFiles.AddExtension ("cs");
741                         StreamWriter sw = new StreamWriter (file);
742                         
743                         if (!deleteTempFiles)
744                                 Console.WriteLine ("Generating " + file);
745                         
746                         SerializationCodeGenerator gen = new SerializationCodeGenerator (maps);
747                         
748                         try
749                         {
750                                 gen.GenerateSerializers (sw);
751                         }
752                         catch (Exception ex)
753                         {
754                                 Console.WriteLine ("Serializer could not be generated");
755                                 Console.WriteLine (ex);
756                                 cp.TempFiles.Delete ();
757                                 return null;
758                         }
759                         sw.Close ();
760                         
761                         CSharpCodeProvider provider = new CSharpCodeProvider();
762                         ICodeCompiler comp = provider.CreateCompiler ();
763                         
764                         cp.GenerateExecutable = false;
765                         
766                         foreach (Type rtype in gen.ReferencedTypes)
767                         {
768                                 string path = new Uri (rtype.Assembly.CodeBase).LocalPath;
769                                 if (!cp.ReferencedAssemblies.Contains (path))
770                                         cp.ReferencedAssemblies.Add (path);
771                         }
772                                 
773                         if (!cp.ReferencedAssemblies.Contains ("System.dll"))
774                                 cp.ReferencedAssemblies.Add ("System.dll");
775                         if (!cp.ReferencedAssemblies.Contains ("System.Xml"))
776                                 cp.ReferencedAssemblies.Add ("System.Xml");
777                         if (!cp.ReferencedAssemblies.Contains ("System.Data"))
778                                 cp.ReferencedAssemblies.Add ("System.Data");
779                         
780                         CompilerResults res = comp.CompileAssemblyFromFile (cp, file);
781                         if (res.Errors.HasErrors || res.CompiledAssembly == null) {
782                                 Console.WriteLine ("Error while compiling generated serializer");
783                                 foreach (CompilerError error in res.Errors)
784                                         Console.WriteLine (error);
785                                         
786                                 cp.TempFiles.Delete ();
787                                 return null;
788                         }
789                         
790                         GenerationResult[] results = gen.GenerationResults;
791                         for (int n=0; n<results.Length; n++)
792                         {
793                                 GenerationResult gres = results[n];
794                                 SerializerData sd = batch.Datas [n];
795                                 lock (sd)
796                                 {
797                                         sd.WriterType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.WriterClassName);
798                                         sd.ReaderType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.ReaderClassName);
799                                         sd.WriterMethod = sd.WriterType.GetMethod (gres.WriteMethodName);
800                                         sd.ReaderMethod = sd.ReaderType.GetMethod (gres.ReadMethodName);
801                                         sd.Batch = null;
802                                 }
803                         }
804                         
805                         cp.TempFiles.Delete ();
806
807                         if (!deleteTempFiles)
808                                 Console.WriteLine ("Generation finished - " + (DateTime.Now - tim).TotalMilliseconds + " ms");
809                                 
810                         return res.CompiledAssembly;
811                 }
812 #endif
813                 
814 #if NET_2_0
815                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
816                 {
817                         return batch;
818                 }
819 #else
820                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
821                 {
822                         return batch;
823                 }
824 #endif
825                 
826 #endregion // Methods
827         }
828 }