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