XmlSerializer.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSerializer.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. //------------------------------------------------------------------------------
  7. namespace System.Xml.Serialization {
  8. using System.Reflection;
  9. using System.Collections;
  10. using System.IO;
  11. using System.Xml.Schema;
  12. using System;
  13. using System.Text;
  14. using System.Threading;
  15. using System.Globalization;
  16. using System.Security;
  17. using System.Security.Permissions;
  18. using System.Security.Policy;
  19. using System.Xml.Serialization.Configuration;
  20. using System.Diagnostics;
  21. using System.CodeDom.Compiler;
  22. using System.Runtime.Versioning;
  23. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlDeserializationEvents"]/*' />
  24. /// <devdoc>
  25. /// <para>[To be supplied.]</para>
  26. /// </devdoc>
  27. public struct XmlDeserializationEvents {
  28. XmlNodeEventHandler onUnknownNode;
  29. XmlAttributeEventHandler onUnknownAttribute;
  30. XmlElementEventHandler onUnknownElement;
  31. UnreferencedObjectEventHandler onUnreferencedObject;
  32. internal object sender;
  33. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlDeserializationEvents.OnUnknownNode"]/*' />
  34. public XmlNodeEventHandler OnUnknownNode {
  35. get {
  36. return onUnknownNode;
  37. }
  38. set {
  39. onUnknownNode = value;
  40. }
  41. }
  42. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlDeserializationEvents.OnUnknownAttribute"]/*' />
  43. public XmlAttributeEventHandler OnUnknownAttribute {
  44. get {
  45. return onUnknownAttribute;
  46. }
  47. set {
  48. onUnknownAttribute = value;
  49. }
  50. }
  51. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlDeserializationEvents.OnUnknownElement"]/*' />
  52. public XmlElementEventHandler OnUnknownElement {
  53. get {
  54. return onUnknownElement;
  55. }
  56. set {
  57. onUnknownElement = value;
  58. }
  59. }
  60. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlDeserializationEvents.OnUnreferencedObject"]/*' />
  61. public UnreferencedObjectEventHandler OnUnreferencedObject {
  62. get {
  63. return onUnreferencedObject;
  64. }
  65. set {
  66. onUnreferencedObject = value;
  67. }
  68. }
  69. }
  70. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation"]/*' />
  71. ///<internalonly/>
  72. /// <devdoc>
  73. /// <para>[To be supplied.]</para>
  74. /// </devdoc>
  75. public abstract class XmlSerializerImplementation {
  76. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.Reader"]/*' />
  77. public virtual XmlSerializationReader Reader{ get {throw new NotSupportedException();} }
  78. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.Writer"]/*' />
  79. public virtual XmlSerializationWriter Writer{ get {throw new NotSupportedException();} }
  80. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.ReadMethods"]/*' />
  81. public virtual Hashtable ReadMethods{ get {throw new NotSupportedException();} }
  82. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.WriteMethods"]/*' />
  83. public virtual Hashtable WriteMethods{ get {throw new NotSupportedException();} }
  84. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.TypedSerializers"]/*' />
  85. public virtual Hashtable TypedSerializers{ get {throw new NotSupportedException();} }
  86. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.CanSerialize"]/*' />
  87. public virtual bool CanSerialize(Type type){ throw new NotSupportedException(); }
  88. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializerImplementation.GetSerializer"]/*' />
  89. public virtual XmlSerializer GetSerializer(Type type){ throw new NotSupportedException(); }
  90. }
  91. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer"]/*' />
  92. /// <devdoc>
  93. /// <para>[To be supplied.]</para>
  94. /// </devdoc>
  95. public class XmlSerializer {
  96. TempAssembly tempAssembly;
  97. bool typedSerializer;
  98. Type primitiveType;
  99. XmlMapping mapping;
  100. XmlDeserializationEvents events = new XmlDeserializationEvents();
  101. static TempAssemblyCache cache = new TempAssemblyCache();
  102. static volatile XmlSerializerNamespaces defaultNamespaces;
  103. static XmlSerializerNamespaces DefaultNamespaces {
  104. get {
  105. if (defaultNamespaces == null) {
  106. XmlSerializerNamespaces nss = new XmlSerializerNamespaces();
  107. nss.AddInternal("xsi", XmlSchema.InstanceNamespace);
  108. nss.AddInternal("xsd", XmlSchema.Namespace);
  109. if (defaultNamespaces == null) {
  110. defaultNamespaces = nss;
  111. }
  112. }
  113. return defaultNamespaces;
  114. }
  115. }
  116. static Hashtable xmlSerializerTable = new Hashtable();
  117. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer8"]/*' />
  118. ///<internalonly/>
  119. protected XmlSerializer() {
  120. }
  121. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer"]/*' />
  122. /// <devdoc>
  123. /// <para>[To be supplied.]</para>
  124. /// </devdoc>
  125. public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace) :
  126. this (type, overrides, extraTypes, root, defaultNamespace, null) {
  127. }
  128. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer2"]/*' />
  129. /// <devdoc>
  130. /// <para>[To be supplied.]</para>
  131. /// </devdoc>
  132. public XmlSerializer(Type type, XmlRootAttribute root) : this(type, null, new Type[0], root, null, null) {
  133. }
  134. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer3"]/*' />
  135. /// <devdoc>
  136. /// <para>[To be supplied.]</para>
  137. /// </devdoc>
  138. public XmlSerializer(Type type, Type[] extraTypes) : this(type, null, extraTypes, null, null, null) {
  139. }
  140. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer4"]/*' />
  141. /// <devdoc>
  142. /// <para>[To be supplied.]</para>
  143. /// </devdoc>
  144. public XmlSerializer(Type type, XmlAttributeOverrides overrides) : this(type, overrides, new Type[0], null, null, null) {
  145. }
  146. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer5"]/*' />
  147. /// <devdoc>
  148. /// <para>[To be supplied.]</para>
  149. /// </devdoc>
  150. public XmlSerializer(XmlTypeMapping xmlTypeMapping) {
  151. tempAssembly = GenerateTempAssembly(xmlTypeMapping);
  152. this.mapping = xmlTypeMapping;
  153. }
  154. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer6"]/*' />
  155. /// <devdoc>
  156. /// <para>[To be supplied.]</para>
  157. /// </devdoc>
  158. public XmlSerializer(Type type) : this(type, (string)null) {
  159. }
  160. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer1"]/*' />
  161. /// <devdoc>
  162. /// <para>[To be supplied.]</para>
  163. /// </devdoc>
  164. public XmlSerializer(Type type, string defaultNamespace) {
  165. if (type == null)
  166. throw new ArgumentNullException("type");
  167. this.mapping = GetKnownMapping(type, defaultNamespace);
  168. if (this.mapping != null) {
  169. this.primitiveType = type;
  170. return;
  171. }
  172. tempAssembly = cache[defaultNamespace, type];
  173. if (tempAssembly == null) {
  174. lock (cache) {
  175. tempAssembly = cache[defaultNamespace, type];
  176. if (tempAssembly == null) {
  177. XmlSerializerImplementation contract;
  178. Assembly assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out contract);
  179. if (assembly == null) {
  180. // need to reflect and generate new serialization assembly
  181. XmlReflectionImporter importer = new XmlReflectionImporter(defaultNamespace);
  182. this.mapping = importer.ImportTypeMapping(type, null, defaultNamespace);
  183. tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace);
  184. }
  185. else {
  186. // we found the pre-generated assembly, now make sure that the assembly has the right serializer
  187. // try to avoid the reflection step, need to get ElementName, namespace and the Key form the type
  188. this.mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
  189. tempAssembly = new TempAssembly(new XmlMapping[] { this.mapping }, assembly, contract);
  190. }
  191. }
  192. cache.Add(defaultNamespace, type, tempAssembly);
  193. }
  194. }
  195. if (mapping == null) {
  196. mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace);
  197. }
  198. }
  199. public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location)
  200. #pragma warning disable 618 // Passing through null evidence to keep the .ctor code centralized
  201. : this (type, overrides, extraTypes, root, defaultNamespace, location, null) {
  202. #pragma warning restore 618
  203. }
  204. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.XmlSerializer7"]/*' />
  205. /// <devdoc>
  206. /// <para>[To be supplied.]</para>
  207. /// </devdoc>
  208. [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use a XmlSerializer constructor overload which does not take an Evidence parameter. See http://go2.microsoft.com/fwlink/?LinkId=131738 for more information.")]
  209. public XmlSerializer(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace, string location, Evidence evidence) {
  210. if (type == null)
  211. throw new ArgumentNullException("type");
  212. XmlReflectionImporter importer = new XmlReflectionImporter(overrides, defaultNamespace);
  213. if (extraTypes != null)
  214. {
  215. for (int i = 0; i < extraTypes.Length; i++)
  216. importer.IncludeType(extraTypes[i]);
  217. }
  218. this.mapping = importer.ImportTypeMapping(type, root, defaultNamespace);
  219. if (location != null || evidence != null) {
  220. DemandForUserLocationOrEvidence();
  221. }
  222. tempAssembly = GenerateTempAssembly(this.mapping, type, defaultNamespace, location, evidence);
  223. }
  224. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  225. void DemandForUserLocationOrEvidence() {
  226. // Ensure full trust before asserting full file access to the user-provided location or evidence
  227. }
  228. internal static TempAssembly GenerateTempAssembly(XmlMapping xmlMapping) {
  229. return GenerateTempAssembly(xmlMapping, null, null);
  230. }
  231. internal static TempAssembly GenerateTempAssembly(XmlMapping xmlMapping, Type type, string defaultNamespace) {
  232. if (xmlMapping == null)
  233. throw new ArgumentNullException("xmlMapping");
  234. return new TempAssembly(new XmlMapping[] { xmlMapping }, new Type[] {type}, defaultNamespace, null, null);
  235. }
  236. internal static TempAssembly GenerateTempAssembly(XmlMapping xmlMapping, Type type, string defaultNamespace, string location, Evidence evidence) {
  237. return new TempAssembly(new XmlMapping[] { xmlMapping }, new Type[] {type}, defaultNamespace, location, evidence);
  238. }
  239. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize"]/*' />
  240. /// <devdoc>
  241. /// <para>[To be supplied.]</para>
  242. /// </devdoc>
  243. public void Serialize(TextWriter textWriter, object o) {
  244. Serialize(textWriter, o, null);
  245. }
  246. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize1"]/*' />
  247. /// <devdoc>
  248. /// <para>[To be supplied.]</para>
  249. /// </devdoc>
  250. public void Serialize(TextWriter textWriter, object o, XmlSerializerNamespaces namespaces) {
  251. XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
  252. xmlWriter.Formatting = Formatting.Indented;
  253. xmlWriter.Indentation = 2;
  254. Serialize(xmlWriter, o, namespaces);
  255. }
  256. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize2"]/*' />
  257. /// <devdoc>
  258. /// <para>[To be supplied.]</para>
  259. /// </devdoc>
  260. public void Serialize(Stream stream, object o) {
  261. Serialize(stream, o, null);
  262. }
  263. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize3"]/*' />
  264. /// <devdoc>
  265. /// <para>[To be supplied.]</para>
  266. /// </devdoc>
  267. public void Serialize(Stream stream, object o, XmlSerializerNamespaces namespaces) {
  268. XmlTextWriter xmlWriter = new XmlTextWriter(stream, null);
  269. xmlWriter.Formatting = Formatting.Indented;
  270. xmlWriter.Indentation = 2;
  271. Serialize(xmlWriter, o, namespaces);
  272. }
  273. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize4"]/*' />
  274. /// <devdoc>
  275. /// <para>[To be supplied.]</para>
  276. /// </devdoc>
  277. public void Serialize(XmlWriter xmlWriter, object o) {
  278. Serialize(xmlWriter, o, null);
  279. }
  280. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize5"]/*' />
  281. /// <devdoc>
  282. /// <para>[To be supplied.]</para>
  283. /// </devdoc>
  284. public void Serialize(XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces) {
  285. Serialize(xmlWriter, o, namespaces, null);
  286. }
  287. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize6"]/*' />
  288. public void Serialize(XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle) {
  289. Serialize(xmlWriter, o, namespaces, encodingStyle, null);
  290. }
  291. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize6"]/*' />
  292. public void Serialize(XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle, string id) {
  293. try {
  294. if (primitiveType != null) {
  295. if (encodingStyle != null && encodingStyle.Length > 0) {
  296. throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEncodingNotEncoded1, encodingStyle));
  297. }
  298. SerializePrimitive(xmlWriter, o, namespaces);
  299. }
  300. else if (tempAssembly == null || typedSerializer) {
  301. XmlSerializationWriter writer = CreateWriter();
  302. writer.Init(xmlWriter, namespaces == null || namespaces.Count == 0 ? DefaultNamespaces : namespaces, encodingStyle, id, tempAssembly);
  303. try {
  304. Serialize(o, writer);
  305. }
  306. finally {
  307. writer.Dispose();
  308. }
  309. }
  310. else
  311. tempAssembly.InvokeWriter(mapping, xmlWriter, o, namespaces == null || namespaces.Count == 0 ? DefaultNamespaces : namespaces, encodingStyle, id);
  312. }
  313. catch (Exception e) {
  314. if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  315. throw;
  316. }
  317. if (e is TargetInvocationException)
  318. e = e.InnerException;
  319. throw new InvalidOperationException(Res.GetString(Res.XmlGenError), e);
  320. }
  321. xmlWriter.Flush();
  322. }
  323. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize"]/*' />
  324. /// <devdoc>
  325. /// <para>[To be supplied.]</para>
  326. /// </devdoc>
  327. public object Deserialize(Stream stream) {
  328. XmlTextReader xmlReader = new XmlTextReader(stream);
  329. xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
  330. xmlReader.Normalization = true;
  331. xmlReader.XmlResolver = null;
  332. return Deserialize(xmlReader, null);
  333. }
  334. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize1"]/*' />
  335. /// <devdoc>
  336. /// <para>[To be supplied.]</para>
  337. /// </devdoc>
  338. public object Deserialize(TextReader textReader) {
  339. XmlTextReader xmlReader = new XmlTextReader(textReader);
  340. xmlReader.WhitespaceHandling = WhitespaceHandling.Significant;
  341. xmlReader.Normalization = true;
  342. xmlReader.XmlResolver = null;
  343. return Deserialize(xmlReader, null);
  344. }
  345. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize2"]/*' />
  346. /// <devdoc>
  347. /// <para>[To be supplied.]</para>
  348. /// </devdoc>
  349. public object Deserialize(XmlReader xmlReader) {
  350. return Deserialize(xmlReader, null);
  351. }
  352. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize3"]/*' />
  353. public object Deserialize(XmlReader xmlReader, XmlDeserializationEvents events) {
  354. return Deserialize(xmlReader, null, events);
  355. }
  356. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize4"]/*' />
  357. public object Deserialize(XmlReader xmlReader, string encodingStyle) {
  358. return Deserialize(xmlReader, encodingStyle, this.events);
  359. }
  360. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize5"]/*' />
  361. public object Deserialize(XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events) {
  362. events.sender = this;
  363. try {
  364. if (primitiveType != null) {
  365. if (encodingStyle != null && encodingStyle.Length > 0) {
  366. throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEncodingNotEncoded1, encodingStyle));
  367. }
  368. return DeserializePrimitive(xmlReader, events);
  369. }
  370. else if (tempAssembly == null || typedSerializer) {
  371. XmlSerializationReader reader = CreateReader();
  372. reader.Init(xmlReader, events, encodingStyle, tempAssembly);
  373. try {
  374. return Deserialize(reader);
  375. }
  376. finally {
  377. reader.Dispose();
  378. }
  379. }
  380. else {
  381. return tempAssembly.InvokeReader(mapping, xmlReader, events, encodingStyle);
  382. }
  383. }
  384. catch (Exception e) {
  385. if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  386. throw;
  387. }
  388. if (e is TargetInvocationException)
  389. e = e.InnerException;
  390. if (xmlReader is IXmlLineInfo) {
  391. IXmlLineInfo lineInfo = (IXmlLineInfo)xmlReader;
  392. throw new InvalidOperationException(Res.GetString(Res.XmlSerializeErrorDetails, lineInfo.LineNumber.ToString(CultureInfo.InvariantCulture), lineInfo.LinePosition.ToString(CultureInfo.InvariantCulture)), e);
  393. }
  394. else {
  395. throw new InvalidOperationException(Res.GetString(Res.XmlSerializeError), e);
  396. }
  397. }
  398. }
  399. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.CanDeserialize"]/*' />
  400. /// <devdoc>
  401. /// <para>[To be supplied.]</para>
  402. /// </devdoc>
  403. public virtual bool CanDeserialize(XmlReader xmlReader) {
  404. if (primitiveType != null) {
  405. TypeDesc typeDesc = (TypeDesc)TypeScope.PrimtiveTypes[primitiveType];
  406. return xmlReader.IsStartElement(typeDesc.DataType.Name, string.Empty);
  407. }
  408. else if (tempAssembly != null) {
  409. return tempAssembly.CanRead(mapping, xmlReader);
  410. }
  411. else {
  412. return false;
  413. }
  414. }
  415. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.FromMappings"]/*' />
  416. /// <devdoc>
  417. /// <para>[To be supplied.]</para>
  418. /// </devdoc>
  419. [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
  420. public static XmlSerializer[] FromMappings(XmlMapping[] mappings) {
  421. return FromMappings(mappings, (Type)null);
  422. }
  423. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.FromMappings1"]/*' />
  424. /// <devdoc>
  425. /// <para>[To be supplied.]</para>
  426. /// </devdoc>
  427. [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
  428. public static XmlSerializer[] FromMappings(XmlMapping[] mappings, Type type) {
  429. if (mappings == null || mappings.Length == 0) return new XmlSerializer[0];
  430. XmlSerializerImplementation contract = null;
  431. Assembly assembly = type == null ? null : TempAssembly.LoadGeneratedAssembly(type, null, out contract);
  432. TempAssembly tempAssembly = null;
  433. if (assembly == null) {
  434. if (XmlMapping.IsShallow(mappings)) {
  435. return new XmlSerializer[0];
  436. }
  437. else {
  438. if (type == null) {
  439. tempAssembly = new TempAssembly(mappings, new Type[] { type }, null, null, null);
  440. XmlSerializer[] serializers = new XmlSerializer[mappings.Length];
  441. contract = tempAssembly.Contract;
  442. for (int i = 0; i < serializers.Length; i++) {
  443. serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key];
  444. serializers[i].SetTempAssembly(tempAssembly, mappings[i]);
  445. }
  446. return serializers;
  447. }
  448. else {
  449. // Use XmlSerializer cache when the type is not null.
  450. return GetSerializersFromCache(mappings, type);
  451. }
  452. }
  453. }
  454. else {
  455. XmlSerializer[] serializers = new XmlSerializer[mappings.Length];
  456. for (int i = 0; i < serializers.Length; i++)
  457. serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key];
  458. return serializers;
  459. }
  460. }
  461. static XmlSerializer[] GetSerializersFromCache(XmlMapping[] mappings, Type type) {
  462. XmlSerializer[] serializers = new XmlSerializer[mappings.Length];
  463. Hashtable typedMappingTable = null;
  464. lock (xmlSerializerTable) {
  465. typedMappingTable = xmlSerializerTable[type] as Hashtable;
  466. if (typedMappingTable == null) {
  467. typedMappingTable = new Hashtable();
  468. xmlSerializerTable[type] = typedMappingTable;
  469. }
  470. }
  471. lock (typedMappingTable) {
  472. Hashtable pendingKeys = new Hashtable();
  473. for (int i = 0; i < mappings.Length; i++) {
  474. XmlSerializerMappingKey mappingKey = new XmlSerializerMappingKey(mappings[i]);
  475. serializers[i] = typedMappingTable[mappingKey] as XmlSerializer;
  476. if (serializers[i] == null) {
  477. pendingKeys.Add(mappingKey, i);
  478. }
  479. }
  480. if (pendingKeys.Count > 0) {
  481. XmlMapping[] pendingMappings = new XmlMapping[pendingKeys.Count];
  482. int index = 0;
  483. foreach (XmlSerializerMappingKey mappingKey in pendingKeys.Keys) {
  484. pendingMappings[index++] = mappingKey.Mapping;
  485. }
  486. TempAssembly tempAssembly = new TempAssembly(pendingMappings, new Type[] { type }, null, null, null);
  487. XmlSerializerImplementation contract = tempAssembly.Contract;
  488. foreach (XmlSerializerMappingKey mappingKey in pendingKeys.Keys) {
  489. index = (int)pendingKeys[mappingKey];
  490. serializers[index] = (XmlSerializer)contract.TypedSerializers[mappingKey.Mapping.Key];
  491. serializers[index].SetTempAssembly(tempAssembly, mappingKey.Mapping);
  492. typedMappingTable[mappingKey] = serializers[index];
  493. }
  494. }
  495. }
  496. return serializers;
  497. }
  498. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.FromMappings3"]/*' />
  499. /// <devdoc>
  500. /// <para>[To be supplied.]</para>
  501. /// </devdoc>
  502. [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
  503. [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of FromMappings which does not take an Evidence parameter. See http://go2.microsoft.com/fwlink/?LinkId=131738 for more information.")]
  504. public static XmlSerializer[] FromMappings(XmlMapping[] mappings, Evidence evidence) {
  505. if (mappings == null || mappings.Length == 0) return new XmlSerializer[0];
  506. if (XmlMapping.IsShallow(mappings)) {
  507. return new XmlSerializer[0];
  508. }
  509. TempAssembly tempAssembly = new TempAssembly(mappings, new Type[0], null, null, evidence);
  510. XmlSerializerImplementation contract = tempAssembly.Contract;
  511. XmlSerializer[] serializers = new XmlSerializer[mappings.Length];
  512. for (int i = 0; i < serializers.Length; i++) {
  513. serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key];
  514. }
  515. return serializers;
  516. }
  517. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.GenerateSerializer"]/*' />
  518. /// <devdoc>
  519. /// <para>[To be supplied.]</para>
  520. /// </devdoc>
  521. [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
  522. public static Assembly GenerateSerializer(Type[] types, XmlMapping[] mappings) {
  523. CompilerParameters parameters = new CompilerParameters();
  524. parameters.TempFiles = new TempFileCollection();
  525. parameters.GenerateInMemory = false;
  526. parameters.IncludeDebugInformation = false;
  527. return GenerateSerializer(types, mappings, parameters);
  528. }
  529. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.GenerateSerializer1"]/*' />
  530. /// <devdoc>
  531. /// <para>[To be supplied.]</para>
  532. /// </devdoc>
  533. // SxS: This method does not take any resource name and does not expose any resources to the caller.
  534. // It's OK to suppress the SxS warning.
  535. [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
  536. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  537. [ResourceExposure(ResourceScope.None)]
  538. public static Assembly GenerateSerializer(Type[] types, XmlMapping[] mappings, CompilerParameters parameters) {
  539. if (types == null || types.Length == 0)
  540. return null;
  541. if (mappings == null)
  542. throw new ArgumentNullException("mappings");
  543. if (XmlMapping.IsShallow(mappings)) {
  544. throw new InvalidOperationException(Res.GetString(Res.XmlMelformMapping));
  545. }
  546. Assembly assembly = null;
  547. for (int i = 0; i < types.Length; i ++) {
  548. Type type = types[i];
  549. if (DynamicAssemblies.IsTypeDynamic(type)) {
  550. throw new InvalidOperationException(Res.GetString(Res.XmlPregenTypeDynamic, type.FullName));
  551. }
  552. if (assembly == null)
  553. assembly = type.Assembly;
  554. else if (type.Assembly != assembly) {
  555. throw new ArgumentException(Res.GetString(Res.XmlPregenOrphanType, type.FullName, assembly.Location), "types");
  556. }
  557. }
  558. return TempAssembly.GenerateAssembly(mappings, types, null, null, XmlSerializerCompilerParameters.Create(parameters, /* needTempDirAccess = */ true), assembly, new Hashtable());
  559. }
  560. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.FromTypes"]/*' />
  561. /// <devdoc>
  562. /// <para>[To be supplied.]</para>
  563. /// </devdoc>
  564. public static XmlSerializer[] FromTypes(Type[] types) {
  565. if (types == null)
  566. return new XmlSerializer[0];
  567. XmlReflectionImporter importer = new XmlReflectionImporter();
  568. XmlTypeMapping[] mappings = new XmlTypeMapping[types.Length];
  569. for (int i = 0; i < types.Length; i++) {
  570. mappings[i] = importer.ImportTypeMapping(types[i]);
  571. }
  572. return FromMappings(mappings);
  573. }
  574. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.GetXmlSerializerAssemblyName"]/*' />
  575. /// <devdoc>
  576. /// <para>[To be supplied.]</para>
  577. /// </devdoc>
  578. [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
  579. public static string GetXmlSerializerAssemblyName(Type type) {
  580. return GetXmlSerializerAssemblyName(type, null);
  581. }
  582. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.GetXmlSerializerAssemblyName"]/*' />
  583. /// <devdoc>
  584. /// <para>[To be supplied.]</para>
  585. /// </devdoc>
  586. [PermissionSet(SecurityAction.Demand, Name="FullTrust")]
  587. public static string GetXmlSerializerAssemblyName(Type type, string defaultNamespace) {
  588. if (type == null) {
  589. throw new ArgumentNullException("type");
  590. }
  591. return Compiler.GetTempAssemblyName(type.Assembly.GetName(), defaultNamespace);
  592. }
  593. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.UnknownNode"]/*' />
  594. /// <devdoc>
  595. /// <para>[To be supplied.]</para>
  596. /// </devdoc>
  597. public event XmlNodeEventHandler UnknownNode {
  598. add {
  599. events.OnUnknownNode += value;
  600. }
  601. remove {
  602. events.OnUnknownNode -= value;
  603. }
  604. }
  605. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.UnknownAttribute"]/*' />
  606. /// <devdoc>
  607. /// <para>[To be supplied.]</para>
  608. /// </devdoc>
  609. public event XmlAttributeEventHandler UnknownAttribute {
  610. add {
  611. events.OnUnknownAttribute += value;
  612. }
  613. remove {
  614. events.OnUnknownAttribute -= value;
  615. }
  616. }
  617. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.UnknownElement"]/*' />
  618. public event XmlElementEventHandler UnknownElement {
  619. add {
  620. events.OnUnknownElement += value;
  621. }
  622. remove {
  623. events.OnUnknownElement -= value;
  624. }
  625. }
  626. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.UnreferencedObject"]/*' />
  627. public event UnreferencedObjectEventHandler UnreferencedObject {
  628. add {
  629. events.OnUnreferencedObject += value;
  630. }
  631. remove {
  632. events.OnUnreferencedObject -= value;
  633. }
  634. }
  635. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.CreateReader"]/*' />
  636. ///<internalonly/>
  637. protected virtual XmlSerializationReader CreateReader() {throw new NotImplementedException();}
  638. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Deserialize4"]/*' />
  639. ///<internalonly/>
  640. protected virtual object Deserialize(XmlSerializationReader reader){throw new NotImplementedException();}
  641. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.CreateWriter"]/*' />
  642. ///<internalonly/>
  643. protected virtual XmlSerializationWriter CreateWriter(){throw new NotImplementedException();}
  644. /// <include file='doc\XmlSerializer.uex' path='docs/doc[@for="XmlSerializer.Serialize7"]/*' />
  645. ///<internalonly/>
  646. protected virtual void Serialize(object o, XmlSerializationWriter writer){throw new NotImplementedException();}
  647. internal void SetTempAssembly(TempAssembly tempAssembly, XmlMapping mapping) {
  648. this.tempAssembly = tempAssembly;
  649. this.mapping = mapping;
  650. this.typedSerializer = true;
  651. }
  652. static XmlTypeMapping GetKnownMapping(Type type, string ns) {
  653. if (ns != null && ns != string.Empty)
  654. return null;
  655. TypeDesc typeDesc = (TypeDesc)TypeScope.PrimtiveTypes[type];
  656. if (typeDesc == null)
  657. return null;
  658. ElementAccessor element = new ElementAccessor();
  659. element.Name = typeDesc.DataType.Name;
  660. XmlTypeMapping mapping = new XmlTypeMapping(null, element);
  661. mapping.SetKeyInternal(XmlMapping.GenerateKey(type, null, null));
  662. return mapping;
  663. }
  664. void SerializePrimitive(XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces) {
  665. XmlSerializationPrimitiveWriter writer = new XmlSerializationPrimitiveWriter();
  666. writer.Init(xmlWriter, namespaces, null, null, null);
  667. switch (Type.GetTypeCode(primitiveType)) {
  668. case TypeCode.String:
  669. writer.Write_string(o);
  670. break;
  671. case TypeCode.Int32:
  672. writer.Write_int(o);
  673. break;
  674. case TypeCode.Boolean:
  675. writer.Write_boolean(o);
  676. break;
  677. case TypeCode.Int16:
  678. writer.Write_short(o);
  679. break;
  680. case TypeCode.Int64:
  681. writer.Write_long(o);
  682. break;
  683. case TypeCode.Single:
  684. writer.Write_float(o);
  685. break;
  686. case TypeCode.Double:
  687. writer.Write_double(o);
  688. break;
  689. case TypeCode.Decimal:
  690. writer.Write_decimal(o);
  691. break;
  692. case TypeCode.DateTime:
  693. writer.Write_dateTime(o);
  694. break;
  695. case TypeCode.Char:
  696. writer.Write_char(o);
  697. break;
  698. case TypeCode.Byte:
  699. writer.Write_unsignedByte(o);
  700. break;
  701. case TypeCode.SByte:
  702. writer.Write_byte(o);
  703. break;
  704. case TypeCode.UInt16:
  705. writer.Write_unsignedShort(o);
  706. break;
  707. case TypeCode.UInt32:
  708. writer.Write_unsignedInt(o);
  709. break;
  710. case TypeCode.UInt64:
  711. writer.Write_unsignedLong(o);
  712. break;
  713. default:
  714. if (primitiveType == typeof(XmlQualifiedName)) {
  715. writer.Write_QName(o);
  716. }
  717. else if (primitiveType == typeof(byte[])) {
  718. writer.Write_base64Binary(o);
  719. }
  720. else if (primitiveType == typeof(Guid)) {
  721. writer.Write_guid(o);
  722. }
  723. else if (primitiveType == typeof(TimeSpan)) {
  724. writer.Write_TimeSpan(o);
  725. }
  726. else {
  727. throw new InvalidOperationException(Res.GetString(Res.XmlUnxpectedType, primitiveType.FullName));
  728. }
  729. break;
  730. }
  731. }
  732. object DeserializePrimitive(XmlReader xmlReader, XmlDeserializationEvents events) {
  733. XmlSerializationPrimitiveReader reader = new XmlSerializationPrimitiveReader();
  734. reader.Init(xmlReader, events, null, null);
  735. object o;
  736. switch (Type.GetTypeCode(primitiveType)) {
  737. case TypeCode.String:
  738. o = reader.Read_string();
  739. break;
  740. case TypeCode.Int32:
  741. o = reader.Read_int();
  742. break;
  743. case TypeCode.Boolean:
  744. o = reader.Read_boolean();
  745. break;
  746. case TypeCode.Int16:
  747. o = reader.Read_short();
  748. break;
  749. case TypeCode.Int64:
  750. o = reader.Read_long();
  751. break;
  752. case TypeCode.Single:
  753. o = reader.Read_float();
  754. break;
  755. case TypeCode.Double:
  756. o = reader.Read_double();
  757. break;
  758. case TypeCode.Decimal:
  759. o = reader.Read_decimal();
  760. break;
  761. case TypeCode.DateTime:
  762. o = reader.Read_dateTime();
  763. break;
  764. case TypeCode.Char:
  765. o = reader.Read_char();
  766. break;
  767. case TypeCode.Byte:
  768. o = reader.Read_unsignedByte();
  769. break;
  770. case TypeCode.SByte:
  771. o = reader.Read_byte();
  772. break;
  773. case TypeCode.UInt16:
  774. o = reader.Read_unsignedShort();
  775. break;
  776. case TypeCode.UInt32:
  777. o = reader.Read_unsignedInt();
  778. break;
  779. case TypeCode.UInt64:
  780. o = reader.Read_unsignedLong();
  781. break;
  782. default:
  783. if (primitiveType == typeof(XmlQualifiedName)) {
  784. o = reader.Read_QName();
  785. }
  786. else if (primitiveType == typeof(byte[])) {
  787. o = reader.Read_base64Binary();
  788. }
  789. else if (primitiveType == typeof(Guid)) {
  790. o = reader.Read_guid();
  791. }
  792. else if (primitiveType == typeof(TimeSpan) && LocalAppContextSwitches.EnableTimeSpanSerialization) {
  793. o = reader.Read_TimeSpan();
  794. }
  795. else {
  796. throw new InvalidOperationException(Res.GetString(Res.XmlUnxpectedType, primitiveType.FullName));
  797. }
  798. break;
  799. }
  800. return o;
  801. }
  802. class XmlSerializerMappingKey {
  803. public XmlMapping Mapping;
  804. public XmlSerializerMappingKey(XmlMapping mapping) {
  805. this.Mapping = mapping;
  806. }
  807. public override bool Equals(object obj) {
  808. XmlSerializerMappingKey other = obj as XmlSerializerMappingKey;
  809. if (other == null)
  810. return false;
  811. if (this.Mapping.Key != other.Mapping.Key)
  812. return false;
  813. if (this.Mapping.ElementName != other.Mapping.ElementName)
  814. return false;
  815. if (this.Mapping.Namespace != other.Mapping.Namespace)
  816. return false;
  817. if (this.Mapping.IsSoap != other.Mapping.IsSoap)
  818. return false;
  819. return true;
  820. }
  821. public override int GetHashCode() {
  822. int hashCode = this.Mapping.IsSoap ? 0 : 1;
  823. if (this.Mapping.Key != null)
  824. hashCode ^= this.Mapping.Key.GetHashCode();
  825. if (this.Mapping.ElementName != null)
  826. hashCode ^= this.Mapping.ElementName.GetHashCode();
  827. if (this.Mapping.Namespace != null)
  828. hashCode ^= this.Mapping.Namespace.GetHashCode();
  829. return hashCode;
  830. }
  831. }
  832. }
  833. }