dotnet / dotnet/runtime

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

Open
#127,569 3 comments 3 reactions 0 assignees View on GitHub
api-suggestion area-System.ComponentModel
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### 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

```csharp

namespace System.ComponentModel
{
public sealed class TypeDescriptor
{
public static TypeDescriptionProvider AddAttributes(params Attribute[] attributes);
public static TypeDescriptionProvider AddAttributes(T instance, params Attribute[] attributes);
public static void AddEditorTable(Hashtable table);
public static void AddProvider(TypeDescriptionProvider provider, T instance);
public static void AddProvider(TypeDescriptionProvider provider);
public static void AddProviderTransparent(TypeDescriptionProvider provider, T instance);
public static void AddProviderTransparent(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:
```csharp
TypeDescriptor.AddProvider(myProvider, typeof(T));
T? instance = (T?)TypeDescriptor.CreateInstance(myProvider, typeof(T), [], []);
```
would become
```csharp
TypeDescriptor.AddProvider(myProvider);
T? instance = TypeDescriptor.CreateInstance(myProvider, [], []);
```

### Alternative Designs

_No response_

### Risks

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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.