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