From f26a1438b933aef75993d5245f2787cbfb90e74f Mon Sep 17 00:00:00 2001 From: Tal Aloni Date: Sat, 7 Aug 2021 01:48:07 +0300 Subject: [PATCH] Sgen: Added 'default-namespace' argument (#46500) * Sgen: Added an optional 'default-namespace' argument The .NET runtime support loading pre-generated assemblies according to both the type & defaultNamespace when creating an XmlSerializer instance, Given that, it is extremely useful to have the ability to generate an assembly for different defaultNamespace. * Added defaultNamespace argument to XmlReflectionImporter * Prevent setting default-namespace twice * Added missing using statement --- .../src/Sgen.cs | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs index 00cff1573636f..9431d4a68855a 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/Sgen.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -28,6 +29,7 @@ private int Run(string[] args) { string assembly = null; var types = new List(); + string defaultNamespace = null; string codePath = null; var errs = new List(); bool force = false; @@ -102,6 +104,18 @@ private int Run(string[] args) assembly = args[i]; } } + else if (ArgumentMatch(arg, "default-namespace")) + { + i++; + if (i >= args.Length || defaultNamespace != null) + { + errs.Add(SR.Format(SR.ErrInvalidArgument, arg)); + } + else + { + defaultNamespace = args[i]; + } + } else if (ArgumentMatch(arg, "quiet")) { disableRun = false; @@ -189,7 +203,7 @@ private int Run(string[] args) ParseReferences(); } - GenerateFile(types, assembly, proxyOnly, silent, verbose, force, codePath, parsableErrors); + GenerateFile(types, defaultNamespace, assembly, proxyOnly, silent, verbose, force, codePath, parsableErrors); } catch (Exception e) { @@ -205,7 +219,7 @@ private int Run(string[] args) return 0; } - private void GenerateFile(List typeNames, string assemblyName, bool proxyOnly, bool silent, bool verbose, bool force, string outputDirectory, bool parsableerrors) + private void GenerateFile(List typeNames, string defaultNamespace, string assemblyName, bool proxyOnly, bool silent, bool verbose, bool force, string outputDirectory, bool parsableerrors) { Assembly assembly = LoadAssembly(assemblyName, true); Type[] types; @@ -248,7 +262,7 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox var mappings = new List(); var importedTypes = new List(); - var importer = new XmlReflectionImporter(); + var importer = new XmlReflectionImporter(defaultNamespace); for (int i = 0; i < types.Length; i++) { @@ -294,7 +308,7 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox if (!proxyOnly) { - ImportType(type, mappings, importedTypes, verbose, importer, parsableerrors); + ImportType(type, defaultNamespace, mappings, importedTypes, verbose, importer, parsableerrors); } } @@ -318,7 +332,7 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox } } - string serializerName = GetXmlSerializerAssemblyName(serializableTypes[0], null); + string serializerName = GetXmlSerializerAssemblyName(serializableTypes[0], defaultNamespace); string codePath = Path.Combine(outputDirectory, serializerName + ".cs"); if (!force) @@ -344,14 +358,31 @@ private void GenerateFile(List typeNames, string assemblyName, bool prox using (FileStream fs = File.Create(codePath)) { - MethodInfo method = typeof(System.Xml.Serialization.XmlSerializer).GetMethod("GenerateSerializer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + MethodInfo method; + if (defaultNamespace == null) + { + method = typeof(System.Xml.Serialization.XmlSerializer).GetMethod("GenerateSerializer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } + else + { + Type tempAssemblyType = typeof(System.Xml.Serialization.XmlSerializer).Assembly.GetType("System.Xml.Serialization.TempAssembly"); + method = tempAssemblyType.GetMethod("GenerateSerializerToStream", BindingFlags.Static | BindingFlags.NonPublic); + } + if (method == null) { Console.Error.WriteLine(FormatMessage(parsableerrors: false, warning: false, message: SR.GenerateSerializerNotFound)); } else { - success = (bool)method.Invoke(null, new object[] { serializableTypes, allMappings, fs }); + if (defaultNamespace == null) + { + success = (bool)method.Invoke(null, new object[] { serializableTypes, allMappings, fs }); + } + else + { + success = (bool)method.Invoke(null, new object[] { allMappings, serializableTypes, defaultNamespace, assembly, new Hashtable(), fs }); + } } } } @@ -410,13 +441,13 @@ private bool ShortNameArgumentMatch(string arg, string shortName) return arg.Equals(shortName, StringComparison.InvariantCultureIgnoreCase); } - private void ImportType(Type type, List mappings, List importedTypes, bool verbose, XmlReflectionImporter importer, bool parsableerrors) + private void ImportType(Type type, string defaultNamespace, List mappings, List importedTypes, bool verbose, XmlReflectionImporter importer, bool parsableerrors) { XmlTypeMapping xmlTypeMapping = null; - var localImporter = new XmlReflectionImporter(); + var localImporter = new XmlReflectionImporter(defaultNamespace); try { - xmlTypeMapping = localImporter.ImportTypeMapping(type); + xmlTypeMapping = localImporter.ImportTypeMapping(type, defaultNamespace); } catch (Exception e) { @@ -435,7 +466,7 @@ private void ImportType(Type type, List mappings, List importe } if (xmlTypeMapping != null) { - xmlTypeMapping = importer.ImportTypeMapping(type); + xmlTypeMapping = importer.ImportTypeMapping(type, defaultNamespace); mappings.Add(xmlTypeMapping); importedTypes.Add(type); }