File: System\Xaml\XamlTypeName.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\System.Xaml\System.Xaml.csproj (System.Xaml)
// 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.
 
#nullable disable
 
using System.Text;
using MS.Internal.Xaml.Parser;
 
namespace System.Xaml.Schema
{
    [DebuggerDisplay("{ToString()}")]
    public class XamlTypeName
    {
        List<XamlTypeName> _typeArguments;
 
        public string Name { get; set; }
        public string Namespace { get; set; }
 
        public XamlTypeName()
        {
        }
 
        public XamlTypeName(string xamlNamespace, string name)
            : this(xamlNamespace, name, null)
        {
        }
 
        public XamlTypeName(string xamlNamespace, string name, IEnumerable<XamlTypeName> typeArguments)
        {
            Name = name;
            Namespace = xamlNamespace;
            if (typeArguments is not null)
            {
                List<XamlTypeName> typeArgList = new List<XamlTypeName>(typeArguments);
                _typeArguments = typeArgList;
            }
        }
 
        public XamlTypeName(XamlType xamlType)
        {
            ArgumentNullException.ThrowIfNull(xamlType);
            Name = xamlType.Name;
            Namespace = xamlType.GetXamlNamespaces()[0];
            if (xamlType.TypeArguments is not null)
            {
                foreach (XamlType argumentType in xamlType.TypeArguments)
                {
                    TypeArguments.Add(new XamlTypeName(argumentType));
                }
            }
        }
 
        public IList<XamlTypeName> TypeArguments
        {
            get
            {
                if (_typeArguments is null)
                {
                    _typeArguments = new List<XamlTypeName>();
                }
                return _typeArguments;
            }
        }
 
        internal List<XamlTypeName> TypeArgumentsList => _typeArguments;
 
        public override string ToString()
        {
            return ToString(null);
        }
 
        public string ToString(INamespacePrefixLookup prefixLookup)
        {
            if (prefixLookup is null)
            {
                return ConvertToStringInternal(null);
            }
            else
            {
                return ConvertToStringInternal(prefixLookup.LookupPrefix);
            }
        }
 
        public static string ToString(IList<XamlTypeName> typeNameList, INamespacePrefixLookup prefixLookup)
        {
            ArgumentNullException.ThrowIfNull(typeNameList);
            ArgumentNullException.ThrowIfNull(prefixLookup);
            return ConvertListToStringInternal(typeNameList, prefixLookup.LookupPrefix);
        }
 
        public static XamlTypeName Parse(string typeName, IXamlNamespaceResolver namespaceResolver)
        {
            ArgumentNullException.ThrowIfNull(typeName);
            ArgumentNullException.ThrowIfNull(namespaceResolver);
 
            string error;
            XamlTypeName result = ParseInternal(typeName, namespaceResolver.GetNamespace, out error);
            if (result is null)
            {
                throw new FormatException(error);
            }
            return result;
        }
 
        public static IList<XamlTypeName> ParseList(string typeNameList, IXamlNamespaceResolver namespaceResolver)
        {
            ArgumentNullException.ThrowIfNull(typeNameList);
            ArgumentNullException.ThrowIfNull(namespaceResolver);
 
            string error;
            IList<XamlTypeName> result = ParseListInternal(typeNameList, namespaceResolver.GetNamespace, out error);
            if (result is null)
            {
                throw new FormatException(error);
            }
            return result;
        }
 
        public static bool TryParse(string typeName, IXamlNamespaceResolver namespaceResolver,
            out XamlTypeName result)
        {
            ArgumentNullException.ThrowIfNull(typeName);
            ArgumentNullException.ThrowIfNull(namespaceResolver);
 
            result = ParseInternal(typeName, namespaceResolver.GetNamespace, out _);
            return (result is not null);
        }
 
        public static bool TryParseList(string typeNameList, IXamlNamespaceResolver namespaceResolver,
            out IList<XamlTypeName> result)
        {
            ArgumentNullException.ThrowIfNull(typeNameList);
            ArgumentNullException.ThrowIfNull(namespaceResolver);
 
            result = ParseListInternal(typeNameList, namespaceResolver.GetNamespace, out _);
            return (result is not null);
        }
 
        internal bool HasTypeArgs
        {
            get
            {
                return _typeArguments is not null && _typeArguments.Count > 0;
            }
        }
 
        internal static string ConvertListToStringInternal(IList<XamlTypeName> typeNameList,
            Func<string, string> prefixGenerator)
        {
            StringBuilder result = new StringBuilder();
            ConvertListToStringInternal(result, typeNameList, prefixGenerator);
            return result.ToString();
        }
 
        internal static void ConvertListToStringInternal(StringBuilder result, IList<XamlTypeName> typeNameList,
            Func<string, string> prefixGenerator)
        {
            bool first = true;
            foreach (XamlTypeName typeName in typeNameList)
            {
                if (!first)
                {
                    result.Append(", ");
                }
                else
                {
                    first = false;
                }
                typeName.ConvertToStringInternal(result, prefixGenerator);
            }
        }
 
        internal static XamlTypeName ParseInternal(string typeName, Func<string, string> prefixResolver, out string error)
        {
            XamlTypeName xamlTypeName = GenericTypeNameParser.ParseIfTrivalName(typeName, prefixResolver, out error);
            if (xamlTypeName is not null)
            {
                return xamlTypeName;
            }
 
            GenericTypeNameParser nameParser = new GenericTypeNameParser(prefixResolver);
            xamlTypeName = nameParser.ParseName(typeName, out error);
            return xamlTypeName;
        }
 
        internal static IList<XamlTypeName> ParseListInternal(string typeNameList,
            Func<string, string> prefixResolver, out string error)
        {
            GenericTypeNameParser nameParser = new GenericTypeNameParser(prefixResolver);
            IList<XamlTypeName> xamlTypeName = nameParser.ParseList(typeNameList, out error);
            return xamlTypeName;
        }
 
        internal string ConvertToStringInternal(Func<string, string> prefixGenerator)
        {
            StringBuilder result = new StringBuilder();
            ConvertToStringInternal(result, prefixGenerator);
            return result.ToString();
        }
 
        internal void ConvertToStringInternal(StringBuilder result, Func<string, string> prefixGenerator)
        {
            if (Namespace is null)
            {
                throw new InvalidOperationException(SR.XamlTypeNameNamespaceIsNull);
            }
            if (string.IsNullOrEmpty(Name))
            {
                throw new InvalidOperationException(SR.XamlTypeNameNameIsNullOrEmpty);
            }
            if (prefixGenerator is null)
            {
                result.Append('{');
                result.Append(Namespace);
                result.Append('}');
            }
            else
            {
                string prefix = prefixGenerator.Invoke(Namespace);
                if (prefix is null)
                {
                    throw new InvalidOperationException(SR.Format(SR.XamlTypeNameCannotGetPrefix, Namespace));
                }
                if (prefix.Length != 0)
                {
                    result.Append(prefix);
                    result.Append(':');
                }
            }
            if (HasTypeArgs)
            {
                // The subscript goes after the type args
                string subscript;
                string name = GenericTypeNameScanner.StripSubscript(Name, out subscript);
                result.Append(name);
 
                result.Append('(');
                ConvertListToStringInternal(result, TypeArguments, prefixGenerator);
                result.Append(')');
 
                result.Append(subscript);
            }
            else
            {
                result.Append(Name);
            }
        }
    }
}