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