Skip to content

[API Proposal]: TypeDescriptor: Add generic overloads to supply Type argument #127569

@franchyd

Description

@franchyd

Background and motivation

All of System.ComponentModel.TypeDescriptor's entry points are currently static and currently lean on either Type or object parameters (e.g., GetConverter(Type), GetEditor(Type, Type), GetAttributes(Type)), which callers often use by passing typeof(<>) and casting return types. But design precedent in .NET has consistently guided development towards generic overloads to improve ergonomics, safety, and analyzability when the type argument is known:

  • IServiceProvider usage is universally guided toward GetService() / GetRequiredService() extension methods rather than the non-generic GetService(Type).
  • ActivatorUtilities.CreateInstance(…) complements the non-generic factory methods for DI-activated construction.
  • Roslyn rule CA2263 – Prefer generic overload when type is known encodes this guidance to reduce boxing/casting and improve clarity. Adding TypeDescriptor generics would align with this rule.

API Proposal

namespace System.ComponentModel
{
    public sealed class TypeDescriptor
    {
        public static TypeDescriptionProvider AddAttributes<T>(params Attribute[] attributes);
        public static TypeDescriptionProvider AddAttributes<T>(T instance, params Attribute[] attributes);
        public static void AddEditorTable<T>(Hashtable table);
        public static void AddProvider<T>(TypeDescriptionProvider provider, T instance);
        public static void AddProvider<T>(TypeDescriptionProvider provider);
        public static void AddProviderTransparent<T>(TypeDescriptionProvider provider, T instance);
        public static void AddProviderTransparent<T>(TypeDescriptionProvider provider);
        public static EventDescriptor CreateEvent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] CT, T>(string name, params Attribute[] attributes);
        public static EventDescriptor CreateEvent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] CT>(EventDescriptor oldEventDescriptor, params Attribute[] attributes);
        public static T? CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
            IServiceProvider? provider,
            Type[]? argTypes,
            object?[]? args);
    }
}

and so on...

API Usage

Usages of some of the APIs such as:

 TypeDescriptor.AddProvider(myProvider, typeof(T));
 T? instance = (T?)TypeDescriptor.CreateInstance(myProvider, typeof(T), [], []);

would become

 TypeDescriptor.AddProvider<T>(myProvider);
 T? instance = TypeDescriptor.CreateInstance<T>(myProvider, [], []);

Alternative Designs

No response

Risks

Generic overload signatures might imply more trim compatibility than actually present.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.ComponentModeluntriagedNew issue has not been triaged by the area owner

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions