Merge pull request #1223 from esdrubal/xmlgenerator
[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                                 }
149                         }
150 #endif
151                         deleteTempFiles = (db == null || db == "no");
152 #if !NET_2_1
153                         IDictionary table = (IDictionary) ConfigurationSettings.GetConfig("system.diagnostics");
154                         if (table != null) 
155                         {
156                                 table = (IDictionary) table["switches"];
157                                 if (table != null) 
158                                 {
159                                         string val = (string) table ["XmlSerialization.Compilation"];
160                                         if (val == "1") deleteTempFiles = false;
161                                 }
162                         }
163 #endif
164                 }
165
166 #region Constructors
167
168                 protected XmlSerializer ()
169                 {
170                         customSerializer = true;
171                 }
172
173                 public XmlSerializer (Type type)
174                         : this (type, null, null, null, null)
175                 {
176                 }
177
178                 public XmlSerializer (XmlTypeMapping xmlTypeMapping)
179                 {
180                         typeMapping = xmlTypeMapping;
181                 }
182
183                 internal XmlSerializer (XmlMapping mapping, SerializerData data)
184                 {
185                         typeMapping = mapping;
186                         serializerData = data;
187                 }
188
189                 public XmlSerializer (Type type, string defaultNamespace)
190                         : this (type, null, null, null, defaultNamespace)
191                 {
192                 }
193
194                 public XmlSerializer (Type type, Type[] extraTypes)
195                         : this (type, null, extraTypes, null, null)
196                 {
197                 }
198
199                 public XmlSerializer (Type type, XmlAttributeOverrides overrides)
200                         : this (type, overrides, null, null, null)
201                 {
202                 }
203
204                 public XmlSerializer (Type type, XmlRootAttribute root)
205                         : this (type, null, null, root, null)
206                 {
207                 }
208
209                 public XmlSerializer (Type type,
210                         XmlAttributeOverrides overrides,
211                         Type [] extraTypes,
212                         XmlRootAttribute root,
213                         string defaultNamespace)
214                 {
215                         if (type == null)
216                                 throw new ArgumentNullException ("type");
217
218                         XmlReflectionImporter importer = new XmlReflectionImporter (overrides, defaultNamespace);
219
220                         if (extraTypes != null) 
221                         {
222                                 foreach (Type intype in extraTypes)
223                                         importer.IncludeType (intype);
224                         }
225
226                         typeMapping = importer.ImportTypeMapping (type, root, defaultNamespace);
227                 }
228                 
229                 internal XmlMapping Mapping
230                 {
231                         get { return typeMapping; }
232                 }
233
234 #if NET_2_0
235
236                 [MonoTODO]
237                 public XmlSerializer (Type type,
238                         XmlAttributeOverrides overrides,
239                         Type [] extraTypes,
240                         XmlRootAttribute root,
241                         string defaultNamespace,
242                         string location,
243                         Evidence evidence)
244                 {
245                 }
246 #endif
247
248 #endregion // Constructors
249
250 #region Events
251                 private UnreferencedObjectEventHandler onUnreferencedObject;
252                 private XmlAttributeEventHandler onUnknownAttribute;
253                 private XmlElementEventHandler onUnknownElement;
254                 private XmlNodeEventHandler onUnknownNode;
255
256                 public event XmlAttributeEventHandler UnknownAttribute 
257                 {
258                         add { onUnknownAttribute += value; } remove { onUnknownAttribute -= value; }
259                 }
260
261                 public event XmlElementEventHandler UnknownElement 
262                 {
263                         add { onUnknownElement += value; } remove { onUnknownElement -= value; }
264                 }
265
266                 public event XmlNodeEventHandler UnknownNode 
267                 {
268                         add { onUnknownNode += value; } remove { onUnknownNode -= value; }
269                 }
270
271
272                 internal virtual void OnUnknownAttribute (XmlAttributeEventArgs e) 
273                 {
274                         if (onUnknownAttribute != null) onUnknownAttribute(this, e);
275                 }
276
277                 internal virtual void OnUnknownElement (XmlElementEventArgs e) 
278                 {
279                         if (onUnknownElement != null) onUnknownElement(this, e);
280                 }
281
282                 internal virtual void OnUnknownNode (XmlNodeEventArgs e) 
283                 {
284                         if (onUnknownNode != null) onUnknownNode(this, e);
285                 }
286
287                 internal virtual void OnUnreferencedObject (UnreferencedObjectEventArgs e) 
288                 {
289                         if (onUnreferencedObject != null) onUnreferencedObject(this, e);
290                 }
291
292                 public event UnreferencedObjectEventHandler UnreferencedObject 
293                 {
294                         add { onUnreferencedObject += value; } remove { onUnreferencedObject -= value; }
295                 }
296
297 #endregion // Events
298
299 #region Methods
300
301                 public virtual bool CanDeserialize (XmlReader xmlReader)
302                 {
303                         xmlReader.MoveToContent ();
304                         if (typeMapping is XmlMembersMapping) 
305                                 return true;
306                         else
307                                 return ((XmlTypeMapping)typeMapping).ElementName == xmlReader.LocalName;
308                 }
309
310                 protected virtual XmlSerializationReader CreateReader ()
311                 {
312                         // Must be implemented in derived class
313                         throw new NotImplementedException ();
314                 }
315
316                 protected virtual XmlSerializationWriter CreateWriter ()
317                 {
318                         // Must be implemented in derived class
319                         throw new NotImplementedException ();
320                 }
321
322                 public object Deserialize (Stream stream)
323                 {
324                         XmlTextReader xmlReader = new XmlTextReader(stream);
325                         xmlReader.Normalization = true;
326                         xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
327                         return Deserialize(xmlReader);
328                 }
329
330                 public object Deserialize (TextReader textReader)
331                 {
332                         XmlTextReader xmlReader = new XmlTextReader(textReader);
333                         xmlReader.Normalization = true;
334                         xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
335                         return Deserialize(xmlReader);
336                 }
337
338                 public object Deserialize (XmlReader xmlReader)
339                 {
340                         XmlSerializationReader xsReader;
341                         if (customSerializer)
342                                 xsReader = CreateReader ();
343                         else
344                                 xsReader = CreateReader (typeMapping);
345                                 
346                         xsReader.Initialize (xmlReader, this);
347                         return Deserialize (xsReader);
348                 }
349
350                 protected virtual object Deserialize (XmlSerializationReader reader)
351                 {
352                         if (customSerializer)
353                                 // Must be implemented in derived class
354                                 throw new NotImplementedException ();
355                         
356                         try {
357                                 if (reader is XmlSerializationReaderInterpreter)
358                                         return ((XmlSerializationReaderInterpreter) reader).ReadRoot ();
359                                 else {
360                                         try {
361                                                 return serializerData.ReaderMethod.Invoke (reader, null);
362                                         } catch (TargetInvocationException ex) {
363                                                 throw ex.InnerException;
364                                         }
365                                 }
366                         } catch (Exception ex) {
367                                 if (ex is InvalidOperationException || ex is InvalidCastException)
368                                         throw new InvalidOperationException ("There is an error in"
369                                                 + " XML document.", ex);
370                                 throw;
371                         }
372                 }
373
374                 public static XmlSerializer [] FromMappings (XmlMapping [] mappings)
375                 {
376                         XmlSerializer[] sers = new XmlSerializer [mappings.Length];
377                         SerializerData[] datas = new SerializerData [mappings.Length];
378                         GenerationBatch batch = new GenerationBatch ();
379                         batch.Maps = mappings;
380                         batch.Datas = datas;
381                         
382                         for (int n=0; n<mappings.Length; n++)
383                         {
384                                 if (mappings[n] != null)
385                                 {
386                                         SerializerData data = new SerializerData ();
387                                         data.Batch = batch;
388                                         sers[n] = new XmlSerializer (mappings[n], data);
389                                         datas[n] = data;
390                                 }
391                         }
392                         
393                         return sers;
394                 }
395
396                 public static XmlSerializer [] FromTypes (Type [] types)
397                 {
398                         XmlSerializer [] sers = new XmlSerializer [types.Length];
399                         for (int n=0; n<types.Length; n++)
400                                 sers[n] = new XmlSerializer (types[n]);
401                         return sers;
402                 }
403
404                 protected virtual void Serialize (object o, XmlSerializationWriter writer)
405                 {
406                         if (customSerializer)
407                                 // Must be implemented in derived class
408                                 throw new NotImplementedException ();
409                                 
410                         if (writer is XmlSerializationWriterInterpreter)
411                                 ((XmlSerializationWriterInterpreter)writer).WriteRoot (o);
412                         else {
413                                 try {
414                                         serializerData.WriterMethod.Invoke (writer, new object[] {o});
415                                 } catch (TargetInvocationException ex) {
416                                         throw ex.InnerException;
417                                 }
418                         }
419                 }
420
421                 static Encoding DefaultEncoding = Encoding.Default;
422
423                 public void Serialize (Stream stream, object o)
424                 {
425                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, DefaultEncoding);
426                         xmlWriter.Formatting = Formatting.Indented;
427                         Serialize (xmlWriter, o, null);
428                 }
429
430                 public void Serialize (TextWriter textWriter, object o)
431                 {
432                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
433                         xmlWriter.Formatting = Formatting.Indented;
434                         Serialize (xmlWriter, o, null);
435                 }
436
437                 public void Serialize (XmlWriter xmlWriter, object o)
438                 {
439                         Serialize (xmlWriter, o, null);
440                 }
441
442                 public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
443                 {
444                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, DefaultEncoding);
445                         xmlWriter.Formatting = Formatting.Indented;
446                         Serialize (xmlWriter, o, namespaces);
447                 }
448
449                 public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
450                 {
451                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
452                         xmlWriter.Formatting = Formatting.Indented;
453                         Serialize (xmlWriter, o, namespaces);
454                         xmlWriter.Flush();
455                 }
456
457                 public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces)
458                 {
459                         XmlSerializationWriter xsWriter;
460
461                         try {
462                                 if (customSerializer)
463                                         xsWriter = CreateWriter ();
464                                 else
465                                         xsWriter = CreateWriter (typeMapping);
466
467                                 if (namespaces == null || namespaces.Count == 0) {
468                                         namespaces = new XmlSerializerNamespaces ();
469 #if NET_2_0
470                                         namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
471                                         namespaces.Add ("xsd", XmlSchema.Namespace);
472 #else
473                                         namespaces.Add ("xsd", XmlSchema.Namespace);
474                                         namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
475 #endif
476                                 }
477
478                                 xsWriter.Initialize (xmlWriter, namespaces);
479                                 Serialize (o, xsWriter);
480                                 xmlWriter.Flush ();
481                         } catch (Exception ex) {
482                                 if (ex is TargetInvocationException)
483                                         ex = ex.InnerException;
484
485                                 if (ex is InvalidOperationException || ex is InvalidCastException)
486                                         throw new InvalidOperationException ("There was an error generating" +
487                                                 " the XML document.", ex);
488
489                                 throw;
490                         }
491                 }
492                 
493                 [MonoTODO]
494                 public object Deserialize (XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
495                 {
496                         throw new NotImplementedException ();
497                 }
498
499                 [MonoTODO]
500                 public object Deserialize (XmlReader xmlReader, string encodingStyle)
501                 {
502                         throw new NotImplementedException ();
503                 }
504
505                 [MonoTODO]
506                 public object Deserialize (XmlReader xmlReader, XmlDeserializationEvents events)
507                 {
508                         throw new NotImplementedException ();
509                 }
510                 
511                 [MonoTODO]
512                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Evidence evidence)
513                 {
514                         throw new NotImplementedException ();
515                 }
516
517                 [MonoTODO]
518                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Type type)
519                 {
520                         throw new NotImplementedException ();
521                 }
522
523 #if !TARGET_JVM && !MOBILE
524                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings)
525                 {
526                         return GenerateSerializer (types, mappings, null);
527                 }
528                 
529                 [MonoTODO]
530                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings, CompilerParameters parameters)
531                 {
532                         GenerationBatch batch = new GenerationBatch ();
533                         batch.Maps = mappings;
534                         batch.Datas = new SerializerData [mappings.Length];
535                         
536                         for (int n=0; n<mappings.Length; n++) {
537                                 SerializerData data = new SerializerData ();
538                                 data.Batch = batch;
539                                 batch.Datas [n] = data;
540                         }
541                         
542                         return GenerateSerializers (batch, parameters);
543                 }
544 #endif
545
546                 public static string GetXmlSerializerAssemblyName (Type type)
547                 {
548                         return type.Assembly.GetName().Name + ".XmlSerializers";
549                 }
550
551                 public static string GetXmlSerializerAssemblyName (Type type, string defaultNamespace)
552                 {
553                         return GetXmlSerializerAssemblyName (type) + "." + defaultNamespace.GetHashCode ();
554                 }
555                 
556                 [MonoTODO]
557                 public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle)
558                 {
559                         throw new NotImplementedException ();
560                 }
561
562                 [MonoNotSupported("")]
563                 public void Serialize (XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, string encodingStyle, string id)
564                 {
565                         throw new NotImplementedException ();
566                 }
567                 
568                 XmlSerializationWriter CreateWriter (XmlMapping typeMapping)
569                 {
570                         XmlSerializationWriter writer;
571                         
572                         lock (this) {
573                                 if (serializerData != null) {
574                                         lock (serializerData) {
575                                                 writer = serializerData.CreateWriter ();
576                                         }
577                                         if (writer != null) return writer;
578                                 }
579                         }
580                         
581 #if !NET_2_1
582                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
583                                 return new XmlSerializationWriterInterpreter (typeMapping);
584
585                         CheckGeneratedTypes (typeMapping);
586                         
587                         lock (this) {
588                                 lock (serializerData) {
589                                         writer = serializerData.CreateWriter ();
590                                 }
591                                 if (writer != null) return writer;
592                                 if (!generatorFallback)
593                                         throw new InvalidOperationException ("Error while generating serializer");
594                         }
595                         
596 #endif
597                         return new XmlSerializationWriterInterpreter (typeMapping);
598                 }
599                 
600                 XmlSerializationReader CreateReader (XmlMapping typeMapping)
601                 {
602 #if !NET_2_1
603                         XmlSerializationReader reader;
604                         
605                         lock (this) {
606                                 if (serializerData != null) {
607                                         lock (serializerData) {
608                                                 reader = serializerData.CreateReader ();
609                                         }
610                                         if (reader != null) return reader;
611                                 }
612                         }
613                         
614                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
615                                 return new XmlSerializationReaderInterpreter (typeMapping);
616
617                         CheckGeneratedTypes (typeMapping);
618                         
619                         lock (this) {
620                                 lock (serializerData) {
621                                         reader = serializerData.CreateReader ();
622                                 }
623                                 if (reader != null) return reader;
624                                 if (!generatorFallback)
625                                         throw new InvalidOperationException ("Error while generating serializer");
626                         }
627
628 #endif
629                         return new XmlSerializationReaderInterpreter (typeMapping);
630                 }
631                 
632 #if TARGET_JVM || NET_2_1
633                 void CheckGeneratedTypes (XmlMapping typeMapping)
634                 {
635                         throw new NotImplementedException();
636                 }
637                 void GenerateSerializersAsync (GenerationBatch batch)
638                 {
639                         throw new NotImplementedException();
640                 }
641                 void RunSerializerGeneration (object obj)
642                 {
643                         throw new NotImplementedException();
644                 }
645 #else
646                 void CheckGeneratedTypes (XmlMapping typeMapping)
647                 {
648                         lock (this)
649                         {
650                                 if (serializerData == null) 
651                                 {
652                                         lock (serializerTypes)
653                                         {
654                                                 serializerData = (SerializerData) serializerTypes [typeMapping.Source];
655                                                 if (serializerData == null) {
656                                                         serializerData = new SerializerData();
657                                                         serializerTypes [typeMapping.Source] = serializerData;
658                                                 }
659                                         }
660                                 }
661                         }
662                         
663                         bool generate = false;
664                         lock (serializerData)
665                         {
666                                 generate = (serializerData.UsageCount++ == generationThreshold);
667                         }
668                         
669                         if (generate)
670                         {
671                                 if (serializerData.Batch != null)
672                                         GenerateSerializersAsync (serializerData.Batch);
673                                 else
674                                 {
675                                         GenerationBatch batch = new GenerationBatch ();
676                                         batch.Maps = new XmlMapping[] {typeMapping};
677                                         batch.Datas = new SerializerData[] {serializerData};
678                                         GenerateSerializersAsync (batch);
679                                 }
680                         }
681                 }
682                 
683                 void GenerateSerializersAsync (GenerationBatch batch)
684                 {
685                         if (batch.Maps.Length != batch.Datas.Length)
686                                 throw new ArgumentException ("batch");
687
688                         lock (batch)
689                         {
690                                 if (batch.Done) return;
691                                 batch.Done = true;
692                         }
693                         
694                         if (backgroundGeneration)
695                                 ThreadPool.QueueUserWorkItem (new WaitCallback (RunSerializerGeneration), batch);
696                         else
697                                 RunSerializerGeneration (batch);
698                 }
699                 
700                 void RunSerializerGeneration (object obj)
701                 {
702                         try
703                         {
704                                 GenerationBatch batch = (GenerationBatch) obj;
705                                 batch = LoadFromSatelliteAssembly (batch);
706                                 
707                                 if (batch != null)
708                                         GenerateSerializers (batch, null);
709                         }
710                         catch (Exception ex)
711                         {
712                                 Console.WriteLine (ex);
713                         }
714                 }
715                 
716                 static Assembly GenerateSerializers (GenerationBatch batch, CompilerParameters cp)
717                 {
718                         DateTime tim = DateTime.Now;
719                         
720                         XmlMapping[] maps = batch.Maps;
721                         
722                         if (cp == null) {
723                                 cp = new CompilerParameters();
724                                 cp.IncludeDebugInformation = false;
725                                 cp.GenerateInMemory = true;
726                                 cp.TempFiles.KeepFiles = !deleteTempFiles;
727                         }
728                         
729                         string file = cp.TempFiles.AddExtension ("cs");
730                         StreamWriter sw = new StreamWriter (file);
731                         
732                         if (!deleteTempFiles)
733                                 Console.WriteLine ("Generating " + file);
734                         
735                         SerializationCodeGenerator gen = new SerializationCodeGenerator (maps);
736                         
737                         try
738                         {
739                                 gen.GenerateSerializers (sw);
740                         }
741                         catch (Exception ex)
742                         {
743                                 Console.WriteLine ("Serializer could not be generated");
744                                 Console.WriteLine (ex);
745                                 cp.TempFiles.Delete ();
746                                 return null;
747                         }
748                         sw.Close ();
749                         
750                         CSharpCodeProvider provider = new CSharpCodeProvider();
751                         ICodeCompiler comp = provider.CreateCompiler ();
752                         
753                         cp.GenerateExecutable = false;
754                         
755                         foreach (Type rtype in gen.ReferencedTypes)
756                         {
757                                 string path = new Uri (rtype.Assembly.CodeBase).LocalPath;
758                                 if (!cp.ReferencedAssemblies.Contains (path))
759                                         cp.ReferencedAssemblies.Add (path);
760                         }
761                                 
762                         if (!cp.ReferencedAssemblies.Contains ("System.dll"))
763                                 cp.ReferencedAssemblies.Add ("System.dll");
764                         if (!cp.ReferencedAssemblies.Contains ("System.Xml"))
765                                 cp.ReferencedAssemblies.Add ("System.Xml");
766                         if (!cp.ReferencedAssemblies.Contains ("System.Data"))
767                                 cp.ReferencedAssemblies.Add ("System.Data");
768                         
769                         CompilerResults res = comp.CompileAssemblyFromFile (cp, file);
770                         if (res.Errors.HasErrors || res.CompiledAssembly == null) {
771                                 Console.WriteLine ("Error while compiling generated serializer");
772                                 foreach (CompilerError error in res.Errors)
773                                         Console.WriteLine (error);
774                                         
775                                 cp.TempFiles.Delete ();
776                                 return null;
777                         }
778                         
779                         GenerationResult[] results = gen.GenerationResults;
780                         for (int n=0; n<results.Length; n++)
781                         {
782                                 GenerationResult gres = results[n];
783                                 SerializerData sd = batch.Datas [n];
784                                 lock (sd)
785                                 {
786                                         sd.WriterType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.WriterClassName);
787                                         sd.ReaderType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.ReaderClassName);
788                                         sd.WriterMethod = sd.WriterType.GetMethod (gres.WriteMethodName);
789                                         sd.ReaderMethod = sd.ReaderType.GetMethod (gres.ReadMethodName);
790                                         sd.Batch = null;
791                                 }
792                         }
793                         
794                         cp.TempFiles.Delete ();
795
796                         if (!deleteTempFiles)
797                                 Console.WriteLine ("Generation finished - " + (DateTime.Now - tim).TotalMilliseconds + " ms");
798                                 
799                         return res.CompiledAssembly;
800                 }
801 #endif
802                 
803 #if NET_2_0
804                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
805                 {
806                         return batch;
807                 }
808 #else
809                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
810                 {
811                         return batch;
812                 }
813 #endif
814                 
815 #endregion // Methods
816         }
817 }