| File: System\Xml\Serialization\XmlSerializationGeneratedCode.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml) |
// 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.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Reflection; using System.Security; using System.Threading; namespace System.Xml.Serialization { ///<internalonly/> public abstract class XmlSerializationGeneratedCode { } internal class XmlSerializationCodeGen { private readonly IndentedWriter _writer; private int _nextMethodNumber; private readonly Hashtable _methodNames = new Hashtable(); private readonly ReflectionAwareCodeGen _raCodeGen; private readonly TypeScope[] _scopes; private readonly TypeDesc? _stringTypeDesc; private readonly TypeDesc? _qnameTypeDesc; private readonly string _access; private readonly string _className; private TypeMapping[]? _referencedMethods; private int _references; private readonly Hashtable _generatedMethods = new Hashtable(); [RequiresUnreferencedCode("Calls GetTypeDesc")] internal XmlSerializationCodeGen(IndentedWriter writer, TypeScope[] scopes, string access, string className) { _writer = writer; _scopes = scopes; if (scopes.Length > 0) { _stringTypeDesc = scopes[0].GetTypeDesc(typeof(string)); _qnameTypeDesc = scopes[0].GetTypeDesc(typeof(XmlQualifiedName)); } _raCodeGen = new ReflectionAwareCodeGen(writer); _className = className; _access = access; } internal IndentedWriter Writer { get { return _writer; } } internal int NextMethodNumber { get { return _nextMethodNumber; } set { _nextMethodNumber = value; } } internal ReflectionAwareCodeGen RaCodeGen { get { return _raCodeGen; } } internal TypeDesc? StringTypeDesc { get { return _stringTypeDesc; } } internal TypeDesc? QnameTypeDesc { get { return _qnameTypeDesc; } } internal string ClassName { get { return _className; } } internal string Access { get { return _access; } } internal TypeScope[] Scopes { get { return _scopes; } } internal Hashtable MethodNames { get { return _methodNames; } } internal Hashtable GeneratedMethods { get { return _generatedMethods; } } [RequiresUnreferencedCode("calls WriteStructMethod")] internal virtual void GenerateMethod(TypeMapping mapping) { } [RequiresUnreferencedCode("calls GenerateMethod")] internal void GenerateReferencedMethods() { while (_references > 0) { TypeMapping mapping = _referencedMethods![--_references]; GenerateMethod(mapping); } } internal string? ReferenceMapping(TypeMapping mapping) { if (!mapping.IsSoap) { if (_generatedMethods[mapping] == null) { _referencedMethods = EnsureArrayIndex(_referencedMethods!, _references); _referencedMethods[_references++] = mapping; } } return (string?)_methodNames[mapping]; } private static TypeMapping[] EnsureArrayIndex(TypeMapping[] a, int index) { if (a == null) return new TypeMapping[32]; if (index < a.Length) return a; TypeMapping[] b = new TypeMapping[a.Length + 32]; Array.Copy(a, b, index); return b; } internal void WriteQuotedCSharpString(string? value) { _raCodeGen.WriteQuotedCSharpString(value); } internal void GenerateHashtableGetBegin(string privateName, string publicName) { _writer.Write(typeof(Hashtable).FullName); _writer.Write(" "); _writer.Write(privateName); _writer.WriteLine(" = null;"); _writer.Write("public override "); _writer.Write(typeof(Hashtable).FullName); _writer.Write(" "); _writer.Write(publicName); _writer.WriteLine(" {"); _writer.Indent++; _writer.WriteLine("get {"); _writer.Indent++; _writer.Write("if ("); _writer.Write(privateName); _writer.WriteLine(" == null) {"); _writer.Indent++; _writer.Write(typeof(Hashtable).FullName); _writer.Write(" _tmp = new "); _writer.Write(typeof(Hashtable).FullName); _writer.WriteLine("();"); } internal void GenerateHashtableGetEnd(string privateName) { _writer.Write("if ("); _writer.Write(privateName); _writer.Write(" == null) "); _writer.Write(privateName); _writer.WriteLine(" = _tmp;"); _writer.Indent--; _writer.WriteLine("}"); _writer.Write("return "); _writer.Write(privateName); _writer.WriteLine(";"); _writer.Indent--; _writer.WriteLine("}"); _writer.Indent--; _writer.WriteLine("}"); } internal void GeneratePublicMethods(string privateName, string publicName, string?[] methods, XmlMapping[] xmlMappings) { GenerateHashtableGetBegin(privateName, publicName); if (methods != null && methods.Length != 0 && xmlMappings != null && xmlMappings.Length == methods.Length) { for (int i = 0; i < methods.Length; i++) { if (methods[i] == null) continue; _writer.Write("_tmp["); WriteQuotedCSharpString(xmlMappings[i].Key); _writer.Write("] = "); WriteQuotedCSharpString(methods[i]); _writer.WriteLine(";"); } } GenerateHashtableGetEnd(privateName); } internal void GenerateSupportedTypes(Type?[] types) { _writer.Write("public override "); _writer.Write(typeof(bool).FullName); _writer.Write(" CanSerialize("); _writer.Write(typeof(Type).FullName); _writer.WriteLine(" type) {"); _writer.Indent++; Hashtable uniqueTypes = new Hashtable(); for (int i = 0; i < types.Length; i++) { Type? type = types[i]; if (type == null) continue; if (!type.IsPublic && !type.IsNestedPublic) continue; if (uniqueTypes[type] != null) continue; if (DynamicAssemblies.IsTypeDynamic(type)) continue; if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments())) continue; uniqueTypes[type] = type; _writer.Write("if (type == typeof("); _writer.Write(CodeIdentifier.GetCSharpName(type)); _writer.WriteLine(")) return true;"); } _writer.WriteLine("return false;"); _writer.Indent--; _writer.WriteLine("}"); } internal string GenerateBaseSerializer(string baseSerializer, string readerClass, string writerClass, CodeIdentifiers classes) { baseSerializer = CodeIdentifier.MakeValid(baseSerializer); baseSerializer = classes.AddUnique(baseSerializer, baseSerializer); _writer.WriteLine(); _writer.Write("public abstract class "); _writer.Write(CodeIdentifier.GetCSharpName(baseSerializer)); _writer.Write(" : "); _writer.Write(typeof(System.Xml.Serialization.XmlSerializer).FullName); _writer.WriteLine(" {"); _writer.Indent++; _writer.Write("protected override "); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationReader).FullName); _writer.WriteLine(" CreateReader() {"); _writer.Indent++; _writer.Write("return new "); _writer.Write(readerClass); _writer.WriteLine("();"); _writer.Indent--; _writer.WriteLine("}"); _writer.Write("protected override "); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationWriter).FullName); _writer.WriteLine(" CreateWriter() {"); _writer.Indent++; _writer.Write("return new "); _writer.Write(writerClass); _writer.WriteLine("();"); _writer.Indent--; _writer.WriteLine("}"); _writer.Indent--; _writer.WriteLine("}"); return baseSerializer; } internal string GenerateTypedSerializer(string? readMethod, string? writeMethod, XmlMapping mapping, CodeIdentifiers classes, string baseSerializer, string readerClass, string writerClass) { string serializerName = CodeIdentifier.MakeValid(Accessor.UnescapeName(mapping.Accessor.Mapping!.TypeDesc!.Name)); serializerName = classes.AddUnique($"{serializerName}Serializer", mapping); _writer.WriteLine(); _writer.Write("public sealed class "); _writer.Write(CodeIdentifier.GetCSharpName(serializerName)); _writer.Write(" : "); _writer.Write(baseSerializer); _writer.WriteLine(" {"); _writer.Indent++; _writer.WriteLine(); _writer.Write("public override "); _writer.Write(typeof(bool).FullName); _writer.Write(" CanDeserialize("); _writer.Write(typeof(XmlReader).FullName); _writer.WriteLine(" xmlReader) {"); _writer.Indent++; if (mapping.Accessor.Any) { _writer.WriteLine("return true;"); } else { _writer.Write("return xmlReader.IsStartElement("); WriteQuotedCSharpString(mapping.Accessor.Name); _writer.Write(", "); WriteQuotedCSharpString(mapping.Accessor.Namespace); _writer.WriteLine(");"); } _writer.Indent--; _writer.WriteLine("}"); if (writeMethod != null) { _writer.WriteLine(); _writer.Write("protected override void Serialize(object objectToSerialize, "); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationWriter).FullName); _writer.WriteLine(" writer) {"); _writer.Indent++; _writer.Write("(("); _writer.Write(writerClass); _writer.Write(")writer)."); _writer.Write(writeMethod); _writer.Write("("); if (mapping is XmlMembersMapping) { _writer.Write("(object[])"); } _writer.WriteLine("objectToSerialize);"); _writer.Indent--; _writer.WriteLine("}"); } if (readMethod != null) { _writer.WriteLine(); _writer.Write("protected override object Deserialize("); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationReader).FullName); _writer.WriteLine(" reader) {"); _writer.Indent++; _writer.Write("return (("); _writer.Write(readerClass); _writer.Write(")reader)."); _writer.Write(readMethod); _writer.WriteLine("();"); _writer.Indent--; _writer.WriteLine("}"); } _writer.Indent--; _writer.WriteLine("}"); return serializerName; } private void GenerateTypedSerializers(Hashtable serializers) { string privateName = "typedSerializers"; GenerateHashtableGetBegin(privateName, "TypedSerializers"); foreach (string key in serializers.Keys) { _writer.Write("_tmp.Add("); WriteQuotedCSharpString(key); _writer.Write(", new "); _writer.Write((string?)serializers[key]); _writer.WriteLine("());"); } GenerateHashtableGetEnd("typedSerializers"); } //GenerateGetSerializer(serializers, xmlMappings); private void GenerateGetSerializer(Hashtable serializers, XmlMapping[] xmlMappings) { _writer.Write("public override "); _writer.Write(typeof(System.Xml.Serialization.XmlSerializer).FullName); _writer.Write(" GetSerializer("); _writer.Write(typeof(Type).FullName); _writer.WriteLine(" type) {"); _writer.Indent++; for (int i = 0; i < xmlMappings.Length; i++) { if (xmlMappings[i] is XmlTypeMapping) { Type? type = xmlMappings[i].Accessor.Mapping!.TypeDesc!.Type; if (type == null) continue; if (!type.IsPublic && !type.IsNestedPublic) continue; if (DynamicAssemblies.IsTypeDynamic(type)) continue; if (type.IsGenericType || type.ContainsGenericParameters && DynamicAssemblies.IsTypeDynamic(type.GetGenericArguments())) continue; _writer.Write("if (type == typeof("); _writer.Write(CodeIdentifier.GetCSharpName(type)); _writer.Write(")) return new "); _writer.Write((string?)serializers[xmlMappings[i].Key!]); _writer.WriteLine("();"); } } _writer.WriteLine("return null;"); _writer.Indent--; _writer.WriteLine("}"); } internal void GenerateSerializerContract(XmlMapping[] xmlMappings, Type?[] types, string readerType, string?[] readMethods, string writerType, string?[] writerMethods, Hashtable serializers) { _writer.WriteLine(); _writer.Write("public class XmlSerializerContract : global::"); _writer.Write(typeof(System.Xml.Serialization.XmlSerializerImplementation).FullName); _writer.WriteLine(" {"); _writer.Indent++; _writer.Write("public override global::"); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationReader).FullName); _writer.Write(" Reader { get { return new "); _writer.Write(readerType); _writer.WriteLine("(); } }"); _writer.Write("public override global::"); _writer.Write(typeof(System.Xml.Serialization.XmlSerializationWriter).FullName); _writer.Write(" Writer { get { return new "); _writer.Write(writerType); _writer.WriteLine("(); } }"); GeneratePublicMethods(nameof(readMethods), "ReadMethods", readMethods, xmlMappings); GeneratePublicMethods("writeMethods", "WriteMethods", writerMethods, xmlMappings); GenerateTypedSerializers(serializers); GenerateSupportedTypes(types); GenerateGetSerializer(serializers, xmlMappings); _writer.Indent--; _writer.WriteLine("}"); } internal static bool IsWildcard(SpecialMapping mapping) { if (mapping is SerializableMapping) return ((SerializableMapping)mapping).IsAny; return mapping.TypeDesc!.CanBeElementValue; } } }