File: System\Reflection\TypeLoading\General\Ecma\EcmaSignatureTypeProviderForToString.cs
Web Access
Project: src\src\libraries\System.Reflection.MetadataLoadContext\src\System.Reflection.MetadataLoadContext.csproj (System.Reflection.MetadataLoadContext)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Immutable;
using System.Reflection.Metadata;
using System.Text;
 
namespace System.Reflection.TypeLoading.Ecma
{
    //
    // This SignatureProvider is used to generate the Type portion of ToString() values for fields, methods, parameters, events
    // and properties.
    //
    // Though this may seem like something that belongs at the format-agnostic layer, it is not acceptable for ToString() to
    // trigger resolving. Thus, ToString() must be built up using only the raw data in the metadata and without creating or
    // resolving Type objects.
    //
    // Compat: Since this a new library, we are choosing not to carry forth the ancient oddities of runtime
    // Reflection's ToString() ("ByRef" instead of "&", "Int32" rather than "System.Int32"), etc.
    //
    internal sealed class EcmaSignatureTypeProviderForToString : ISignatureTypeProvider<string, TypeContext>
    {
        public static readonly EcmaSignatureTypeProviderForToString Instance = new EcmaSignatureTypeProviderForToString();
 
        private EcmaSignatureTypeProviderForToString() { }
 
        public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => handle.ToTypeString(reader);
        public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => handle.ToTypeString(reader);
        public string GetTypeFromSpecification(MetadataReader reader, TypeContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind) => handle.ToTypeString(reader, genericContext);
 
        public string GetSZArrayType(string elementType) => elementType + "[]";
        public string GetArrayType(string elementType, ArrayShape shape) => elementType + Helpers.ComputeArraySuffix(shape.Rank, multiDim: true);
        public string GetByReferenceType(string elementType) => elementType + "&";
        public string GetPointerType(string elementType) => elementType + "*";
 
        public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(genericType);
            sb.Append('[');
            for (int i = 0; i < typeArguments.Length; i++)
            {
                if (i != 0)
                {
                    sb.Append(',');
                }
 
                sb.Append(typeArguments[i]);
            }
            sb.Append(']');
            return sb.ToString();
        }
 
        public string GetGenericTypeParameter(TypeContext genericContext, int index) => genericContext.GetGenericTypeArgumentOrNull(index)?.ToString() ?? ("!" + index);
        public string GetGenericMethodParameter(TypeContext genericContext, int index) => genericContext.GetGenericMethodArgumentOrNull(index)?.ToString() ?? ("!!" + index);
 
        public string GetFunctionPointerType(MethodSignature<string> signature)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(signature.ReturnType);
            sb.Append('(');
            for (int i = 0; i < signature.ParameterTypes.Length; i++)
            {
                if (i != 0)
                {
                    sb.Append(", ");
                }
 
                sb.Append(signature.ParameterTypes[i]);
            }
            sb.Append(')');
            return sb.ToString();
        }
        public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired) => unmodifiedType;
        public string GetPinnedType(string elementType) => elementType;
 
        public string GetPrimitiveType(PrimitiveTypeCode typeCode)
        {
            typeCode.ToCoreType().GetFullName(out ReadOnlySpan<byte> ns, out ReadOnlySpan<byte> name);
            return ns.ToUtf16() + "." + name.ToUtf16();  // This is not safe for types outside of a namespace, but all primitive types are known to be in "System"
        }
    }
}