XmlSerializer.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. //
  2. // XmlSerializer.cs:
  3. //
  4. // Author:
  5. // Lluis Sanchez Gual ([email protected])
  6. //
  7. // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Threading;
  31. using System.Collections;
  32. using System.Globalization;
  33. using System.IO;
  34. using System.Reflection;
  35. using System.Xml;
  36. using System.Xml.Schema;
  37. using System.Text;
  38. #if !TARGET_JVM
  39. using System.CodeDom;
  40. using System.CodeDom.Compiler;
  41. using Microsoft.CSharp;
  42. #endif
  43. using System.Configuration;
  44. using System.Security.Policy;
  45. namespace System.Xml.Serialization
  46. {
  47. public class XmlSerializer
  48. {
  49. internal const string WsdlNamespace = "http://schemas.xmlsoap.org/wsdl/";
  50. internal const string EncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
  51. internal const string WsdlTypesNamespace = "http://microsoft.com/wsdl/types/";
  52. static int generationThreshold;
  53. static bool backgroundGeneration = true;
  54. static bool deleteTempFiles = true;
  55. static bool generatorFallback = true;
  56. bool customSerializer;
  57. XmlMapping typeMapping;
  58. SerializerData serializerData;
  59. static Hashtable serializerTypes = new Hashtable ();
  60. internal class SerializerData
  61. {
  62. public int UsageCount;
  63. public Type ReaderType;
  64. public MethodInfo ReaderMethod;
  65. public Type WriterType;
  66. public MethodInfo WriterMethod;
  67. public GenerationBatch Batch;
  68. public XmlSerializerImplementation Implementation = null;
  69. public XmlSerializationReader CreateReader () {
  70. if (ReaderType != null)
  71. return (XmlSerializationReader) Activator.CreateInstance (ReaderType);
  72. else if (Implementation != null)
  73. return Implementation.Reader;
  74. else
  75. return null;
  76. }
  77. public XmlSerializationWriter CreateWriter () {
  78. if (WriterType != null)
  79. return (XmlSerializationWriter) Activator.CreateInstance (WriterType);
  80. else if (Implementation != null)
  81. return Implementation.Writer;
  82. else
  83. return null;
  84. }
  85. }
  86. internal class GenerationBatch
  87. {
  88. public bool Done;
  89. public XmlMapping[] Maps;
  90. public SerializerData[] Datas;
  91. }
  92. static XmlSerializer ()
  93. {
  94. // The following options are available:
  95. // MONO_XMLSERIALIZER_DEBUG: when set to something != "no", it will
  96. // it will print the name of the generated file, and it won't
  97. // be deleted.
  98. // MONO_XMLSERIALIZER_THS: The code generator threshold. It can be:
  99. // no: does not use the generator, always the interpreter.
  100. // 0: always use the generator, wait until the generation is done.
  101. // any number: use the interpreted serializer until the specified
  102. // number of serializations is reached. At this point the generation
  103. // of the serializer will start in the background. The interpreter
  104. // will be used while the serializer is being generated.
  105. //
  106. // XmlSerializer will fall back to the interpreted serializer if
  107. // the code generation somehow fails. This can be avoided for
  108. // debugging pourposes by adding the "nofallback" option.
  109. // For example: MONO_XMLSERIALIZER_THS=0,nofallback
  110. #if TARGET_JVM
  111. string db = null;
  112. string th = null;
  113. generationThreshold = -1;
  114. backgroundGeneration = false;
  115. #else
  116. string db = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_DEBUG");
  117. string th = Environment.GetEnvironmentVariable ("MONO_XMLSERIALIZER_THS");
  118. if (th == null) {
  119. generationThreshold = 50;
  120. backgroundGeneration = true;
  121. } else {
  122. int i = th.IndexOf (',');
  123. if (i != -1) {
  124. if (th.Substring (i+1) == "nofallback")
  125. generatorFallback = false;
  126. th = th.Substring (0, i);
  127. }
  128. if (th.ToLower(CultureInfo.InvariantCulture) == "no")
  129. generationThreshold = -1;
  130. else {
  131. generationThreshold = int.Parse (th, CultureInfo.InvariantCulture);
  132. backgroundGeneration = (generationThreshold != 0);
  133. if (generationThreshold < 1) generationThreshold = 1;
  134. }
  135. }
  136. #endif
  137. deleteTempFiles = (db == null || db == "no");
  138. IDictionary table = (IDictionary) ConfigurationSettings.GetConfig("system.diagnostics");
  139. if (table != null)
  140. {
  141. table = (IDictionary) table["switches"];
  142. if (table != null)
  143. {
  144. string val = (string) table ["XmlSerialization.Compilation"];
  145. if (val == "1") deleteTempFiles = false;
  146. }
  147. }
  148. }
  149. #region Constructors
  150. protected XmlSerializer ()
  151. {
  152. customSerializer = true;
  153. }
  154. public XmlSerializer (Type type)
  155. : this (type, null, null, null, null)
  156. {
  157. }
  158. public XmlSerializer (XmlTypeMapping xmlTypeMapping)
  159. {
  160. typeMapping = xmlTypeMapping;
  161. }
  162. internal XmlSerializer (XmlMapping mapping, SerializerData data)
  163. {
  164. typeMapping = mapping;
  165. serializerData = data;
  166. }
  167. public XmlSerializer (Type type, string defaultNamespace)
  168. : this (type, null, null, null, defaultNamespace)
  169. {
  170. }
  171. public XmlSerializer (Type type, Type[] extraTypes)
  172. : this (type, null, extraTypes, null, null)
  173. {
  174. }
  175. public XmlSerializer (Type type, XmlAttributeOverrides overrides)
  176. : this (type, overrides, null, null, null)
  177. {
  178. }
  179. public XmlSerializer (Type type, XmlRootAttribute root)
  180. : this (type, null, null, root, null)
  181. {
  182. }
  183. public XmlSerializer (Type type,
  184. XmlAttributeOverrides overrides,
  185. Type [] extraTypes,
  186. XmlRootAttribute root,
  187. string defaultNamespace)
  188. {
  189. if (type == null)
  190. throw new ArgumentNullException ("type");
  191. XmlReflectionImporter importer = new XmlReflectionImporter (overrides, defaultNamespace);
  192. if (extraTypes != null)
  193. {
  194. foreach (Type intype in extraTypes)
  195. importer.IncludeType (intype);
  196. }
  197. typeMapping = importer.ImportTypeMapping (type, root, defaultNamespace);
  198. }
  199. internal XmlMapping Mapping
  200. {
  201. get { return typeMapping; }
  202. }
  203. #if NET_2_0
  204. [MonoTODO]
  205. public XmlSerializer (Type type,
  206. XmlAttributeOverrides overrides,
  207. Type [] extraTypes,
  208. XmlRootAttribute root,
  209. string defaultNamespace,
  210. string location,
  211. Evidence evidence)
  212. {
  213. }
  214. #endif
  215. #endregion // Constructors
  216. #region Events
  217. private XmlAttributeEventHandler onUnknownAttribute;
  218. private XmlElementEventHandler onUnknownElement;
  219. private XmlNodeEventHandler onUnknownNode;
  220. private UnreferencedObjectEventHandler onUnreferencedObject;
  221. public event XmlAttributeEventHandler UnknownAttribute
  222. {
  223. add { onUnknownAttribute += value; } remove { onUnknownAttribute -= value; }
  224. }
  225. public event XmlElementEventHandler UnknownElement
  226. {
  227. add { onUnknownElement += value; } remove { onUnknownElement -= value; }
  228. }
  229. public event XmlNodeEventHandler UnknownNode
  230. {
  231. add { onUnknownNode += value; } remove { onUnknownNode -= value; }
  232. }
  233. public event UnreferencedObjectEventHandler UnreferencedObject
  234. {
  235. add { onUnreferencedObject += value; } remove { onUnreferencedObject -= value; }
  236. }
  237. internal virtual void OnUnknownAttribute (XmlAttributeEventArgs e)
  238. {
  239. if (onUnknownAttribute != null) onUnknownAttribute(this, e);
  240. }
  241. internal virtual void OnUnknownElement (XmlElementEventArgs e)
  242. {
  243. if (onUnknownElement != null) onUnknownElement(this, e);
  244. }
  245. internal virtual void OnUnknownNode (XmlNodeEventArgs e)
  246. {
  247. if (onUnknownNode != null) onUnknownNode(this, e);
  248. }
  249. internal virtual void OnUnreferencedObject (UnreferencedObjectEventArgs e)
  250. {
  251. if (onUnreferencedObject != null) onUnreferencedObject(this, e);
  252. }
  253. #endregion // Events
  254. #region Methods
  255. public virtual bool CanDeserialize (XmlReader xmlReader)
  256. {
  257. xmlReader.MoveToContent ();
  258. if (typeMapping is XmlMembersMapping)
  259. return true;
  260. else
  261. return ((XmlTypeMapping)typeMapping).ElementName == xmlReader.LocalName;
  262. }
  263. protected virtual XmlSerializationReader CreateReader ()
  264. {
  265. // Must be implemented in derived class
  266. throw new NotImplementedException ();
  267. }
  268. protected virtual XmlSerializationWriter CreateWriter ()
  269. {
  270. // Must be implemented in derived class
  271. throw new NotImplementedException ();
  272. }
  273. public object Deserialize (Stream stream)
  274. {
  275. #if NET_2_0
  276. var s = new XmlReaderSettings () { IgnoreWhitespace = true };
  277. return Deserialize (XmlReader.Create (stream, s));
  278. #else
  279. XmlTextReader xmlReader = new XmlTextReader(stream);
  280. xmlReader.Normalization = true;
  281. xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
  282. return Deserialize(xmlReader);
  283. #endif
  284. }
  285. public object Deserialize (TextReader textReader)
  286. {
  287. #if NET_2_0
  288. var s = new XmlReaderSettings () { IgnoreWhitespace = true };
  289. return Deserialize (XmlReader.Create (textReader, s));
  290. #else
  291. XmlTextReader xmlReader = new XmlTextReader(textReader);
  292. xmlReader.Normalization = true;
  293. xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
  294. return Deserialize(xmlReader);
  295. #endif
  296. }
  297. public object Deserialize (XmlReader xmlReader)
  298. {
  299. XmlSerializationReader xsReader;
  300. if (customSerializer)
  301. xsReader = CreateReader ();
  302. else
  303. xsReader = CreateReader (typeMapping);
  304. xsReader.Initialize (xmlReader, this);
  305. return Deserialize (xsReader);
  306. }
  307. protected virtual object Deserialize (XmlSerializationReader reader)
  308. {
  309. if (customSerializer)
  310. // Must be implemented in derived class
  311. throw new NotImplementedException ();
  312. try {
  313. if (reader is XmlSerializationReaderInterpreter)
  314. return ((XmlSerializationReaderInterpreter) reader).ReadRoot ();
  315. else
  316. return serializerData.ReaderMethod.Invoke (reader, null);
  317. } catch (Exception ex) {
  318. if (ex is InvalidOperationException || ex is InvalidCastException)
  319. throw new InvalidOperationException ("There is an error in"
  320. + " XML document.", ex);
  321. throw;
  322. }
  323. }
  324. public static XmlSerializer [] FromMappings (XmlMapping [] mappings)
  325. {
  326. XmlSerializer[] sers = new XmlSerializer [mappings.Length];
  327. SerializerData[] datas = new SerializerData [mappings.Length];
  328. GenerationBatch batch = new GenerationBatch ();
  329. batch.Maps = mappings;
  330. batch.Datas = datas;
  331. for (int n=0; n<mappings.Length; n++)
  332. {
  333. if (mappings[n] != null)
  334. {
  335. SerializerData data = new SerializerData ();
  336. data.Batch = batch;
  337. sers[n] = new XmlSerializer (mappings[n], data);
  338. datas[n] = data;
  339. }
  340. }
  341. return sers;
  342. }
  343. public static XmlSerializer [] FromTypes (Type [] mappings)
  344. {
  345. XmlSerializer [] sers = new XmlSerializer [mappings.Length];
  346. for (int n=0; n<mappings.Length; n++)
  347. sers[n] = new XmlSerializer (mappings[n]);
  348. return sers;
  349. }
  350. protected virtual void Serialize (object o, XmlSerializationWriter writer)
  351. {
  352. if (customSerializer)
  353. // Must be implemented in derived class
  354. throw new NotImplementedException ();
  355. if (writer is XmlSerializationWriterInterpreter)
  356. ((XmlSerializationWriterInterpreter)writer).WriteRoot (o);
  357. else
  358. serializerData.WriterMethod.Invoke (writer, new object[] {o});
  359. }
  360. public void Serialize (Stream stream, object o)
  361. {
  362. XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
  363. xmlWriter.Formatting = Formatting.Indented;
  364. Serialize (xmlWriter, o, null);
  365. }
  366. public void Serialize (TextWriter textWriter, object o)
  367. {
  368. XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
  369. xmlWriter.Formatting = Formatting.Indented;
  370. Serialize (xmlWriter, o, null);
  371. }
  372. public void Serialize (XmlWriter xmlWriter, object o)
  373. {
  374. Serialize (xmlWriter, o, null);
  375. }
  376. public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
  377. {
  378. XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
  379. xmlWriter.Formatting = Formatting.Indented;
  380. Serialize (xmlWriter, o, namespaces);
  381. }
  382. public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
  383. {
  384. XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
  385. xmlWriter.Formatting = Formatting.Indented;
  386. Serialize (xmlWriter, o, namespaces);
  387. xmlWriter.Flush();
  388. }
  389. public void Serialize (XmlWriter writer, object o, XmlSerializerNamespaces namespaces)
  390. {
  391. XmlSerializationWriter xsWriter;
  392. try {
  393. if (customSerializer)
  394. xsWriter = CreateWriter ();
  395. else
  396. xsWriter = CreateWriter (typeMapping);
  397. if (namespaces == null || namespaces.Count == 0) {
  398. namespaces = new XmlSerializerNamespaces ();
  399. #if NET_2_0
  400. namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
  401. namespaces.Add ("xsd", XmlSchema.Namespace);
  402. #else
  403. namespaces.Add ("xsd", XmlSchema.Namespace);
  404. namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
  405. #endif
  406. }
  407. xsWriter.Initialize (writer, namespaces);
  408. Serialize (o, xsWriter);
  409. writer.Flush ();
  410. } catch (Exception ex) {
  411. if (ex is TargetInvocationException)
  412. ex = ex.InnerException;
  413. if (ex is InvalidOperationException || ex is InvalidCastException)
  414. throw new InvalidOperationException ("There was an error generating" +
  415. " the XML document.", ex);
  416. throw;
  417. }
  418. }
  419. #if NET_2_0
  420. [MonoTODO]
  421. public object Deserialize (XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
  422. {
  423. throw new NotImplementedException ();
  424. }
  425. [MonoTODO]
  426. public object Deserialize (XmlReader xmlReader, string encodingStyle)
  427. {
  428. throw new NotImplementedException ();
  429. }
  430. [MonoTODO]
  431. public object Deserialize (XmlReader xmlReader, XmlDeserializationEvents events)
  432. {
  433. throw new NotImplementedException ();
  434. }
  435. [MonoTODO]
  436. public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Evidence evidence)
  437. {
  438. throw new NotImplementedException ();
  439. }
  440. [MonoTODO]
  441. public static XmlSerializer[] FromMappings (XmlMapping[] mappings, Type type)
  442. {
  443. throw new NotImplementedException ();
  444. }
  445. #if !TARGET_JVM
  446. public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings)
  447. {
  448. return GenerateSerializer (types, mappings, null);
  449. }
  450. [MonoTODO]
  451. public static Assembly GenerateSerializer (Type[] types, XmlMapping[] mappings, CompilerParameters parameters)
  452. {
  453. GenerationBatch batch = new GenerationBatch ();
  454. batch.Maps = mappings;
  455. batch.Datas = new SerializerData [mappings.Length];
  456. for (int n=0; n<mappings.Length; n++) {
  457. SerializerData data = new SerializerData ();
  458. data.Batch = batch;
  459. batch.Datas [n] = data;
  460. }
  461. return GenerateSerializers (batch, parameters);
  462. }
  463. #endif
  464. public static string GetXmlSerializerAssemblyName (Type type)
  465. {
  466. return type.Assembly.GetName().Name + ".XmlSerializers";
  467. }
  468. public static string GetXmlSerializerAssemblyName (Type type, string defaultNamespace)
  469. {
  470. return GetXmlSerializerAssemblyName (type) + "." + defaultNamespace.GetHashCode ();
  471. }
  472. [MonoTODO]
  473. public void Serialize (XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle)
  474. {
  475. throw new NotImplementedException ();
  476. }
  477. [MonoNotSupported("")]
  478. public void Serialize (XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, string encodingStyle, string id)
  479. {
  480. throw new NotImplementedException ();
  481. }
  482. #endif
  483. XmlSerializationWriter CreateWriter (XmlMapping typeMapping)
  484. {
  485. XmlSerializationWriter writer;
  486. lock (this) {
  487. if (serializerData != null) {
  488. lock (serializerData) {
  489. writer = serializerData.CreateWriter ();
  490. }
  491. if (writer != null) return writer;
  492. }
  493. }
  494. if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
  495. return new XmlSerializationWriterInterpreter (typeMapping);
  496. CheckGeneratedTypes (typeMapping);
  497. lock (this) {
  498. lock (serializerData) {
  499. writer = serializerData.CreateWriter ();
  500. }
  501. if (writer != null) return writer;
  502. if (!generatorFallback)
  503. throw new InvalidOperationException ("Error while generating serializer");
  504. }
  505. return new XmlSerializationWriterInterpreter (typeMapping);
  506. }
  507. XmlSerializationReader CreateReader (XmlMapping typeMapping)
  508. {
  509. XmlSerializationReader reader;
  510. lock (this) {
  511. if (serializerData != null) {
  512. lock (serializerData) {
  513. reader = serializerData.CreateReader ();
  514. }
  515. if (reader != null) return reader;
  516. }
  517. }
  518. if (!typeMapping.Source.CanBeGenerated || generationThreshold == -1)
  519. return new XmlSerializationReaderInterpreter (typeMapping);
  520. CheckGeneratedTypes (typeMapping);
  521. lock (this) {
  522. lock (serializerData) {
  523. reader = serializerData.CreateReader ();
  524. }
  525. if (reader != null) return reader;
  526. if (!generatorFallback)
  527. throw new InvalidOperationException ("Error while generating serializer");
  528. }
  529. return new XmlSerializationReaderInterpreter (typeMapping);
  530. }
  531. #if TARGET_JVM
  532. void CheckGeneratedTypes (XmlMapping typeMapping)
  533. {
  534. throw new NotImplementedException();
  535. }
  536. void GenerateSerializersAsync (GenerationBatch batch)
  537. {
  538. throw new NotImplementedException();
  539. }
  540. void RunSerializerGeneration (object obj)
  541. {
  542. throw new NotImplementedException();
  543. }
  544. #else
  545. void CheckGeneratedTypes (XmlMapping typeMapping)
  546. {
  547. lock (this)
  548. {
  549. if (serializerData == null)
  550. {
  551. lock (serializerTypes)
  552. {
  553. serializerData = (SerializerData) serializerTypes [typeMapping.Source];
  554. if (serializerData == null) {
  555. serializerData = new SerializerData();
  556. serializerTypes [typeMapping.Source] = serializerData;
  557. }
  558. }
  559. }
  560. }
  561. bool generate = false;
  562. lock (serializerData)
  563. {
  564. generate = (++serializerData.UsageCount == generationThreshold);
  565. }
  566. if (generate)
  567. {
  568. if (serializerData.Batch != null)
  569. GenerateSerializersAsync (serializerData.Batch);
  570. else
  571. {
  572. GenerationBatch batch = new GenerationBatch ();
  573. batch.Maps = new XmlMapping[] {typeMapping};
  574. batch.Datas = new SerializerData[] {serializerData};
  575. GenerateSerializersAsync (batch);
  576. }
  577. }
  578. }
  579. void GenerateSerializersAsync (GenerationBatch batch)
  580. {
  581. if (batch.Maps.Length != batch.Datas.Length)
  582. throw new ArgumentException ("batch");
  583. lock (batch)
  584. {
  585. if (batch.Done) return;
  586. batch.Done = true;
  587. }
  588. if (backgroundGeneration)
  589. ThreadPool.QueueUserWorkItem (new WaitCallback (RunSerializerGeneration), batch);
  590. else
  591. RunSerializerGeneration (batch);
  592. }
  593. void RunSerializerGeneration (object obj)
  594. {
  595. try
  596. {
  597. GenerationBatch batch = (GenerationBatch) obj;
  598. batch = LoadFromSatelliteAssembly (batch);
  599. if (batch != null)
  600. GenerateSerializers (batch, null);
  601. }
  602. catch (Exception ex)
  603. {
  604. Console.WriteLine (ex);
  605. }
  606. }
  607. static Assembly GenerateSerializers (GenerationBatch batch, CompilerParameters cp)
  608. {
  609. DateTime tim = DateTime.Now;
  610. XmlMapping[] maps = batch.Maps;
  611. if (cp == null) {
  612. cp = new CompilerParameters();
  613. cp.IncludeDebugInformation = false;
  614. cp.GenerateInMemory = true;
  615. cp.TempFiles.KeepFiles = !deleteTempFiles;
  616. }
  617. string file = cp.TempFiles.AddExtension ("cs");
  618. StreamWriter sw = new StreamWriter (file);
  619. if (!deleteTempFiles)
  620. Console.WriteLine ("Generating " + file);
  621. SerializationCodeGenerator gen = new SerializationCodeGenerator (maps);
  622. try
  623. {
  624. gen.GenerateSerializers (sw);
  625. }
  626. catch (Exception ex)
  627. {
  628. Console.WriteLine ("Serializer could not be generated");
  629. Console.WriteLine (ex);
  630. cp.TempFiles.Delete ();
  631. return null;
  632. }
  633. sw.Close ();
  634. CSharpCodeProvider provider = new CSharpCodeProvider();
  635. ICodeCompiler comp = provider.CreateCompiler ();
  636. cp.GenerateExecutable = false;
  637. foreach (Type rtype in gen.ReferencedTypes)
  638. {
  639. if (!cp.ReferencedAssemblies.Contains (rtype.Assembly.Location))
  640. cp.ReferencedAssemblies.Add (rtype.Assembly.Location);
  641. }
  642. if (!cp.ReferencedAssemblies.Contains ("System.dll"))
  643. cp.ReferencedAssemblies.Add ("System.dll");
  644. if (!cp.ReferencedAssemblies.Contains ("System.Xml"))
  645. cp.ReferencedAssemblies.Add ("System.Xml");
  646. if (!cp.ReferencedAssemblies.Contains ("System.Data"))
  647. cp.ReferencedAssemblies.Add ("System.Data");
  648. CompilerResults res = comp.CompileAssemblyFromFile (cp, file);
  649. if (res.Errors.HasErrors || res.CompiledAssembly == null) {
  650. Console.WriteLine ("Error while compiling generated serializer");
  651. foreach (CompilerError error in res.Errors)
  652. Console.WriteLine (error);
  653. cp.TempFiles.Delete ();
  654. return null;
  655. }
  656. GenerationResult[] results = gen.GenerationResults;
  657. for (int n=0; n<results.Length; n++)
  658. {
  659. GenerationResult gres = results[n];
  660. SerializerData sd = batch.Datas [n];
  661. lock (sd)
  662. {
  663. sd.WriterType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.WriterClassName);
  664. sd.ReaderType = res.CompiledAssembly.GetType (gres.Namespace + "." + gres.ReaderClassName);
  665. sd.WriterMethod = sd.WriterType.GetMethod (gres.WriteMethodName);
  666. sd.ReaderMethod = sd.ReaderType.GetMethod (gres.ReadMethodName);
  667. sd.Batch = null;
  668. }
  669. }
  670. cp.TempFiles.Delete ();
  671. if (!deleteTempFiles)
  672. Console.WriteLine ("Generation finished - " + (DateTime.Now - tim).TotalMilliseconds + " ms");
  673. return res.CompiledAssembly;
  674. }
  675. #endif
  676. #if NET_2_0
  677. GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
  678. {
  679. return batch;
  680. }
  681. #else
  682. GenerationBatch LoadFromSatelliteAssembly (GenerationBatch batch)
  683. {
  684. return batch;
  685. }
  686. #endif
  687. #endregion // Methods
  688. }
  689. }