| File: CodeDomFixup\CodeDomVisitors\SpecialIXmlSerializableRemapper.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using Microsoft.CodeDom; using System.Collections.Generic; namespace Microsoft.Tools.ServiceModel.Svcutil { internal class SpecialIXmlSerializableRemapper : SimpleTypeRemapper { private Dictionary<string, CodeTypeDeclaration> _specialIXmlSerializableTypes = new Dictionary<string, CodeTypeDeclaration>(); private TypeDeclCollection _typeDeclCollection = new TypeDeclCollection(); private const string specialTypeName = "schema"; private const string specialFieldName = "schema"; private static string s_currentMatchingFullTypeName = null; private readonly ArrayOfXElementTypeHelper _arrayOfXElementTypeHelper; public SpecialIXmlSerializableRemapper(ArrayOfXElementTypeHelper arrayOfXElementTypeHelper) : base(null, ArrayOfXElementTypeHelper.ArrayOfXElementRef.BaseType) { _arrayOfXElementTypeHelper = arrayOfXElementTypeHelper; } protected override bool Match(CodeTypeReference typeref) { if (typeref.BaseType.Contains(".")) { s_currentMatchingFullTypeName = typeref.BaseType; return _specialIXmlSerializableTypes.ContainsKey(typeref.BaseType); } else { return MatchTypeName(typeref.BaseType); } } private bool MatchTypeName(string typeName) { foreach (string name in _specialIXmlSerializableTypes.Keys) { if (name.EndsWith(typeName, StringComparison.Ordinal)) { s_currentMatchingFullTypeName = name; return true; } } s_currentMatchingFullTypeName = null; return false; } private bool IsSpecialIXmlSerializableType(CodeTypeDeclaration type) { foreach (CodeTypeMember member in type.Members) { CodeMemberProperty memberProp = member as CodeMemberProperty; if (memberProp != null) { if (memberProp.Name == specialFieldName && memberProp.Type.BaseType == specialTypeName && !_typeDeclCollection.AllTypeDecls.ContainsKey(specialTypeName)) { return true; } } } return false; } private static bool IsIXmlSerializableType(CodeTypeDeclaration typeDecl) { foreach (CodeTypeReference typeRef in typeDecl.BaseTypes) { if (CodeDomHelpers.MatchType<Microsoft.Xml.Serialization.IXmlSerializable>(typeRef)) return true; } return false; } protected override void Map(CodeTypeReference typeref) { string typeNamespace = _typeDeclCollection.TypeNamespaceMappings[s_currentMatchingFullTypeName]; if (!string.IsNullOrEmpty(s_currentMatchingFullTypeName)) { _arrayOfXElementTypeHelper.CheckToAdd(typeNamespace); } typeref.BaseType = string.IsNullOrEmpty(typeNamespace) ? destType : _typeDeclCollection.TypeNamespaceMappings[s_currentMatchingFullTypeName] + "." + destType; } protected override void Visit(CodeCompileUnit cu) { base.Visit(cu); _typeDeclCollection.Visit(cu); CodeTypeDeclaration typeDecl; foreach (string typeName in _typeDeclCollection.AllTypeDecls.Keys) { typeDecl = _typeDeclCollection.AllTypeDecls[typeName]; if (IsSpecialIXmlSerializableType(typeDecl) || IsIXmlSerializableType(typeDecl)) { System.Diagnostics.Debug.Assert(!_specialIXmlSerializableTypes.ContainsKey(typeName), $"Key '{typeName}' already added to dictionary!"); _specialIXmlSerializableTypes[typeName] = _typeDeclCollection.AllTypeDecls[typeName]; } } } protected override void FinishVisit(CodeCompileUnit cu) { base.FinishVisit(cu); List<string> namespaceToAdd = new List<string>(); foreach (CodeNamespace ns in cu.Namespaces) { foreach (CodeTypeDeclaration typeDecl in _specialIXmlSerializableTypes.Values) { if (ns.Types.Contains(typeDecl)) { ns.Types.Remove(typeDecl); namespaceToAdd.Add(ns.Name); } } } foreach (string ns in namespaceToAdd) { _arrayOfXElementTypeHelper.AddToCompileUnit(cu, ns); } } } }