XmlSerializationILGen.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSerializationILGen.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.Collections;
  10. using System.Collections.Generic;
  11. using System.Reflection;
  12. using System.Reflection.Emit;
  13. using System.Text.RegularExpressions;
  14. internal class XmlSerializationILGen {
  15. int nextMethodNumber = 0;
  16. Hashtable methodNames = new Hashtable();
  17. // Lookup name->created Method
  18. Dictionary<string, MethodBuilderInfo> methodBuilders = new Dictionary<string, MethodBuilderInfo>();
  19. // Lookup name->created Type
  20. internal Dictionary<string, Type> CreatedTypes = new Dictionary<string, Type>();
  21. // Lookup name->class Member
  22. internal Dictionary<string, MemberInfo> memberInfos = new Dictionary<string, MemberInfo>();
  23. ReflectionAwareILGen raCodeGen;
  24. TypeScope[] scopes;
  25. TypeDesc stringTypeDesc = null;
  26. TypeDesc qnameTypeDesc = null;
  27. string className;
  28. TypeMapping[] referencedMethods;
  29. int references = 0;
  30. Hashtable generatedMethods = new Hashtable();
  31. ModuleBuilder moduleBuilder;
  32. TypeAttributes typeAttributes;
  33. protected TypeBuilder typeBuilder;
  34. protected CodeGenerator ilg;
  35. internal XmlSerializationILGen(TypeScope[] scopes, string access, string className) {
  36. this.scopes = scopes;
  37. if (scopes.Length > 0) {
  38. stringTypeDesc = scopes[0].GetTypeDesc(typeof(string));
  39. qnameTypeDesc = scopes[0].GetTypeDesc(typeof(XmlQualifiedName));
  40. }
  41. this.raCodeGen = new ReflectionAwareILGen();
  42. this.className = className;
  43. System.Diagnostics.Debug.Assert(access == "public");
  44. this.typeAttributes = TypeAttributes.Public;
  45. }
  46. internal int NextMethodNumber { get { return nextMethodNumber; } set { nextMethodNumber = value; } }
  47. internal ReflectionAwareILGen RaCodeGen { get { return raCodeGen; } }
  48. internal TypeDesc StringTypeDesc { get { return stringTypeDesc; } }
  49. internal TypeDesc QnameTypeDesc { get { return qnameTypeDesc; } }
  50. internal string ClassName { get { return className; } }
  51. internal TypeScope[] Scopes { get { return scopes; } }
  52. internal Hashtable MethodNames { get { return methodNames; } }
  53. internal Hashtable GeneratedMethods { get { return generatedMethods; } }
  54. internal ModuleBuilder ModuleBuilder {
  55. get { System.Diagnostics.Debug.Assert(moduleBuilder != null); return moduleBuilder; }
  56. set { System.Diagnostics.Debug.Assert(moduleBuilder == null && value != null); moduleBuilder = value; }
  57. }
  58. internal TypeAttributes TypeAttributes { get { return typeAttributes; } }
  59. static Dictionary<string, Regex> regexs = new Dictionary<string, Regex>();
  60. static internal Regex NewRegex(string pattern) {
  61. Regex regex;
  62. lock (regexs) {
  63. if (!regexs.TryGetValue(pattern, out regex)) {
  64. regex = new Regex(pattern);
  65. regexs.Add(pattern, regex);
  66. }
  67. }
  68. return regex;
  69. }
  70. internal MethodBuilder EnsureMethodBuilder(TypeBuilder typeBuilder, string methodName,
  71. MethodAttributes attributes, Type returnType, Type[] parameterTypes) {
  72. MethodBuilderInfo methodBuilderInfo;
  73. if (!methodBuilders.TryGetValue(methodName, out methodBuilderInfo)) {
  74. MethodBuilder methodBuilder = typeBuilder.DefineMethod(
  75. methodName,
  76. attributes,
  77. returnType,
  78. parameterTypes);
  79. methodBuilderInfo = new MethodBuilderInfo(methodBuilder, parameterTypes);
  80. methodBuilders.Add(methodName, methodBuilderInfo);
  81. }
  82. #if DEBUG
  83. else {
  84. methodBuilderInfo.Validate(returnType, parameterTypes, attributes);
  85. }
  86. #endif
  87. return methodBuilderInfo.MethodBuilder;
  88. }
  89. internal MethodBuilderInfo GetMethodBuilder(string methodName) {
  90. System.Diagnostics.Debug.Assert(methodBuilders.ContainsKey(methodName));
  91. return methodBuilders[methodName];
  92. }
  93. internal virtual void GenerateMethod(TypeMapping mapping) { }
  94. internal void GenerateReferencedMethods() {
  95. while (references > 0) {
  96. TypeMapping mapping = referencedMethods[--references];
  97. GenerateMethod(mapping);
  98. }
  99. }
  100. internal string ReferenceMapping(TypeMapping mapping) {
  101. if (generatedMethods[mapping] == null) {
  102. referencedMethods = EnsureArrayIndex(referencedMethods, references);
  103. referencedMethods[references++] = mapping;
  104. }
  105. return (string)methodNames[mapping];
  106. }
  107. TypeMapping[] EnsureArrayIndex(TypeMapping[] a, int index) {
  108. if (a == null) return new TypeMapping[32];
  109. if (index < a.Length) return a;
  110. TypeMapping[] b = new TypeMapping[a.Length + 32];
  111. Array.Copy(a, b, index);
  112. return b;
  113. }
  114. internal FieldBuilder GenerateHashtableGetBegin(string privateName, string publicName, TypeBuilder serializerContractTypeBuilder) {
  115. FieldBuilder fieldBuilder = serializerContractTypeBuilder.DefineField(
  116. privateName,
  117. typeof(Hashtable),
  118. FieldAttributes.Private
  119. );
  120. ilg = new CodeGenerator(serializerContractTypeBuilder);
  121. PropertyBuilder propertyBuilder = serializerContractTypeBuilder.DefineProperty(
  122. publicName,
  123. PropertyAttributes.None,
  124. CallingConventions.HasThis,
  125. typeof(Hashtable),
  126. null, null, null, null, null);
  127. ilg.BeginMethod(
  128. typeof(Hashtable),
  129. "get_" + publicName,
  130. CodeGenerator.EmptyTypeArray,
  131. CodeGenerator.EmptyStringArray,
  132. CodeGenerator.PublicOverrideMethodAttributes | MethodAttributes.SpecialName);
  133. propertyBuilder.SetGetMethod(ilg.MethodBuilder);
  134. ilg.Ldarg(0);
  135. ilg.LoadMember(fieldBuilder);
  136. ilg.Load(null);
  137. // this 'if' ends in GenerateHashtableGetEnd
  138. ilg.If(Cmp.EqualTo);
  139. ConstructorInfo Hashtable_ctor = typeof(Hashtable).GetConstructor(
  140. CodeGenerator.InstanceBindingFlags,
  141. null,
  142. CodeGenerator.EmptyTypeArray,
  143. null
  144. );
  145. LocalBuilder _tmpLoc = ilg.DeclareLocal(typeof(Hashtable), "_tmp");
  146. ilg.New(Hashtable_ctor);
  147. ilg.Stloc(_tmpLoc);
  148. return fieldBuilder;
  149. }
  150. internal void GenerateHashtableGetEnd(FieldBuilder fieldBuilder) {
  151. ilg.Ldarg(0);
  152. ilg.LoadMember(fieldBuilder);
  153. ilg.Load(null);
  154. ilg.If(Cmp.EqualTo);
  155. {
  156. ilg.Ldarg(0);
  157. ilg.Ldloc(typeof(Hashtable), "_tmp");
  158. ilg.StoreMember(fieldBuilder);
  159. }
  160. ilg.EndIf();
  161. // 'endif' from GenerateHashtableGetBegin
  162. ilg.EndIf();
  163. ilg.Ldarg(0);
  164. ilg.LoadMember(fieldBuilder);
  165. ilg.GotoMethodEnd();
  166. ilg.EndMethod();
  167. }
  168. internal FieldBuilder GeneratePublicMethods(string privateName, string publicName, string[] methods, XmlMapping[] xmlMappings, TypeBuilder serializerContractTypeBuilder) {
  169. FieldBuilder fieldBuilder = GenerateHashtableGetBegin(privateName, publicName, serializerContractTypeBuilder);
  170. if (methods != null && methods.Length != 0 && xmlMappings != null && xmlMappings.Length == methods.Length) {
  171. MethodInfo Hashtable_set_Item = typeof(Hashtable).GetMethod(
  172. "set_Item",
  173. CodeGenerator.InstanceBindingFlags,
  174. null,
  175. new Type[] { typeof(Object), typeof(Object) },
  176. null
  177. );
  178. for (int i = 0; i < methods.Length; i++) {
  179. if (methods[i] == null)
  180. continue;
  181. ilg.Ldloc(typeof(Hashtable), "_tmp");
  182. ilg.Ldstr(xmlMappings[i].Key);
  183. ilg.Ldstr(methods[i]);
  184. ilg.Call(Hashtable_set_Item);
  185. }
  186. }
  187. GenerateHashtableGetEnd(fieldBuilder);
  188. return fieldBuilder;
  189. }
  190. internal void GenerateSupportedTypes(Type[] types, TypeBuilder serializerContractTypeBuilder) {
  191. ilg = new CodeGenerator(serializerContractTypeBuilder);
  192. ilg.BeginMethod(
  193. typeof(bool),
  194. "CanSerialize",
  195. new Type[] { typeof(Type) },
  196. new string[] { "type" },
  197. CodeGenerator.PublicOverrideMethodAttributes);
  198. Hashtable uniqueTypes = new Hashtable();
  199. for (int i = 0; i < types.Length; i++) {
  200. Type type = types[i];
  201. if (type == null)
  202. continue;
  203. if (!type.IsPublic && !type.IsNestedPublic)
  204. continue;
  205. if (uniqueTypes[type] != null)
  206. continue;
  207. // DDB172141: Wrong generated CS for serializer of List<string> type
  208. if (type.IsGenericType || type.ContainsGenericParameters)
  209. continue;
  210. uniqueTypes[type] = type;
  211. ilg.Ldarg("type");
  212. ilg.Ldc(type);
  213. ilg.If(Cmp.EqualTo);
  214. {
  215. ilg.Ldc(true);
  216. ilg.GotoMethodEnd();
  217. }
  218. ilg.EndIf();
  219. }
  220. ilg.Ldc(false);
  221. ilg.GotoMethodEnd();
  222. ilg.EndMethod();
  223. }
  224. internal string GenerateBaseSerializer(string baseSerializer, string readerClass, string writerClass, CodeIdentifiers classes) {
  225. baseSerializer = CodeIdentifier.MakeValid(baseSerializer);
  226. baseSerializer = classes.AddUnique(baseSerializer, baseSerializer);
  227. TypeBuilder baseSerializerTypeBuilder = CodeGenerator.CreateTypeBuilder(
  228. this.moduleBuilder,
  229. CodeIdentifier.GetCSharpName(baseSerializer),
  230. TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit,
  231. typeof(XmlSerializer),
  232. CodeGenerator.EmptyTypeArray);
  233. ConstructorInfo readerCtor = CreatedTypes[readerClass].GetConstructor(
  234. CodeGenerator.InstanceBindingFlags,
  235. null,
  236. CodeGenerator.EmptyTypeArray,
  237. null
  238. );
  239. ilg = new CodeGenerator(baseSerializerTypeBuilder);
  240. ilg.BeginMethod(typeof(XmlSerializationReader),
  241. "CreateReader",
  242. CodeGenerator.EmptyTypeArray,
  243. CodeGenerator.EmptyStringArray,
  244. CodeGenerator.ProtectedOverrideMethodAttributes);
  245. ilg.New(readerCtor);
  246. ilg.EndMethod();
  247. ConstructorInfo writerCtor = CreatedTypes[writerClass].GetConstructor(
  248. CodeGenerator.InstanceBindingFlags,
  249. null,
  250. CodeGenerator.EmptyTypeArray,
  251. null
  252. );
  253. ilg.BeginMethod(typeof(XmlSerializationWriter),
  254. "CreateWriter",
  255. CodeGenerator.EmptyTypeArray,
  256. CodeGenerator.EmptyStringArray,
  257. CodeGenerator.ProtectedOverrideMethodAttributes);
  258. ilg.New(writerCtor);
  259. ilg.EndMethod();
  260. baseSerializerTypeBuilder.DefineDefaultConstructor(
  261. MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
  262. Type baseSerializerType = baseSerializerTypeBuilder.CreateType();
  263. CreatedTypes.Add(baseSerializerType.Name, baseSerializerType);
  264. return baseSerializer;
  265. }
  266. internal string GenerateTypedSerializer(string readMethod, string writeMethod, XmlMapping mapping, CodeIdentifiers classes, string baseSerializer, string readerClass, string writerClass) {
  267. string serializerName = CodeIdentifier.MakeValid(Accessor.UnescapeName(mapping.Accessor.Mapping.TypeDesc.Name));
  268. serializerName = classes.AddUnique(serializerName + "Serializer", mapping);
  269. TypeBuilder typedSerializerTypeBuilder = CodeGenerator.CreateTypeBuilder(
  270. this.moduleBuilder,
  271. CodeIdentifier.GetCSharpName(serializerName),
  272. TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit,
  273. CreatedTypes[baseSerializer],
  274. CodeGenerator.EmptyTypeArray
  275. );
  276. ilg = new CodeGenerator(typedSerializerTypeBuilder);
  277. ilg.BeginMethod(
  278. typeof(Boolean),
  279. "CanDeserialize",
  280. new Type[] { typeof(XmlReader) },
  281. new string[] { "xmlReader" },
  282. CodeGenerator.PublicOverrideMethodAttributes
  283. );
  284. if (mapping.Accessor.Any) {
  285. ilg.Ldc(true);
  286. ilg.Stloc(ilg.ReturnLocal);
  287. ilg.Br(ilg.ReturnLabel);
  288. }
  289. else {
  290. MethodInfo XmlReader_IsStartElement = typeof(XmlReader).GetMethod(
  291. "IsStartElement",
  292. CodeGenerator.InstanceBindingFlags,
  293. null,
  294. new Type[] { typeof(String), typeof(String) },
  295. null
  296. );
  297. ilg.Ldarg(ilg.GetArg("xmlReader"));
  298. ilg.Ldstr(mapping.Accessor.Name);
  299. ilg.Ldstr(mapping.Accessor.Namespace);
  300. ilg.Call(XmlReader_IsStartElement);
  301. ilg.Stloc(ilg.ReturnLocal);
  302. ilg.Br(ilg.ReturnLabel);
  303. }
  304. ilg.MarkLabel(ilg.ReturnLabel);
  305. ilg.Ldloc(ilg.ReturnLocal);
  306. ilg.EndMethod();
  307. if (writeMethod != null) {
  308. ilg = new CodeGenerator(typedSerializerTypeBuilder);
  309. ilg.BeginMethod(
  310. typeof(void),
  311. "Serialize",
  312. new Type[] { typeof(object), typeof(XmlSerializationWriter) },
  313. new string[] { "objectToSerialize", "writer" },
  314. CodeGenerator.ProtectedOverrideMethodAttributes);
  315. MethodInfo writerType_writeMethod = CreatedTypes[writerClass].GetMethod(
  316. writeMethod,
  317. CodeGenerator.InstanceBindingFlags,
  318. null,
  319. new Type[] { (mapping is XmlMembersMapping) ? typeof(object[]) : typeof(object) },
  320. null
  321. );
  322. ilg.Ldarg("writer");
  323. ilg.Castclass(CreatedTypes[writerClass]);
  324. ilg.Ldarg("objectToSerialize");
  325. if (mapping is XmlMembersMapping) {
  326. ilg.ConvertValue(typeof(object), typeof(object[]));
  327. }
  328. ilg.Call(writerType_writeMethod);
  329. ilg.EndMethod();
  330. }
  331. if (readMethod != null) {
  332. ilg = new CodeGenerator(typedSerializerTypeBuilder);
  333. ilg.BeginMethod(
  334. typeof(object),
  335. "Deserialize",
  336. new Type[] { typeof(XmlSerializationReader) },
  337. new string[] { "reader" },
  338. CodeGenerator.ProtectedOverrideMethodAttributes);
  339. MethodInfo readerType_readMethod = CreatedTypes[readerClass].GetMethod(
  340. readMethod,
  341. CodeGenerator.InstanceBindingFlags,
  342. null,
  343. CodeGenerator.EmptyTypeArray,
  344. null
  345. );
  346. ilg.Ldarg("reader");
  347. ilg.Castclass(CreatedTypes[readerClass]);
  348. ilg.Call(readerType_readMethod);
  349. ilg.EndMethod();
  350. }
  351. typedSerializerTypeBuilder.DefineDefaultConstructor(CodeGenerator.PublicMethodAttributes);
  352. Type typedSerializerType = typedSerializerTypeBuilder.CreateType();
  353. CreatedTypes.Add(typedSerializerType.Name, typedSerializerType);
  354. return typedSerializerType.Name;
  355. }
  356. FieldBuilder GenerateTypedSerializers(Hashtable serializers, TypeBuilder serializerContractTypeBuilder) {
  357. string privateName = "typedSerializers";
  358. FieldBuilder fieldBuilder = GenerateHashtableGetBegin(privateName, "TypedSerializers", serializerContractTypeBuilder);
  359. MethodInfo Hashtable_Add = typeof(Hashtable).GetMethod(
  360. "Add",
  361. CodeGenerator.InstanceBindingFlags,
  362. null,
  363. new Type[] { typeof(Object), typeof(Object) },
  364. null
  365. );
  366. foreach (string key in serializers.Keys) {
  367. ConstructorInfo ctor = CreatedTypes[(string)serializers[key]].GetConstructor(
  368. CodeGenerator.InstanceBindingFlags,
  369. null,
  370. CodeGenerator.EmptyTypeArray,
  371. null
  372. );
  373. ilg.Ldloc(typeof(Hashtable), "_tmp");
  374. ilg.Ldstr(key);
  375. ilg.New(ctor);
  376. ilg.Call(Hashtable_Add);
  377. }
  378. GenerateHashtableGetEnd(fieldBuilder);
  379. return fieldBuilder;
  380. }
  381. //GenerateGetSerializer(serializers, xmlMappings);
  382. void GenerateGetSerializer(Hashtable serializers, XmlMapping[] xmlMappings, TypeBuilder serializerContractTypeBuilder) {
  383. ilg = new CodeGenerator(serializerContractTypeBuilder);
  384. ilg.BeginMethod(
  385. typeof(XmlSerializer),
  386. "GetSerializer",
  387. new Type[] { typeof(Type) },
  388. new string[] { "type" },
  389. CodeGenerator.PublicOverrideMethodAttributes);
  390. for (int i = 0; i < xmlMappings.Length; i++) {
  391. if (xmlMappings[i] is XmlTypeMapping) {
  392. Type type = xmlMappings[i].Accessor.Mapping.TypeDesc.Type;
  393. if (type == null)
  394. continue;
  395. if (!type.IsPublic && !type.IsNestedPublic)
  396. continue;
  397. // DDB172141: Wrong generated CS for serializer of List<string> type
  398. if (type.IsGenericType || type.ContainsGenericParameters)
  399. continue;
  400. ilg.Ldarg("type");
  401. ilg.Ldc(type);
  402. ilg.If(Cmp.EqualTo);
  403. {
  404. ConstructorInfo ctor = CreatedTypes[(string)serializers[xmlMappings[i].Key]].GetConstructor(
  405. CodeGenerator.InstanceBindingFlags,
  406. null,
  407. CodeGenerator.EmptyTypeArray,
  408. null
  409. );
  410. ilg.New(ctor);
  411. ilg.Stloc(ilg.ReturnLocal);
  412. ilg.Br(ilg.ReturnLabel);
  413. }
  414. ilg.EndIf();
  415. }
  416. }
  417. ilg.Load(null);
  418. ilg.Stloc(ilg.ReturnLocal);
  419. ilg.Br(ilg.ReturnLabel);
  420. ilg.MarkLabel(ilg.ReturnLabel);
  421. ilg.Ldloc(ilg.ReturnLocal);
  422. ilg.EndMethod();
  423. }
  424. internal void GenerateSerializerContract(string className, XmlMapping[] xmlMappings, Type[] types, string readerType, string[] readMethods, string writerType, string[] writerMethods, Hashtable serializers) {
  425. TypeBuilder serializerContractTypeBuilder = CodeGenerator.CreateTypeBuilder(
  426. this.moduleBuilder,
  427. "XmlSerializerContract",
  428. TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
  429. typeof(XmlSerializerImplementation),
  430. CodeGenerator.EmptyTypeArray
  431. );
  432. ilg = new CodeGenerator(serializerContractTypeBuilder);
  433. PropertyBuilder propertyBuilder = serializerContractTypeBuilder.DefineProperty(
  434. "Reader",
  435. PropertyAttributes.None,
  436. CallingConventions.HasThis,
  437. typeof(XmlSerializationReader),
  438. null, null, null, null, null);
  439. ilg.BeginMethod(
  440. typeof(XmlSerializationReader),
  441. "get_Reader",
  442. CodeGenerator.EmptyTypeArray,
  443. CodeGenerator.EmptyStringArray,
  444. CodeGenerator.PublicOverrideMethodAttributes | MethodAttributes.SpecialName);
  445. propertyBuilder.SetGetMethod(ilg.MethodBuilder);
  446. ConstructorInfo ctor = CreatedTypes[readerType].GetConstructor(
  447. CodeGenerator.InstanceBindingFlags,
  448. null,
  449. CodeGenerator.EmptyTypeArray,
  450. null
  451. );
  452. ilg.New(ctor);
  453. ilg.EndMethod();
  454. ilg = new CodeGenerator(serializerContractTypeBuilder);
  455. propertyBuilder = serializerContractTypeBuilder.DefineProperty(
  456. "Writer",
  457. PropertyAttributes.None,
  458. CallingConventions.HasThis,
  459. typeof(XmlSerializationWriter),
  460. null, null, null, null, null);
  461. ilg.BeginMethod(
  462. typeof(XmlSerializationWriter),
  463. "get_Writer",
  464. CodeGenerator.EmptyTypeArray,
  465. CodeGenerator.EmptyStringArray,
  466. CodeGenerator.PublicOverrideMethodAttributes | MethodAttributes.SpecialName);
  467. propertyBuilder.SetGetMethod(ilg.MethodBuilder);
  468. ctor = CreatedTypes[writerType].GetConstructor(
  469. CodeGenerator.InstanceBindingFlags,
  470. null,
  471. CodeGenerator.EmptyTypeArray,
  472. null
  473. );
  474. ilg.New(ctor);
  475. ilg.EndMethod();
  476. FieldBuilder readMethodsField = GeneratePublicMethods("readMethods", "ReadMethods", readMethods, xmlMappings, serializerContractTypeBuilder);
  477. FieldBuilder writeMethodsField = GeneratePublicMethods("writeMethods", "WriteMethods", writerMethods, xmlMappings, serializerContractTypeBuilder);
  478. FieldBuilder typedSerializersField = GenerateTypedSerializers(serializers, serializerContractTypeBuilder);
  479. GenerateSupportedTypes(types, serializerContractTypeBuilder);
  480. GenerateGetSerializer(serializers, xmlMappings, serializerContractTypeBuilder);
  481. // Default ctor
  482. ConstructorInfo baseCtor = typeof(XmlSerializerImplementation).GetConstructor(
  483. CodeGenerator.InstanceBindingFlags,
  484. null,
  485. CodeGenerator.EmptyTypeArray,
  486. null
  487. );
  488. ilg = new CodeGenerator(serializerContractTypeBuilder);
  489. ilg.BeginMethod(
  490. typeof(void),
  491. ".ctor",
  492. CodeGenerator.EmptyTypeArray,
  493. CodeGenerator.EmptyStringArray,
  494. CodeGenerator.PublicMethodAttributes | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName
  495. );
  496. ilg.Ldarg(0);
  497. ilg.Load(null);
  498. ilg.StoreMember(readMethodsField);
  499. ilg.Ldarg(0);
  500. ilg.Load(null);
  501. ilg.StoreMember(writeMethodsField);
  502. ilg.Ldarg(0);
  503. ilg.Load(null);
  504. ilg.StoreMember(typedSerializersField);
  505. ilg.Ldarg(0);
  506. ilg.Call(baseCtor);
  507. ilg.EndMethod();
  508. // Instantiate type
  509. Type serializerContractType = serializerContractTypeBuilder.CreateType();
  510. CreatedTypes.Add(serializerContractType.Name, serializerContractType);
  511. }
  512. internal static bool IsWildcard(SpecialMapping mapping) {
  513. if (mapping is SerializableMapping)
  514. return ((SerializableMapping)mapping).IsAny;
  515. return mapping.TypeDesc.CanBeElementValue;
  516. }
  517. internal void ILGenLoad(string source) {
  518. ILGenLoad(source, null);
  519. }
  520. internal void ILGenLoad(string source, Type type) {
  521. if (source.StartsWith("o.@", StringComparison.Ordinal)) {
  522. System.Diagnostics.Debug.Assert(memberInfos.ContainsKey(source.Substring(3)));
  523. MemberInfo memInfo = memberInfos[source.Substring(3)];
  524. ilg.LoadMember(ilg.GetVariable("o"), memInfo);
  525. if (type != null) {
  526. Type memType = (memInfo.MemberType == MemberTypes.Field) ? ((FieldInfo)memInfo).FieldType : ((PropertyInfo)memInfo).PropertyType;
  527. ilg.ConvertValue(memType, type);
  528. }
  529. }
  530. else {
  531. SourceInfo info = new SourceInfo(source, null, null, null, ilg);
  532. info.Load(type);
  533. }
  534. }
  535. }
  536. }