XmlSerializationGeneratedCode.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSerializationGeneratedCode.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;
  9. using System.IO;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Threading;
  13. using System.Reflection;
  14. using System.Security;
  15. using System.Globalization;
  16. /// <include file='doc\XmlSerializationGeneratedCode.uex' path='docs/doc[@for="XmlSerializationGeneratedCode"]/*' />
  17. ///<internalonly/>
  18. public abstract class XmlSerializationGeneratedCode {
  19. TempAssembly tempAssembly;
  20. int threadCode;
  21. ResolveEventHandler assemblyResolver;
  22. internal void Init(TempAssembly tempAssembly) {
  23. this.tempAssembly = tempAssembly;
  24. // only hook the assembly resolver if we have something to help us do the resolution
  25. if (tempAssembly != null && tempAssembly.NeedAssembyResolve) {
  26. // we save the threadcode to make sure we don't handle any resolve events for any other threads
  27. threadCode = Thread.CurrentThread.GetHashCode();
  28. assemblyResolver = new ResolveEventHandler(OnAssemblyResolve);
  29. AppDomain.CurrentDomain.AssemblyResolve += assemblyResolver;
  30. }
  31. }
  32. // this method must be called at the end of serialization
  33. internal void Dispose() {
  34. if (assemblyResolver != null)
  35. AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolver;
  36. assemblyResolver = null;
  37. }
  38. internal Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) {
  39. if (tempAssembly != null && Thread.CurrentThread.GetHashCode() == threadCode)
  40. return tempAssembly.GetReferencedAssembly(args.Name);
  41. return null;
  42. }
  43. }
  44. internal class XmlSerializationCodeGen {
  45. IndentedWriter writer;
  46. int nextMethodNumber = 0;
  47. Hashtable methodNames = new Hashtable();
  48. ReflectionAwareCodeGen raCodeGen;
  49. TypeScope[] scopes;
  50. TypeDesc stringTypeDesc = null;
  51. TypeDesc qnameTypeDesc = null;
  52. string access;
  53. string className;
  54. TypeMapping[] referencedMethods;
  55. int references = 0;
  56. Hashtable generatedMethods = new Hashtable();
  57. internal XmlSerializationCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className) {
  58. this.writer = writer;
  59. this.scopes = scopes;
  60. if (scopes.Length > 0) {
  61. stringTypeDesc = scopes[0].GetTypeDesc(typeof(string));
  62. qnameTypeDesc = scopes[0].GetTypeDesc(typeof(XmlQualifiedName));
  63. }
  64. this.raCodeGen = new ReflectionAwareCodeGen(writer);
  65. this.className = className;
  66. this.access = access;
  67. }
  68. internal IndentedWriter Writer { get { return writer; } }
  69. internal int NextMethodNumber { get { return nextMethodNumber; } set { nextMethodNumber = value; } }
  70. internal ReflectionAwareCodeGen RaCodeGen { get { return raCodeGen; } }
  71. internal TypeDesc StringTypeDesc { get { return stringTypeDesc; } }
  72. internal TypeDesc QnameTypeDesc { get { return qnameTypeDesc; } }
  73. internal string ClassName { get { return className; } }
  74. internal string Access { get { return access; } }
  75. internal TypeScope[] Scopes { get { return scopes; } }
  76. internal Hashtable MethodNames { get { return methodNames; } }
  77. internal Hashtable GeneratedMethods { get { return generatedMethods; } }
  78. internal virtual void GenerateMethod(TypeMapping mapping){}
  79. internal void GenerateReferencedMethods() {
  80. while(references > 0) {
  81. TypeMapping mapping = referencedMethods[--references];
  82. GenerateMethod(mapping);
  83. }
  84. }
  85. internal string ReferenceMapping(TypeMapping mapping) {
  86. if (!mapping.IsSoap) {
  87. if (generatedMethods[mapping] == null) {
  88. referencedMethods = EnsureArrayIndex(referencedMethods, references);
  89. referencedMethods[references++] = mapping;
  90. }
  91. }
  92. return (string)methodNames[mapping];
  93. }
  94. TypeMapping[] EnsureArrayIndex(TypeMapping[] a, int index) {
  95. if (a == null) return new TypeMapping[32];
  96. if (index < a.Length) return a;
  97. TypeMapping[] b = new TypeMapping[a.Length + 32];
  98. Array.Copy(a, b, index);
  99. return b;
  100. }
  101. internal void WriteQuotedCSharpString(string value) {
  102. raCodeGen.WriteQuotedCSharpString(value);
  103. }
  104. internal void GenerateHashtableGetBegin(string privateName, string publicName) {
  105. writer.Write(typeof(Hashtable).FullName);
  106. writer.Write(" ");
  107. writer.Write(privateName);
  108. writer.WriteLine(" = null;");
  109. writer.Write("public override ");
  110. writer.Write(typeof(Hashtable).FullName);
  111. writer.Write(" ");
  112. writer.Write(publicName);
  113. writer.WriteLine(" {");
  114. writer.Indent++;
  115. writer.WriteLine("get {");
  116. writer.Indent++;
  117. writer.Write("if (");
  118. writer.Write(privateName);
  119. writer.WriteLine(" == null) {");
  120. writer.Indent++;
  121. writer.Write(typeof(Hashtable).FullName);
  122. writer.Write(" _tmp = new ");
  123. writer.Write(typeof(Hashtable).FullName);
  124. writer.WriteLine("();");
  125. }
  126. internal void GenerateHashtableGetEnd(string privateName) {
  127. writer.Write("if (");
  128. writer.Write(privateName);
  129. writer.Write(" == null) ");
  130. writer.Write(privateName);
  131. writer.WriteLine(" = _tmp;");
  132. writer.Indent--;
  133. writer.WriteLine("}");
  134. writer.Write("return ");
  135. writer.Write(privateName);
  136. writer.WriteLine(";");
  137. writer.Indent--;
  138. writer.WriteLine("}");
  139. writer.Indent--;
  140. writer.WriteLine("}");
  141. }
  142. internal void GeneratePublicMethods(string privateName, string publicName, string[] methods, XmlMapping[] xmlMappings) {
  143. GenerateHashtableGetBegin(privateName, publicName);
  144. if (methods != null && methods.Length != 0 && xmlMappings != null && xmlMappings.Length == methods.Length) {
  145. for (int i = 0; i < methods.Length; i++) {
  146. if (methods[i] == null)
  147. continue;
  148. writer.Write("_tmp[");
  149. WriteQuotedCSharpString(xmlMappings[i].Key);
  150. writer.Write("] = ");
  151. WriteQuotedCSharpString(methods[i]);
  152. writer.WriteLine(";");
  153. }
  154. }
  155. GenerateHashtableGetEnd(privateName);
  156. }
  157. internal void GenerateSupportedTypes(Type[] types) {
  158. writer.Write("public override ");
  159. writer.Write(typeof(bool).FullName);
  160. writer.Write(" CanSerialize(");
  161. writer.Write(typeof(Type).FullName);
  162. writer.WriteLine(" type) {");
  163. writer.Indent++;
  164. Hashtable uniqueTypes = new Hashtable();
  165. for (int i = 0; i < types.Length; i++) {
  166. Type type = types[i];
  167. if (type == null)
  168. continue;
  169. if (!type.IsPublic && !type.IsNestedPublic)
  170. continue;
  171. if (uniqueTypes[type] != null)
  172. continue;
  173. if (DynamicAssemblies.IsTypeDynamic(type))
  174. continue;
  175. if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments()))
  176. continue;
  177. uniqueTypes[type] = type;
  178. writer.Write("if (type == typeof(");
  179. writer.Write(CodeIdentifier.GetCSharpName(type));
  180. writer.WriteLine(")) return true;");
  181. }
  182. writer.WriteLine("return false;");
  183. writer.Indent--;
  184. writer.WriteLine("}");
  185. }
  186. internal string GenerateBaseSerializer(string baseSerializer, string readerClass, string writerClass, CodeIdentifiers classes) {
  187. baseSerializer = CodeIdentifier.MakeValid(baseSerializer);
  188. baseSerializer = classes.AddUnique(baseSerializer, baseSerializer);
  189. writer.WriteLine();
  190. writer.Write("public abstract class ");
  191. writer.Write(CodeIdentifier.GetCSharpName(baseSerializer));
  192. writer.Write(" : ");
  193. writer.Write(typeof(XmlSerializer).FullName);
  194. writer.WriteLine(" {");
  195. writer.Indent++;
  196. writer.Write("protected override ");
  197. writer.Write(typeof(XmlSerializationReader).FullName);
  198. writer.WriteLine(" CreateReader() {");
  199. writer.Indent++;
  200. writer.Write("return new ");
  201. writer.Write(readerClass);
  202. writer.WriteLine("();");
  203. writer.Indent--;
  204. writer.WriteLine("}");
  205. writer.Write("protected override ");
  206. writer.Write(typeof(XmlSerializationWriter).FullName);
  207. writer.WriteLine(" CreateWriter() {");
  208. writer.Indent++;
  209. writer.Write("return new ");
  210. writer.Write(writerClass);
  211. writer.WriteLine("();");
  212. writer.Indent--;
  213. writer.WriteLine("}");
  214. writer.Indent--;
  215. writer.WriteLine("}");
  216. return baseSerializer;
  217. }
  218. internal string GenerateTypedSerializer(string readMethod, string writeMethod, XmlMapping mapping, CodeIdentifiers classes, string baseSerializer, string readerClass, string writerClass) {
  219. string serializerName = CodeIdentifier.MakeValid(Accessor.UnescapeName(mapping.Accessor.Mapping.TypeDesc.Name));
  220. serializerName = classes.AddUnique(serializerName + "Serializer", mapping);
  221. writer.WriteLine();
  222. writer.Write("public sealed class ");
  223. writer.Write(CodeIdentifier.GetCSharpName(serializerName));
  224. writer.Write(" : ");
  225. writer.Write(baseSerializer);
  226. writer.WriteLine(" {");
  227. writer.Indent++;
  228. writer.WriteLine();
  229. writer.Write("public override ");
  230. writer.Write(typeof(bool).FullName);
  231. writer.Write(" CanDeserialize(");
  232. writer.Write(typeof(XmlReader).FullName);
  233. writer.WriteLine(" xmlReader) {");
  234. writer.Indent++;
  235. if (mapping.Accessor.Any) {
  236. writer.WriteLine("return true;");
  237. }
  238. else {
  239. writer.Write("return xmlReader.IsStartElement(");
  240. WriteQuotedCSharpString(mapping.Accessor.Name);
  241. writer.Write(", ");
  242. WriteQuotedCSharpString(mapping.Accessor.Namespace);
  243. writer.WriteLine(");");
  244. }
  245. writer.Indent--;
  246. writer.WriteLine("}");
  247. if (writeMethod != null) {
  248. writer.WriteLine();
  249. writer.Write("protected override void Serialize(object objectToSerialize, ");
  250. writer.Write(typeof(XmlSerializationWriter).FullName);
  251. writer.WriteLine(" writer) {");
  252. writer.Indent++;
  253. writer.Write("((");
  254. writer.Write(writerClass);
  255. writer.Write(")writer).");
  256. writer.Write(writeMethod);
  257. writer.Write("(");
  258. if (mapping is XmlMembersMapping) {
  259. writer.Write("(object[])");
  260. }
  261. writer.WriteLine("objectToSerialize);");
  262. writer.Indent--;
  263. writer.WriteLine("}");
  264. }
  265. if (readMethod != null) {
  266. writer.WriteLine();
  267. writer.Write("protected override object Deserialize(");
  268. writer.Write(typeof(XmlSerializationReader).FullName);
  269. writer.WriteLine(" reader) {");
  270. writer.Indent++;
  271. writer.Write("return ((");
  272. writer.Write(readerClass);
  273. writer.Write(")reader).");
  274. writer.Write(readMethod);
  275. writer.WriteLine("();");
  276. writer.Indent--;
  277. writer.WriteLine("}");
  278. }
  279. writer.Indent--;
  280. writer.WriteLine("}");
  281. return serializerName;
  282. }
  283. void GenerateTypedSerializers(Hashtable serializers) {
  284. string privateName = "typedSerializers";
  285. GenerateHashtableGetBegin(privateName, "TypedSerializers");
  286. foreach (string key in serializers.Keys) {
  287. writer.Write("_tmp.Add(");
  288. WriteQuotedCSharpString(key);
  289. writer.Write(", new ");
  290. writer.Write((string)serializers[key]);
  291. writer.WriteLine("());");
  292. }
  293. GenerateHashtableGetEnd("typedSerializers");
  294. }
  295. //GenerateGetSerializer(serializers, xmlMappings);
  296. void GenerateGetSerializer(Hashtable serializers, XmlMapping[] xmlMappings) {
  297. writer.Write("public override ");
  298. writer.Write(typeof(XmlSerializer).FullName);
  299. writer.Write(" GetSerializer(");
  300. writer.Write(typeof(Type).FullName);
  301. writer.WriteLine(" type) {");
  302. writer.Indent++;
  303. for (int i = 0; i < xmlMappings.Length; i++) {
  304. if (xmlMappings[i] is XmlTypeMapping) {
  305. Type type = xmlMappings[i].Accessor.Mapping.TypeDesc.Type;
  306. if (type == null)
  307. continue;
  308. if (!type.IsPublic && !type.IsNestedPublic)
  309. continue;
  310. if (DynamicAssemblies.IsTypeDynamic(type))
  311. continue;
  312. if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments()))
  313. continue;
  314. writer.Write("if (type == typeof(");
  315. writer.Write(CodeIdentifier.GetCSharpName(type));
  316. writer.Write(")) return new ");
  317. writer.Write((string)serializers[xmlMappings[i].Key]);
  318. writer.WriteLine("();");
  319. }
  320. }
  321. writer.WriteLine("return null;");
  322. writer.Indent--;
  323. writer.WriteLine("}");
  324. }
  325. internal void GenerateSerializerContract(string className, XmlMapping[] xmlMappings, Type[] types, string readerType, string[] readMethods, string writerType, string[] writerMethods, Hashtable serializers) {
  326. writer.WriteLine();
  327. writer.Write("public class XmlSerializerContract : global::");
  328. writer.Write(typeof(XmlSerializerImplementation).FullName);
  329. writer.WriteLine(" {");
  330. writer.Indent++;
  331. writer.Write("public override global::");
  332. writer.Write(typeof(XmlSerializationReader).FullName);
  333. writer.Write(" Reader { get { return new ");
  334. writer.Write(readerType);
  335. writer.WriteLine("(); } }");
  336. writer.Write("public override global::");
  337. writer.Write(typeof(XmlSerializationWriter).FullName);
  338. writer.Write(" Writer { get { return new ");
  339. writer.Write(writerType);
  340. writer.WriteLine("(); } }");
  341. GeneratePublicMethods("readMethods", "ReadMethods", readMethods, xmlMappings);
  342. GeneratePublicMethods("writeMethods", "WriteMethods", writerMethods, xmlMappings);
  343. GenerateTypedSerializers(serializers);
  344. GenerateSupportedTypes(types);
  345. GenerateGetSerializer(serializers, xmlMappings);
  346. writer.Indent--;
  347. writer.WriteLine("}");
  348. }
  349. internal static bool IsWildcard(SpecialMapping mapping) {
  350. if (mapping is SerializableMapping)
  351. return ((SerializableMapping)mapping).IsAny;
  352. return mapping.TypeDesc.CanBeElementValue;
  353. }
  354. }
  355. }