Compilation.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. //------------------------------------------------------------------------------
  2. // <copyright file="Compilation.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.Configuration;
  9. using System.Reflection;
  10. using System.Reflection.Emit;
  11. using System.Collections;
  12. using System.IO;
  13. using System;
  14. using System.Text;
  15. using System.Xml;
  16. using System.Threading;
  17. using System.Security;
  18. using System.Security.Permissions;
  19. using System.Security.Policy;
  20. using System.Xml.Serialization.Configuration;
  21. using System.Diagnostics;
  22. using System.CodeDom.Compiler;
  23. using System.Globalization;
  24. using System.Runtime.Versioning;
  25. using System.Diagnostics.CodeAnalysis;
  26. internal class TempAssembly {
  27. internal const string GeneratedAssemblyNamespace = "Microsoft.Xml.Serialization.GeneratedAssembly";
  28. Assembly assembly;
  29. bool pregeneratedAssmbly = false;
  30. XmlSerializerImplementation contract = null;
  31. Hashtable writerMethods;
  32. Hashtable readerMethods;
  33. TempMethodDictionary methods;
  34. static object[] emptyObjectArray = new object[0];
  35. Hashtable assemblies = new Hashtable();
  36. static volatile FileIOPermission fileIOPermission;
  37. internal class TempMethod {
  38. internal MethodInfo writeMethod;
  39. internal MethodInfo readMethod;
  40. internal string name;
  41. internal string ns;
  42. internal bool isSoap;
  43. internal string methodKey;
  44. }
  45. private TempAssembly() {
  46. }
  47. internal TempAssembly(XmlMapping[] xmlMappings, Type[] types, string defaultNamespace, string location, Evidence evidence) {
  48. bool containsSoapMapping = false;
  49. for (int i = 0; i < xmlMappings.Length; i++) {
  50. xmlMappings[i].CheckShallow();
  51. if (xmlMappings[i].IsSoap) {
  52. containsSoapMapping = true;
  53. }
  54. }
  55. // We will make best effort to use RefEmit for assembly generation
  56. bool fallbackToCSharpAssemblyGeneration = false;
  57. if (!containsSoapMapping && !TempAssembly.UseLegacySerializerGeneration) {
  58. try {
  59. assembly = GenerateRefEmitAssembly(xmlMappings, types, defaultNamespace, evidence);
  60. }
  61. // Only catch and handle known failures with RefEmit
  62. catch (CodeGeneratorConversionException) {
  63. fallbackToCSharpAssemblyGeneration = true;
  64. }
  65. // Add other known exceptions here...
  66. //
  67. }
  68. else {
  69. fallbackToCSharpAssemblyGeneration = true;
  70. }
  71. if (fallbackToCSharpAssemblyGeneration) {
  72. assembly = GenerateAssembly(xmlMappings, types, defaultNamespace, evidence, XmlSerializerCompilerParameters.Create(location), null, assemblies);
  73. }
  74. #if DEBUG
  75. // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  76. if (assembly == null) throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Failed to generate XmlSerializer assembly, but did not throw"));
  77. #endif
  78. InitAssemblyMethods(xmlMappings);
  79. }
  80. internal TempAssembly(XmlMapping[] xmlMappings, Assembly assembly, XmlSerializerImplementation contract) {
  81. this.assembly = assembly;
  82. InitAssemblyMethods(xmlMappings);
  83. this.contract = contract;
  84. pregeneratedAssmbly = true;
  85. }
  86. internal static bool UseLegacySerializerGeneration {
  87. get {
  88. if (AppSettings.UseLegacySerializerGeneration.HasValue) {
  89. // AppSetting will always win if specified
  90. return (bool) AppSettings.UseLegacySerializerGeneration;
  91. }
  92. else {
  93. #if CONFIGURATION_DEP
  94. XmlSerializerSection configSection = ConfigurationManager.GetSection(ConfigurationStrings.XmlSerializerSectionPath) as XmlSerializerSection;
  95. return configSection == null ? false : configSection.UseLegacySerializerGeneration;
  96. #else
  97. return false;
  98. #endif
  99. }
  100. }
  101. }
  102. internal TempAssembly(XmlSerializerImplementation contract) {
  103. this.contract = contract;
  104. pregeneratedAssmbly = true;
  105. }
  106. internal XmlSerializerImplementation Contract {
  107. get {
  108. if (contract == null) {
  109. contract = (XmlSerializerImplementation)Activator.CreateInstance(GetTypeFromAssembly(this.assembly, "XmlSerializerContract"));
  110. }
  111. return contract;
  112. }
  113. }
  114. internal void InitAssemblyMethods(XmlMapping[] xmlMappings) {
  115. methods = new TempMethodDictionary();
  116. for (int i = 0; i < xmlMappings.Length; i++) {
  117. TempMethod method = new TempMethod();
  118. method.isSoap = xmlMappings[i].IsSoap;
  119. method.methodKey = xmlMappings[i].Key;
  120. XmlTypeMapping xmlTypeMapping = xmlMappings[i] as XmlTypeMapping;
  121. if (xmlTypeMapping != null) {
  122. method.name = xmlTypeMapping.ElementName;
  123. method.ns = xmlTypeMapping.Namespace;
  124. }
  125. methods.Add(xmlMappings[i].Key, method);
  126. }
  127. }
  128. /// <devdoc>
  129. /// <para>
  130. /// Attempts to load pre-generated serialization assembly.
  131. /// First check for the [XmlSerializerAssembly] attribute
  132. /// </para>
  133. /// </devdoc>
  134. // SxS: This method does not take any resource name and does not expose any resources to the caller.
  135. // It's OK to suppress the SxS warning.
  136. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  137. [ResourceExposure(ResourceScope.None)]
  138. internal static Assembly LoadGeneratedAssembly(Type type, string defaultNamespace, out XmlSerializerImplementation contract) {
  139. Assembly serializer = null;
  140. contract = null;
  141. string serializerName = null;
  142. // Packaged apps do not support loading generated serializers.
  143. if (Microsoft.Win32.UnsafeNativeMethods.IsPackagedProcess.Value) {
  144. return null;
  145. }
  146. bool logEnabled = DiagnosticsSwitches.PregenEventLog.Enabled;
  147. // check to see if we loading explicit pre-generated assembly
  148. object[] attrs = type.GetCustomAttributes(typeof(XmlSerializerAssemblyAttribute), false);
  149. if (attrs.Length == 0) {
  150. // Guess serializer name: if parent assembly signed use strong name
  151. AssemblyName name = GetName(type.Assembly, true);
  152. serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace);
  153. // use strong name
  154. name.Name = serializerName;
  155. name.CodeBase = null;
  156. name.CultureInfo = CultureInfo.InvariantCulture;
  157. try {
  158. serializer = Assembly.Load(name);
  159. }
  160. catch (Exception e) {
  161. if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
  162. throw;
  163. }
  164. if (logEnabled) {
  165. Log(e.Message, EventLogEntryType.Information);
  166. }
  167. byte[] token = name.GetPublicKeyToken();
  168. if (token != null && token.Length > 0) {
  169. // the parent assembly was signed, so do not try to LoadWithPartialName
  170. return null;
  171. }
  172. #pragma warning disable 618
  173. serializer = Assembly.LoadWithPartialName(serializerName, null);
  174. #pragma warning restore 618
  175. }
  176. if (serializer == null) {
  177. #if !FEATURE_PAL // EventLog
  178. if (logEnabled) {
  179. Log(Res.GetString(Res.XmlPregenCannotLoad, serializerName), EventLogEntryType.Information);
  180. }
  181. #endif //!FEATURE_PAL // EventLog
  182. return null;
  183. }
  184. if (!IsSerializerVersionMatch(serializer, type, defaultNamespace, null)) {
  185. #if !FEATURE_PAL // EventLog
  186. if (logEnabled)
  187. Log(Res.GetString(Res.XmlSerializerExpiredDetails, serializerName, type.FullName), EventLogEntryType.Error);
  188. #endif //!FEATURE_PAL // EventLog
  189. return null;
  190. }
  191. }
  192. else {
  193. XmlSerializerAssemblyAttribute assemblyAttribute = (XmlSerializerAssemblyAttribute)attrs[0];
  194. if (assemblyAttribute.AssemblyName != null && assemblyAttribute.CodeBase != null)
  195. throw new InvalidOperationException(Res.GetString(Res.XmlPregenInvalidXmlSerializerAssemblyAttribute, "AssemblyName", "CodeBase"));
  196. // found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer
  197. if (assemblyAttribute.AssemblyName != null) {
  198. serializerName = assemblyAttribute.AssemblyName;
  199. #pragma warning disable 618
  200. serializer = Assembly.LoadWithPartialName(serializerName, null);
  201. #pragma warning restore 618
  202. }
  203. else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0) {
  204. serializerName = assemblyAttribute.CodeBase;
  205. serializer = Assembly.LoadFrom(serializerName);
  206. }
  207. else {
  208. serializerName = type.Assembly.FullName;
  209. serializer = type.Assembly;
  210. }
  211. if (serializer == null) {
  212. throw new FileNotFoundException(null, serializerName);
  213. }
  214. }
  215. Type contractType = GetTypeFromAssembly(serializer, "XmlSerializerContract");
  216. contract = (XmlSerializerImplementation)Activator.CreateInstance(contractType);
  217. if (contract.CanSerialize(type))
  218. return serializer;
  219. #if !FEATURE_PAL // EventLog
  220. if (logEnabled)
  221. Log(Res.GetString(Res.XmlSerializerExpiredDetails, serializerName, type.FullName), EventLogEntryType.Error);
  222. #endif //!FEATURE_PAL // EventLog
  223. return null;
  224. }
  225. #if !FEATURE_PAL // EventLog
  226. static void Log(string message, EventLogEntryType type) {
  227. new EventLogPermission(PermissionState.Unrestricted).Assert();
  228. EventLog.WriteEntry("XmlSerializer", message, type);
  229. }
  230. #endif //!FEATURE_PAL // EventLog
  231. static AssemblyName GetName(Assembly assembly, bool copyName) {
  232. PermissionSet perms = new PermissionSet(PermissionState.None);
  233. perms.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
  234. perms.Assert();
  235. return assembly.GetName(copyName);
  236. }
  237. static bool IsSerializerVersionMatch(Assembly serializer, Type type, string defaultNamespace, string location) {
  238. if (serializer == null)
  239. return false;
  240. object[] attrs = serializer.GetCustomAttributes(typeof(XmlSerializerVersionAttribute), false);
  241. if (attrs.Length != 1)
  242. return false;
  243. XmlSerializerVersionAttribute assemblyInfo = (XmlSerializerVersionAttribute)attrs[0];
  244. // we found out dated pre-generate assembly
  245. //
  246. if (assemblyInfo.ParentAssemblyId == GenerateAssemblyId(type) && assemblyInfo.Namespace == defaultNamespace)
  247. return true;
  248. return false;
  249. }
  250. // SxS: This method does not take any resource name and does not expose any resources to the caller.
  251. // It's OK to suppress the SxS warning.
  252. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  253. [ResourceExposure(ResourceScope.None)]
  254. static string GenerateAssemblyId(Type type) {
  255. Module[] modules = type.Assembly.GetModules();
  256. ArrayList list = new ArrayList();
  257. for (int i = 0; i < modules.Length; i++) {
  258. list.Add(modules[i].ModuleVersionId.ToString());
  259. }
  260. list.Sort();
  261. StringBuilder sb = new StringBuilder();
  262. for (int i = 0; i < list.Count; i++) {
  263. sb.Append(list[i].ToString());
  264. sb.Append(",");
  265. }
  266. return sb.ToString();
  267. }
  268. internal static Assembly GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, string defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) {
  269. FileIOPermission.Assert();
  270. Compiler compiler = new Compiler();
  271. try {
  272. Hashtable scopeTable = new Hashtable();
  273. foreach (XmlMapping mapping in xmlMappings)
  274. scopeTable[mapping.Scope] = mapping;
  275. TypeScope[] scopes = new TypeScope[scopeTable.Keys.Count];
  276. scopeTable.Keys.CopyTo(scopes, 0);
  277. assemblies.Clear();
  278. Hashtable importedTypes = new Hashtable();
  279. foreach (TypeScope scope in scopes) {
  280. foreach (Type t in scope.Types) {
  281. compiler.AddImport(t, importedTypes);
  282. Assembly a = t.Assembly;
  283. string name = a.FullName;
  284. if (assemblies[name] != null)
  285. continue;
  286. if (!a.GlobalAssemblyCache) {
  287. assemblies[name] = a;
  288. }
  289. }
  290. }
  291. for (int i = 0; i < types.Length; i++) {
  292. compiler.AddImport(types[i], importedTypes);
  293. }
  294. compiler.AddImport(typeof(object).Assembly);
  295. compiler.AddImport(typeof(XmlSerializer).Assembly);
  296. IndentedWriter writer = new IndentedWriter(compiler.Source, false);
  297. writer.WriteLine("#if _DYNAMIC_XMLSERIALIZER_COMPILATION");
  298. writer.WriteLine("[assembly:System.Security.AllowPartiallyTrustedCallers()]");
  299. writer.WriteLine("[assembly:System.Security.SecurityTransparent()]");
  300. writer.WriteLine("[assembly:System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]");
  301. writer.WriteLine("#endif");
  302. // Add AssemblyVersion attribute to match parent accembly version
  303. if (types != null && types.Length > 0 && types[0] != null) {
  304. writer.WriteLine("[assembly:System.Reflection.AssemblyVersionAttribute(\"" + types[0].Assembly.GetName().Version.ToString() + "\")]");
  305. }
  306. if (assembly != null && types.Length > 0) {
  307. for (int i = 0; i < types.Length; i++) {
  308. Type type = types[i];
  309. if (type == null)
  310. continue;
  311. if (DynamicAssemblies.IsTypeDynamic(type)) {
  312. throw new InvalidOperationException(Res.GetString(Res.XmlPregenTypeDynamic, types[i].FullName));
  313. }
  314. }
  315. writer.Write("[assembly:");
  316. writer.Write(typeof(XmlSerializerVersionAttribute).FullName);
  317. writer.Write("(");
  318. writer.Write("ParentAssemblyId=");
  319. ReflectionAwareCodeGen.WriteQuotedCSharpString(writer, GenerateAssemblyId(types[0]));
  320. writer.Write(", Version=");
  321. ReflectionAwareCodeGen.WriteQuotedCSharpString(writer, ThisAssembly.Version);
  322. if (defaultNamespace != null) {
  323. writer.Write(", Namespace=");
  324. ReflectionAwareCodeGen.WriteQuotedCSharpString(writer, defaultNamespace);
  325. }
  326. writer.WriteLine(")]");
  327. }
  328. CodeIdentifiers classes = new CodeIdentifiers();
  329. classes.AddUnique("XmlSerializationWriter", "XmlSerializationWriter");
  330. classes.AddUnique("XmlSerializationReader", "XmlSerializationReader");
  331. string suffix = null;
  332. if (types != null && types.Length == 1 && types[0] != null) {
  333. suffix = CodeIdentifier.MakeValid(types[0].Name);
  334. if (types[0].IsArray) {
  335. suffix += "Array";
  336. }
  337. }
  338. writer.WriteLine("namespace " + GeneratedAssemblyNamespace + " {");
  339. writer.Indent++;
  340. writer.WriteLine();
  341. string writerClass = "XmlSerializationWriter" + suffix;
  342. writerClass = classes.AddUnique(writerClass, writerClass);
  343. XmlSerializationWriterCodeGen writerCodeGen = new XmlSerializationWriterCodeGen(writer, scopes, "public", writerClass);
  344. writerCodeGen.GenerateBegin();
  345. string[] writeMethodNames = new string[xmlMappings.Length];
  346. for (int i = 0; i < xmlMappings.Length; i++) {
  347. writeMethodNames[i] = writerCodeGen.GenerateElement(xmlMappings[i]);
  348. }
  349. writerCodeGen.GenerateEnd();
  350. writer.WriteLine();
  351. string readerClass = "XmlSerializationReader" + suffix;
  352. readerClass = classes.AddUnique(readerClass, readerClass);
  353. XmlSerializationReaderCodeGen readerCodeGen = new XmlSerializationReaderCodeGen(writer, scopes, "public", readerClass);
  354. readerCodeGen.GenerateBegin();
  355. string[] readMethodNames = new string[xmlMappings.Length];
  356. for (int i = 0; i < xmlMappings.Length; i++) {
  357. readMethodNames[i] = readerCodeGen.GenerateElement(xmlMappings[i]);
  358. }
  359. readerCodeGen.GenerateEnd(readMethodNames, xmlMappings, types);
  360. string baseSerializer = readerCodeGen.GenerateBaseSerializer("XmlSerializer1", readerClass, writerClass, classes);
  361. Hashtable serializers = new Hashtable();
  362. for (int i = 0; i < xmlMappings.Length; i++) {
  363. if (serializers[xmlMappings[i].Key] == null) {
  364. serializers[xmlMappings[i].Key] = readerCodeGen.GenerateTypedSerializer(readMethodNames[i], writeMethodNames[i], xmlMappings[i], classes, baseSerializer, readerClass, writerClass);
  365. }
  366. }
  367. readerCodeGen.GenerateSerializerContract("XmlSerializerContract", xmlMappings, types, readerClass, readMethodNames, writerClass, writeMethodNames, serializers);
  368. writer.Indent--;
  369. writer.WriteLine("}");
  370. return compiler.Compile(assembly, defaultNamespace, parameters, evidence);
  371. }
  372. finally {
  373. compiler.Close();
  374. }
  375. }
  376. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification="It is safe because the serialization assembly is generated by the framework code, not by the user.")]
  377. internal static Assembly GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type[] types, string defaultNamespace, Evidence evidence) {
  378. Hashtable scopeTable = new Hashtable();
  379. foreach (XmlMapping mapping in xmlMappings)
  380. scopeTable[mapping.Scope] = mapping;
  381. TypeScope[] scopes = new TypeScope[scopeTable.Keys.Count];
  382. scopeTable.Keys.CopyTo(scopes, 0);
  383. string assemblyName = "Microsoft.GeneratedCode";
  384. AssemblyBuilder assemblyBuilder = CodeGenerator.CreateAssemblyBuilder(AppDomain.CurrentDomain, assemblyName);
  385. ConstructorInfo SecurityTransparentAttribute_ctor = typeof(SecurityTransparentAttribute).GetConstructor(
  386. CodeGenerator.InstanceBindingFlags,
  387. null,
  388. CodeGenerator.EmptyTypeArray,
  389. null
  390. );
  391. assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(SecurityTransparentAttribute_ctor, new Object[0]));
  392. ConstructorInfo AllowPartiallyTrustedCallersAttribute_ctor = typeof(AllowPartiallyTrustedCallersAttribute).GetConstructor(
  393. CodeGenerator.InstanceBindingFlags,
  394. null,
  395. CodeGenerator.EmptyTypeArray,
  396. null
  397. );
  398. assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(AllowPartiallyTrustedCallersAttribute_ctor, new Object[0]));
  399. ConstructorInfo SecurityRulesAttribute_ctor = typeof(SecurityRulesAttribute).GetConstructor(
  400. CodeGenerator.InstanceBindingFlags,
  401. null,
  402. new Type[] { typeof(SecurityRuleSet) },
  403. null
  404. );
  405. assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(SecurityRulesAttribute_ctor, new Object[] { SecurityRuleSet.Level1 }));
  406. // Add AssemblyVersion attribute to match parent accembly version
  407. if (types != null && types.Length > 0 && types[0] != null) {
  408. ConstructorInfo AssemblyVersionAttribute_ctor = typeof(AssemblyVersionAttribute).GetConstructor(
  409. CodeGenerator.InstanceBindingFlags,
  410. null,
  411. new Type[] { typeof(String) },
  412. null
  413. );
  414. FileIOPermission.Assert();
  415. string assemblyVersion = types[0].Assembly.GetName().Version.ToString();
  416. FileIOPermission.RevertAssert();
  417. assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(AssemblyVersionAttribute_ctor, new Object[] { assemblyVersion }));
  418. }
  419. CodeIdentifiers classes = new CodeIdentifiers();
  420. classes.AddUnique("XmlSerializationWriter", "XmlSerializationWriter");
  421. classes.AddUnique("XmlSerializationReader", "XmlSerializationReader");
  422. string suffix = null;
  423. if (types != null && types.Length == 1 && types[0] != null) {
  424. suffix = CodeIdentifier.MakeValid(types[0].Name);
  425. if (types[0].IsArray) {
  426. suffix += "Array";
  427. }
  428. }
  429. ModuleBuilder moduleBuilder = CodeGenerator.CreateModuleBuilder(assemblyBuilder, assemblyName);
  430. string writerClass = "XmlSerializationWriter" + suffix;
  431. writerClass = classes.AddUnique(writerClass, writerClass);
  432. XmlSerializationWriterILGen writerCodeGen = new XmlSerializationWriterILGen(scopes, "public", writerClass);
  433. writerCodeGen.ModuleBuilder = moduleBuilder;
  434. writerCodeGen.GenerateBegin();
  435. string[] writeMethodNames = new string[xmlMappings.Length];
  436. for (int i = 0; i < xmlMappings.Length; i++) {
  437. writeMethodNames[i] = writerCodeGen.GenerateElement(xmlMappings[i]);
  438. }
  439. Type writerType = writerCodeGen.GenerateEnd();
  440. string readerClass = "XmlSerializationReader" + suffix;
  441. readerClass = classes.AddUnique(readerClass, readerClass);
  442. XmlSerializationReaderILGen readerCodeGen = new XmlSerializationReaderILGen(scopes, "public", readerClass);
  443. readerCodeGen.ModuleBuilder = moduleBuilder;
  444. readerCodeGen.CreatedTypes.Add(writerType.Name, writerType);
  445. readerCodeGen.GenerateBegin();
  446. string[] readMethodNames = new string[xmlMappings.Length];
  447. for (int i = 0; i < xmlMappings.Length; i++) {
  448. readMethodNames[i] = readerCodeGen.GenerateElement(xmlMappings[i]);
  449. }
  450. readerCodeGen.GenerateEnd(readMethodNames, xmlMappings, types);
  451. string baseSerializer = readerCodeGen.GenerateBaseSerializer("XmlSerializer1", readerClass, writerClass, classes);
  452. Hashtable serializers = new Hashtable();
  453. for (int i = 0; i < xmlMappings.Length; i++) {
  454. if (serializers[xmlMappings[i].Key] == null) {
  455. serializers[xmlMappings[i].Key] = readerCodeGen.GenerateTypedSerializer(readMethodNames[i], writeMethodNames[i], xmlMappings[i], classes, baseSerializer, readerClass, writerClass);
  456. }
  457. }
  458. readerCodeGen.GenerateSerializerContract("XmlSerializerContract", xmlMappings, types, readerClass, readMethodNames, writerClass, writeMethodNames, serializers);
  459. if (DiagnosticsSwitches.KeepTempFiles.Enabled) {
  460. FileIOPermission.Assert();
  461. assemblyBuilder.Save(assemblyName + ".dll");
  462. }
  463. return writerType.Assembly;
  464. }
  465. // SxS: This method does not take any resource name and does not expose any resources to the caller.
  466. // It's OK to suppress the SxS warning.
  467. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  468. [ResourceExposure(ResourceScope.None)]
  469. static MethodInfo GetMethodFromType(Type type, string methodName, Assembly assembly) {
  470. MethodInfo method = type.GetMethod(methodName);
  471. if (method != null)
  472. return method;
  473. MissingMethodException missingMethod = new MissingMethodException(type.FullName, methodName);
  474. if (assembly != null) {
  475. throw new InvalidOperationException(Res.GetString(Res.XmlSerializerExpired, assembly.FullName, assembly.CodeBase), missingMethod);
  476. }
  477. throw missingMethod;
  478. }
  479. internal static Type GetTypeFromAssembly(Assembly assembly, string typeName) {
  480. typeName = GeneratedAssemblyNamespace + "." + typeName;
  481. Type type = assembly.GetType(typeName);
  482. if (type == null) throw new InvalidOperationException(Res.GetString(Res.XmlMissingType, typeName, assembly.FullName));
  483. return type;
  484. }
  485. internal bool CanRead(XmlMapping mapping, XmlReader xmlReader) {
  486. if (mapping == null)
  487. return false;
  488. if (mapping.Accessor.Any) {
  489. return true;
  490. }
  491. TempMethod method = methods[mapping.Key];
  492. return xmlReader.IsStartElement(method.name, method.ns);
  493. }
  494. string ValidateEncodingStyle(string encodingStyle, string methodKey) {
  495. if (encodingStyle != null && encodingStyle.Length > 0) {
  496. if (methods[methodKey].isSoap) {
  497. if (encodingStyle != Soap.Encoding && encodingStyle != Soap12.Encoding) {
  498. throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEncoding3, encodingStyle, Soap.Encoding, Soap12.Encoding));
  499. }
  500. }
  501. else {
  502. throw new InvalidOperationException(Res.GetString(Res.XmlInvalidEncodingNotEncoded1, encodingStyle));
  503. }
  504. }
  505. else {
  506. if (methods[methodKey].isSoap) {
  507. encodingStyle = Soap.Encoding;
  508. }
  509. }
  510. return encodingStyle;
  511. }
  512. internal static FileIOPermission FileIOPermission {
  513. get {
  514. if (fileIOPermission == null)
  515. fileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
  516. return fileIOPermission;
  517. }
  518. }
  519. internal object InvokeReader(XmlMapping mapping, XmlReader xmlReader, XmlDeserializationEvents events, string encodingStyle) {
  520. XmlSerializationReader reader = null;
  521. try {
  522. encodingStyle = ValidateEncodingStyle(encodingStyle, mapping.Key);
  523. reader = Contract.Reader;
  524. reader.Init(xmlReader, events, encodingStyle, this);
  525. if (methods[mapping.Key].readMethod == null) {
  526. if (readerMethods == null) {
  527. readerMethods = Contract.ReadMethods;
  528. }
  529. string methodName = (string)readerMethods[mapping.Key];
  530. if (methodName == null) {
  531. throw new InvalidOperationException(Res.GetString(Res.XmlNotSerializable, mapping.Accessor.Name));
  532. }
  533. methods[mapping.Key].readMethod = GetMethodFromType(reader.GetType(), methodName, pregeneratedAssmbly ? this.assembly : null);
  534. }
  535. return methods[mapping.Key].readMethod.Invoke(reader, emptyObjectArray);
  536. }
  537. catch (SecurityException e) {
  538. throw new InvalidOperationException(Res.GetString(Res.XmlNoPartialTrust), e);
  539. }
  540. finally {
  541. if (reader != null)
  542. reader.Dispose();
  543. }
  544. }
  545. internal void InvokeWriter(XmlMapping mapping, XmlWriter xmlWriter, object o, XmlSerializerNamespaces namespaces, string encodingStyle, string id) {
  546. XmlSerializationWriter writer = null;
  547. try {
  548. encodingStyle = ValidateEncodingStyle(encodingStyle, mapping.Key);
  549. writer = Contract.Writer;
  550. writer.Init(xmlWriter, namespaces, encodingStyle, id, this);
  551. if (methods[mapping.Key].writeMethod == null) {
  552. if (writerMethods == null) {
  553. writerMethods = Contract.WriteMethods;
  554. }
  555. string methodName = (string)writerMethods[mapping.Key];
  556. if (methodName == null) {
  557. throw new InvalidOperationException(Res.GetString(Res.XmlNotSerializable, mapping.Accessor.Name));
  558. }
  559. methods[mapping.Key].writeMethod = GetMethodFromType(writer.GetType(), methodName, pregeneratedAssmbly ? assembly : null);
  560. }
  561. methods[mapping.Key].writeMethod.Invoke(writer, new object[] { o });
  562. }
  563. catch (SecurityException e) {
  564. throw new InvalidOperationException(Res.GetString(Res.XmlNoPartialTrust), e);
  565. }
  566. finally {
  567. if (writer != null)
  568. writer.Dispose();
  569. }
  570. }
  571. internal Assembly GetReferencedAssembly(string name) {
  572. return assemblies != null && name != null ? (Assembly)assemblies[name] : null;
  573. }
  574. internal bool NeedAssembyResolve {
  575. get { return assemblies != null && assemblies.Count > 0; }
  576. }
  577. internal sealed class TempMethodDictionary : DictionaryBase {
  578. internal TempMethod this[string key] {
  579. get {
  580. return (TempMethod)Dictionary[key];
  581. }
  582. }
  583. internal void Add(string key, TempMethod value) {
  584. Dictionary.Add(key, value);
  585. }
  586. }
  587. }
  588. sealed class XmlSerializerCompilerParameters {
  589. bool needTempDirAccess;
  590. CompilerParameters parameters;
  591. XmlSerializerCompilerParameters(CompilerParameters parameters, bool needTempDirAccess) {
  592. this.needTempDirAccess = needTempDirAccess;
  593. this.parameters = parameters;
  594. }
  595. internal bool IsNeedTempDirAccess { get { return this.needTempDirAccess; } }
  596. internal CompilerParameters CodeDomParameters { get { return this.parameters; } }
  597. internal static XmlSerializerCompilerParameters Create(string location) {
  598. CompilerParameters parameters = new CompilerParameters();
  599. parameters.GenerateInMemory = true;
  600. if (string.IsNullOrEmpty(location)) {
  601. #if CONFIGURATION_DEP
  602. XmlSerializerSection configSection = ConfigurationManager.GetSection(ConfigurationStrings.XmlSerializerSectionPath) as XmlSerializerSection;
  603. location = configSection == null ? location : configSection.TempFilesLocation;
  604. #endif
  605. // Trim leading and trailing white spaces (VSWhidbey 229873)
  606. if (!string.IsNullOrEmpty(location)) {
  607. location = location.Trim();
  608. }
  609. }
  610. parameters.TempFiles = new TempFileCollection(location);
  611. return new XmlSerializerCompilerParameters(parameters, string.IsNullOrEmpty(location));
  612. }
  613. internal static XmlSerializerCompilerParameters Create(CompilerParameters parameters, bool needTempDirAccess) {
  614. return new XmlSerializerCompilerParameters(parameters, needTempDirAccess);
  615. }
  616. }
  617. class TempAssemblyCacheKey {
  618. string ns;
  619. object type;
  620. internal TempAssemblyCacheKey(string ns, object type) {
  621. this.type = type;
  622. this.ns = ns;
  623. }
  624. public override bool Equals(object o) {
  625. TempAssemblyCacheKey key = o as TempAssemblyCacheKey;
  626. if (key == null) return false;
  627. return (key.type == this.type && key.ns == this.ns);
  628. }
  629. public override int GetHashCode() {
  630. return ((ns != null ? ns.GetHashCode() : 0) ^ (type != null ? type.GetHashCode() : 0));
  631. }
  632. }
  633. internal class TempAssemblyCache {
  634. Hashtable cache = new Hashtable();
  635. internal TempAssembly this[string ns, object o] {
  636. get { return (TempAssembly)cache[new TempAssemblyCacheKey(ns, o)]; }
  637. }
  638. internal void Add(string ns, object o, TempAssembly assembly) {
  639. TempAssemblyCacheKey key = new TempAssemblyCacheKey(ns, o);
  640. lock (this) {
  641. if (cache[key] == assembly) return;
  642. Hashtable clone = new Hashtable();
  643. foreach (object k in cache.Keys) {
  644. clone.Add(k, cache[k]);
  645. }
  646. cache = clone;
  647. cache[key] = assembly;
  648. }
  649. }
  650. }
  651. }