2006-02-21 Atsushi Enomoto <atsushi@ximian.com>
[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
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                 static int generationThreshold;
56                 static bool backgroundGeneration = true;
57                 static bool deleteTempFiles = true;
58                 static bool generatorFallback = true;
59
60                 bool customSerializer;
61                 XmlMapping typeMapping;
62                 
63                 SerializerData serializerData;
64                 
65                 static Hashtable serializerTypes = new Hashtable ();
66                 
67                 internal class SerializerData
68                 {
69                         public int UsageCount;
70                         public Type ReaderType;
71                         public MethodInfo ReaderMethod;
72                         public Type WriterType;
73                         public MethodInfo WriterMethod;
74                         public GenerationBatch Batch;
75                         public IXmlSerializerImplementation Implementation = null;
76                         
77                         public XmlSerializationReader CreateReader () {
78                                 if (ReaderType != null)
79                                         return (XmlSerializationReader) Activator.CreateInstance (ReaderType);
80                                 else if (Implementation != null)
81                                         return Implementation.Reader;
82                                 else
83                                         return null;
84                         }
85                         
86                         public XmlSerializationWriter CreateWriter () {
87                                 if (WriterType != null)
88                                         return (XmlSerializationWriter) Activator.CreateInstance (WriterType);
89                                 else if (Implementation != null)
90                                         return Implementation.Writer;
91                                 else
92                                         return null;
93                         }
94                 }
95                 
96                 internal class GenerationBatch
97                 {
98                         public bool Done;
99                         public XmlMapping[] Maps;
100                         public SerializerData[] Datas;
101                 }
102                 
103                 static XmlSerializer ()
104                 {
105                         // The following options are available:
106                         // MONO_XMLSERIALIZER_DEBUG: when set to something != "no", it will
107                         //       it will print the name of the generated file, and it won't
108                         //       be deleted.
109                         // MONO_XMLSERIALIZER_THS: The code generator threshold. It can be:
110                         //       no: does not use the generator, always the interpreter.
111                         //       0: always use the generator, wait until the generation is done.
112                         //       any number: use the interpreted serializer until the specified
113                         //       number of serializations is reached. At this point the generation
114                         //       of the serializer will start in the background. The interpreter
115                         //       will be used while the serializer is being generated.
116                         //
117                         //       XmlSerializer will fall back to the interpreted serializer if
118                         //       the code generation somehow fails. This can be avoided for
119                         //       debugging pourposes by adding the "nofallback" option.
120                         //       For example: MONO_XMLSERIALIZER_THS=0,nofallback
121                         
122 #if TARGET_JVM
123                         string db = null;
124                         string th = null;
125                         generationThreshold = -1;
126                         backgroundGeneration = false;
127 #else
128                         string db = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_DEBUG");
129                         string th = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_THS");
130                         
131                         if (th == null) {
132                                 generationThreshold = 50;
133                                 backgroundGeneration = true;
134                         } else {
135                                 int i = th.IndexOf (',');
136                                 if (i != -1) {
137                                         if (th.Substring (i+1) == "nofallback")
138                                                 generatorFallback = false;
139                                         th = th.Substring (0, i);
140                                 }
141                                 
142                                 if (th.ToLower(CultureInfo.InvariantCulture) == "no") 
143                                         generationThreshold = -1;
144                                 else {
145                                         generationThreshold = int.Parse (th, CultureInfo.InvariantCulture);
146                                         backgroundGeneration = (generationThreshold != 0);
147                                         if (generationThreshold < 1) generationThreshold = 1;
148                                 }
149                         }
150 #endif
151                         deleteTempFiles = (db == null || db == "no");
152                         
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                 }
164
165 #region Constructors
166
167                 protected XmlSerializer ()
168                 {
169                         customSerializer = true;
170                 }
171
172                 public XmlSerializer (Type type)
173                         : this (type, null, null, null, null)
174                 {
175                 }
176
177                 public XmlSerializer (XmlTypeMapping xmlTypeMapping)
178                 {
179                         typeMapping = xmlTypeMapping;
180                 }
181
182                 internal XmlSerializer (XmlMapping mapping, SerializerData data)
183                 {
184                         typeMapping = mapping;
185                         serializerData = data;
186                 }
187
188                 public XmlSerializer (Type type, string defaultNamespace)
189                         : this (type, null, null, null, defaultNamespace)
190                 {
191                 }
192
193                 public XmlSerializer (Type type, Type[] extraTypes)
194                         : this (type, null, extraTypes, null, null)
195                 {
196                 }
197
198                 public XmlSerializer (Type type, XmlAttributeOverrides overrides)
199                         : this (type, overrides, null, null, null)
200                 {
201                 }
202
203                 public XmlSerializer (Type type, XmlRootAttribute root)
204                         : this (type, null, null, root, null)
205                 {
206                 }
207
208                 public XmlSerializer (Type type,
209                         XmlAttributeOverrides overrides,
210                         Type [] extraTypes,
211                         XmlRootAttribute root,
212                         string defaultNamespace)
213                 {
214                         if (type == null)
215                                 throw new ArgumentNullException ("type");
216
217                         XmlReflectionImporter importer = new XmlReflectionImporter (overrides, defaultNamespace);
218
219                         if (extraTypes != null) 
220                         {
221                                 foreach (Type intype in extraTypes)
222                                         importer.IncludeType (intype);
223                         }
224
225                         typeMapping = importer.ImportTypeMapping (type, root, defaultNamespace);
226                 }
227                 
228                 internal XmlMapping Mapping
229                 {
230                         get { return typeMapping; }
231                 }
232
233 #if NET_2_0
234
235                 [MonoTODO]
236                 public XmlSerializer (Type type,
237                         XmlAttributeOverrides overrides,
238                         Type [] extraTypes,
239                         XmlRootAttribute root,
240                         string defaultNamespace,
241                         string location,
242                         Evidence evidence)
243                 {
244                 }
245 #endif
246
247 #endregion // Constructors
248
249 #region Events
250
251                 private XmlAttributeEventHandler onUnknownAttribute;
252                 private XmlElementEventHandler onUnknownElement;
253                 private XmlNodeEventHandler onUnknownNode;
254                 private UnreferencedObjectEventHandler onUnreferencedObject;
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                 public event UnreferencedObjectEventHandler UnreferencedObject 
272                 {
273                         add { onUnreferencedObject += value; } remove { onUnreferencedObject -= value; }
274                 }
275
276
277                 internal virtual void OnUnknownAttribute (XmlAttributeEventArgs e) 
278                 {
279                         if (onUnknownAttribute != null) onUnknownAttribute(this, e);
280                 }
281
282                 internal virtual void OnUnknownElement (XmlElementEventArgs e) 
283                 {
284                         if (onUnknownElement != null) onUnknownElement(this, e);
285                 }
286
287                 internal virtual void OnUnknownNode (XmlNodeEventArgs e) 
288                 {
289                         if (onUnknownNode != null) onUnknownNode(this, e);
290                 }
291
292                 internal virtual void OnUnreferencedObject (UnreferencedObjectEventArgs e) 
293                 {
294                         if (onUnreferencedObject != null) onUnreferencedObject(this, e);
295                 }
296
297
298 #endregion // Events
299
300 #region Methods
301
302                 public virtual bool CanDeserialize (XmlReader xmlReader)
303                 {
304                         xmlReader.MoveToContent ();
305                         if (typeMapping is XmlMembersMapping) 
306                                 return true;
307                         else
308                                 return ((XmlTypeMapping)typeMapping).ElementName == xmlReader.LocalName;
309                 }
310
311                 protected virtual XmlSerializationReader CreateReader ()
312                 {
313                         // Must be implemented in derived class
314                         throw new NotImplementedException ();
315                 }
316
317                 protected virtual XmlSerializationWriter CreateWriter ()
318                 {
319                         // Must be implemented in derived class
320                         throw new NotImplementedException ();
321                 }
322
323                 public object Deserialize (Stream stream)
324                 {
325                         XmlTextReader xmlReader = new XmlTextReader(stream);
326                         xmlReader.Normalization = true;
327                         return Deserialize(xmlReader);
328                 }
329
330                 public object Deserialize (TextReader textReader)
331                 {
332                         XmlTextReader xmlReader = new XmlTextReader(textReader);
333                         xmlReader.Normalization = true;
334                         return Deserialize(xmlReader);
335                 }
336
337                 public object Deserialize (XmlReader xmlReader)
338                 {
339                         XmlSerializationReader xsReader;
340                         if (customSerializer)
341                                 xsReader = CreateReader ();
342                         else
343                                 xsReader = CreateReader (typeMapping);
344                                 
345                         xsReader.Initialize (xmlReader, this);
346                         return Deserialize (xsReader);
347                 }
348
349                 protected virtual object Deserialize (XmlSerializationReader reader)
350                 {
351                         if (customSerializer)
352                                 // Must be implemented in derived class
353                                 throw new NotImplementedException ();
354                         
355                         if (reader is XmlSerializationReaderInterpreter)
356                                 return ((XmlSerializationReaderInterpreter)reader).ReadRoot ();
357                         else
358                                 return serializerData.ReaderMethod.Invoke (reader, null);
359                 }
360
361                 public static XmlSerializer [] FromMappings (XmlMapping [] mappings)
362                 {
363                         XmlSerializer[] sers = new XmlSerializer [mappings.Length];
364                         SerializerData[] datas = new SerializerData [mappings.Length];
365                         GenerationBatch batch = new GenerationBatch ();
366                         batch.Maps = mappings;
367                         batch.Datas = datas;
368                         
369                         for (int n=0; n<mappings.Length; n++)
370                         {
371                                 if (mappings[n] != null)
372                                 {
373                                         SerializerData data = new SerializerData ();
374                                         data.Batch = batch;
375                                         sers[n] = new XmlSerializer (mappings[n], data);
376                                         datas[n] = data;
377                                 }
378                         }
379                         
380                         return sers;
381                 }
382
383                 public static XmlSerializer [] FromTypes (Type [] mappings)
384                 {
385                         XmlSerializer [] sers = new XmlSerializer [mappings.Length];
386                         for (int n=0; n<mappings.Length; n++)
387                                 sers[n] = new XmlSerializer (mappings[n]);
388                         return sers;
389                 }
390
391                 protected virtual void Serialize (object o, XmlSerializationWriter writer)
392                 {
393                         if (customSerializer)
394                                 // Must be implemented in derived class
395                                 throw new NotImplementedException ();
396                                 
397                         if (writer is XmlSerializationWriterInterpreter)
398                                 ((XmlSerializationWriterInterpreter)writer).WriteRoot (o);
399                         else
400                                 serializerData.WriterMethod.Invoke (writer, new object[] {o});
401                 }
402
403                 public void Serialize (Stream stream, object o)
404                 {
405                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
406                         xmlWriter.Formatting = Formatting.Indented;
407                         Serialize (xmlWriter, o, null);
408                 }
409
410                 public void Serialize (TextWriter textWriter, object o)
411                 {
412                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
413                         xmlWriter.Formatting = Formatting.Indented;
414                         Serialize (xmlWriter, o, null);
415                 }
416
417                 public void Serialize (XmlWriter xmlWriter, object o)
418                 {
419                         Serialize (xmlWriter, o, null);
420                 }
421
422                 public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
423                 {
424                         XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
425                         xmlWriter.Formatting = Formatting.Indented;
426                         Serialize (xmlWriter, o, namespaces);
427                 }
428
429                 public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
430                 {
431                         XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
432                         xmlWriter.Formatting = Formatting.Indented;
433                         Serialize (xmlWriter, o, namespaces);
434                         xmlWriter.Flush();
435                 }
436
437                 public void Serialize (XmlWriter writer, object o, XmlSerializerNamespaces namespaces)
438                 {
439                         XmlSerializationWriter xsWriter;
440                         
441                         if (customSerializer)
442                                 xsWriter = CreateWriter ();
443                         else
444                                 xsWriter = CreateWriter (typeMapping);
445                                 
446                         if (namespaces == null || namespaces.Count == 0)
447                         {
448                                 namespaces = new XmlSerializerNamespaces ();
449                                 namespaces.Add ("xsd", XmlSchema.Namespace);
450                                 namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
451                         }
452                         
453                         xsWriter.Initialize (writer, namespaces);
454                         Serialize (o, xsWriter);
455                         writer.Flush ();
456                 }
457                 
458 #if NET_2_0
459                 
460                 [MonoTODO]
461                 public object Deserialize (XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
462                 {
463                         throw new NotImplementedException ();
464                 }
465
466                 [MonoTODO]
467                 public object Deserialize (XmlReader xmlReader, string encodingStyle)
468                 {
469                         throw new NotImplementedException ();
470                 }
471
472                 [MonoTODO]
473                 public object Deserialize (XmlReader xmlReader, XmlDeserializationEvents events)
474                 {
475                         throw new NotImplementedException ();
476                 }
477                 
478                 [MonoTODO]
479                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Evidence evidence)
480                 {
481                         throw new NotImplementedException ();
482                 }
483
484                 [MonoTODO]
485                 public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Type type)
486                 {
487                         throw new NotImplementedException ();
488                 }
489
490                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings)
491                 {
492                         return GenerateSerializer (types, mappings, null);
493                 }
494                 
495                 [MonoTODO]
496                 public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings, CompilerParameters parameters)
497                 {
498                         GenerationBatch batch = new GenerationBatch ();
499                         batch.Maps = mappings;
500                         batch.Datas = new SerializerData [mappings.Length];
501                         
502                         for (int n=0; n<mappings.Length; n++) {
503                                 SerializerData data = new SerializerData ();
504                                 data.Batch = batch;
505                                 batch.Datas [n] = data;
506                         }
507                         
508                         return GenerateSerializers (batch, parameters);
509                 }
510                 
511                 [MonoTODO]
512                 [Obsolete]
513                 public static Assembly GenerateSerializer (Type[] types, 
514                         XmlMapping[] mappings, 
515                         string codePath, 
516                         bool debug, 
517                         bool keepFiles)
518                 {
519                         throw new NotImplementedException ();
520                 }
521                 
522                 [MonoTODO]
523                 [Obsolete]
524                 public static Assembly GenerateSerializer (Type[] types, 
525                         XmlMapping[] mappings, 
526                         string codePath, 
527                         bool debug, 
528                         bool keepFiles, 
529                         string compilerOptions)
530                 {
531                         throw new NotImplementedException ();
532                 }
533
534                 public static string GetXmlSerializerAssemblyName (Type type)
535                 {
536                         return type.Assembly.GetName().Name + ".XmlSerializers";
537                 }
538
539                 public static string GetXmlSerializerAssemblyName (Type type, string defaultNamespace)
540                 {
541                         return GetXmlSerializerAssemblyName (type) + "." + defaultNamespace.GetHashCode ();
542                 }
543                 
544                 [MonoTODO]
545                 public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle)
546                 {
547                         throw new NotImplementedException ();
548                 }
549
550 #endif
551                 
552                 XmlSerializationWriter CreateWriter (XmlMapping typeMapping)
553                 {
554                         XmlSerializationWriter writer;
555                         
556                         lock (this) {
557                                 if (serializerData != null) {
558                                         lock (serializerData) {
559                                                 writer = serializerData.CreateWriter ();
560                                         }
561                                         if (writer != null) return writer;
562                                 }
563                         }
564                         
565                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
566                                 return new XmlSerializationWriterInterpreter (typeMapping);
567
568                         CheckGeneratedTypes (typeMapping);
569                         
570                         lock (this) {
571                                 lock (serializerData) {
572                                         writer = serializerData.CreateWriter ();
573                                 }
574                                 if (writer != null) return writer;
575                                 if (!generatorFallback)
576                                         throw new InvalidOperationException ("Error while generating serializer");
577                         }
578                         
579                         return new XmlSerializationWriterInterpreter (typeMapping);
580                 }
581                 
582                 XmlSerializationReader CreateReader (XmlMapping typeMapping)
583                 {
584                         XmlSerializationReader reader;
585                         
586                         lock (this) {
587                                 if (serializerData != null) {
588                                         lock (serializerData) {
589                                                 reader = serializerData.CreateReader ();
590                                         }
591                                         if (reader != null) return reader;
592                                 }
593                         }
594                         
595                         if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
596                                 return new XmlSerializationReaderInterpreter (typeMapping);
597
598                         CheckGeneratedTypes (typeMapping);
599                         
600                         lock (this) {
601                                 lock (serializerData) {
602                                         reader = serializerData.CreateReader ();
603                                 }
604                                 if (reader != null) return reader;
605                                 if (!generatorFallback)
606                                         throw new InvalidOperationException ("Error while generating serializer");
607                         }
608                         
609                         return new XmlSerializationReaderInterpreter (typeMapping);
610                 }
611                 
612 #if TARGET_JVM
613                 void CheckGeneratedTypes (XmlMapping typeMapping)
614                 {
615                         throw new NotImplementedException();
616                 }
617                 void GenerateSerializersAsync (GenerationBatch batch)
618                 {
619                         throw new NotImplementedException();
620                 }
621                 void RunSerializerGeneration (object obj)
622                 {
623                         throw new NotImplementedException();
624                 }
625 #else
626                 void CheckGeneratedTypes (XmlMapping typeMapping)
627                 {
628                         lock (this)
629                         {
630                                 if (serializerData == null) 
631                                 {
632                                         lock (serializerTypes)
633                                         {
634                                                 serializerData = (SerializerData) serializerTypes [typeMapping.Source];
635                                                 if (serializerData == null) {
636                                                         serializerData = new SerializerData();
637                                                         serializerTypes [typeMapping.Source] = serializerData;
638                                                 }
639                                         }
640                                 }
641                         }
642                         
643                         bool generate = false;
644                         lock (serializerData)
645                         {
646                                 generate = (++serializerData.UsageCount == generationThreshold);
647                         }
648                         
649                         if (generate)
650                         {
651                                 if (serializerData.Batch != null)
652                                         GenerateSerializersAsync (serializerData.Batch);
653                                 else
654                                 {
655                                         GenerationBatch batch = new GenerationBatch ();
656                                         batch.Maps = new XmlMapping[] {typeMapping};
657                                         batch.Datas = new SerializerData[] {serializerData};
658                                         GenerateSerializersAsync (batch);
659                                 }
660                         }
661                 }
662                 
663                 void GenerateSerializersAsync (GenerationBatch batch)
664                 {
665                         if (batch.Maps.Length != batch.Datas.Length)
666                                 throw new ArgumentException ("batch");
667
668                         lock (batch)
669                         {
670                                 if (batch.Done) return;
671                                 batch.Done = true;
672                         }
673                         
674                         if (backgroundGeneration)
675                                 ThreadPool.QueueUserWorkItem (new WaitCallback (RunSerializerGeneration), batch);
676                         else
677                                 RunSerializerGeneration (batch);
678                 }
679                 
680                 void RunSerializerGeneration (object obj)
681                 {
682                         try
683                         {
684                                 GenerationBatch batch = (GenerationBatch) obj;
685                                 batch = LoadFromSatelliteAssembly (batch);
686                                 
687                                 if (batch != null)
688                                         GenerateSerializers (batch, null);
689                         }
690                         catch (Exception ex)
691                         {
692                                 Console.WriteLine (ex);
693                         }
694                 }
695                 
696                 static Assembly GenerateSerializers (GenerationBatch batch, CompilerParameters cp)
697                 {
698                         DateTime tim = DateTime.Now;
699                         
700                         XmlMapping[] maps = batch.Maps;
701                         
702                         if (cp == null) {
703                                 cp = new CompilerParameters();
704                                 cp.IncludeDebugInformation = false;
705                                 cp.GenerateInMemory = true;
706                                 cp.TempFiles.KeepFiles = !deleteTempFiles;
707                         }
708                         
709                         string file = cp.TempFiles.AddExtension ("cs");
710                         StreamWriter sw = new StreamWriter (file);
711                         
712                         if (!deleteTempFiles)
713                                 Console.WriteLine ("Generating " + file);
714                         
715                         SerializationCodeGenerator gen = new SerializationCodeGenerator (maps);
716                         
717                         try
718                         {
719                                 gen.GenerateSerializers (sw);
720                         }
721                         catch (Exception ex)
722                         {
723                                 Console.WriteLine ("Serializer could not be generated");
724                                 Console.WriteLine (ex);
725                                 cp.TempFiles.Delete ();
726                                 return null;
727                         }
728                         sw.Close ();
729                         
730                         CSharpCodeProvider provider = new CSharpCodeProvider();
731                         ICodeCompiler comp = provider.CreateCompiler ();
732                         
733                         cp.GenerateExecutable = false;
734                         
735                         foreach (Type rtype in gen.ReferencedTypes)
736                         {
737                                 if (!cp.ReferencedAssemblies.Contains (rtype.Assembly.Location))
738                                         cp.ReferencedAssemblies.Add (rtype.Assembly.Location);
739                         }
740                                 
741                         if (!cp.ReferencedAssemblies.Contains ("System.dll"))
742                                 cp.ReferencedAssemblies.Add ("System.dll");
743                         if (!cp.ReferencedAssemblies.Contains ("System.Xml"))
744                                 cp.ReferencedAssemblies.Add ("System.Xml");
745                         if (!cp.ReferencedAssemblies.Contains ("System.Data"))
746                                 cp.ReferencedAssemblies.Add ("System.Data");
747                         
748                         CompilerResults res = comp.CompileAssemblyFromFile (cp, file);
749                         if (res.Errors.HasErrors || res.CompiledAssembly == null) {
750                                 Console.WriteLine ("Error while compiling generated serializer");
751                                 foreach (CompilerError error in res.Errors)
752                                         Console.WriteLine (error);
753                                         
754                                 cp.TempFiles.Delete ();
755                                 return null;
756                         }
757                         
758                         GenerationResult[] results = gen.GenerationResults;
759                         for (int n=0; n<results.Length; n++)
760                         {
761                                 GenerationResult gres = results[n];
762                                 SerializerData sd = batch.Datas [n];
763                                 lock (sd)
764                                 {
765                                         sd.WriterType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.WriterClassName);
766                                         sd.ReaderType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.ReaderClassName);
767                                         sd.WriterMethod = sd.WriterType.GetMethod (gres.WriteMethodName);
768                                         sd.ReaderMethod = sd.ReaderType.GetMethod (gres.ReadMethodName);
769                                         sd.Batch = null;
770                                 }
771                         }
772                         
773                         cp.TempFiles.Delete ();
774
775                         if (!deleteTempFiles)
776                                 Console.WriteLine ("Generation finished - " + (DateTime.Now - tim).TotalMilliseconds + " ms");
777                                 
778                         return res.CompiledAssembly;
779                 }
780 #endif
781                 
782 #if NET_2_0
783                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
784                 {
785                         return batch;
786                 }
787 #else
788                 GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
789                 {
790                         return batch;
791                 }
792 #endif
793                 
794 #endregion // Methods
795         }
796 }