Skip to content

[API Proposal]: Creating new TypeName without reparsing #102263

Open
@adamsitnik

Description

@adamsitnik

Background and motivation

As we have started using the new TypeName APIs all over the place, I've realized that it would be very nice to have the ability to create a new TypeName instance with given AssemblyNameInfo without the need of re-parsing the concatenated input again.

For example, in BinaryFormatter the type and library names are provided separately (#102014 (comment)), I would like to join them without re-parsing the whole thing again.

API Proposal

namespace System.Reflection.Metadata;

public sealed class TypeName
{
    /// <summary>
    /// Returns a <see cref="TypeName" /> object representing a one-dimensional array
    /// of the current type, with a lower bound of zero.
    /// </summary>
    /// <returns>
    public TypeName MakeArrayTypeName();
    
    /// <summary>
    /// Returns a <see cref="TypeName" /> object representing an array of the current type,
    /// with the specified number of dimensions.
    /// </summary>
    /// <param name="rank">The number of dimensions for the array. This number must be more than zero and less than or equal to 32.</param>
    /// <exception cref="ArgumentOutOfRangeException">rank is invalid. For example, 0 or negative.</exception>
    public TypeName MakeArrayTypeName(int rank);
    
    /// <summary>
    /// Returns a <see cref="TypeName" /> object that represents a pointer to the current type.
    /// </summary>
    public TypeName MakePointerTypeName();
    
    /// <summary>
    /// Returns a <see cref="TypeName" /> object that represents a managed reference to the current type.
    /// </summary>
    public TypeName MakeByRefTypeName();
    
    /// <summary>
    /// Creates a new constructed generic type name.
    /// </summary>
    /// <param name="typeArguments">An array of type names to be used as generic arguments of the current simple type name.</param>
    /// <exception cref="InvalidOperationException">The current type name is not simple.</exception>
    public TypeName MakeGenericTypeName(ImmutableArray<TypeName> typeArguments)

    /// <summary>
    /// Returns a <see cref="TypeName" /> object that represents the current type name with provided assembly name.
    /// </summary>
    public TypeName WithAssemblyName(AssemblyNameInfo? assemblyName);

    public static TypeName CreateSimpleTypeName(string fullName, TypeName? declaringType = null, AssemblyNameInfo? assemblyInfo = null);
}

API Usage

TypeName WithoutAssemblyVersion(TypeName typeName) 
    => typeName.WithAssemblyName(
        new AssemblyNameInfo(
            typeName.AssemblyName.Name,
            version: null,
            typeName.AssemblyName.CultureName,
            typeName.AssemblyName.Flags,
            typeName.AssemblyName.PublicKeyOrToken));

Risks

Some users may miss the fact that the API creates a new instance of TypeName rather than mutating the current instance.

Sample implementation with tests and usages in dotnet/runtime available at #103713

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions