Skip to content

Add API to find MethodInfo on instantiated generic type from generic type definition #45771

@eerhardt

Description

@eerhardt

Background and Motivation

Trying to invoke a method on a generic Type through reflection is not easy. The caller needs to find the method on the instantiated type in order to invoke it. Typically finding the method is done through type.GetMethod("foo"), which doesn't have a great performance characteristic.

Making such code trim-compatible is even harder because the ILLinker doesn't know exactly which method you are trying to find, since the Type is dynamic.

For example, trying to dynamically get the Result of a Task<TResult> object today is done with the following code:

object? result;
Type task_type = task.GetType();
if (task_type == typeof(Task))
{
result = System.Array.Empty<object>();
}
else
{
result = task_type.GetMethod("get_Result")?.Invoke(task, System.Array.Empty<object>());
}

Instead, we should have a method on Type that returns the invokable MethodInfo given the MethodInfo on the generic type definition.

Proposed API

namespace System
{
    public class Type
    {
+        /// <summary>
+        /// Searches for the constructed generic member that matches the specified generic member definition.
+        /// </summary>
+        /// <param name="member">
+        /// The <see cref="MemberInfo"/> representing the generic definition of the member.
+        /// </param>
+        /// <returns>An object representing the member on the current constructed generic type that matches the specified generic definition, if found; otherwise, null.</returns>
+        public virtual MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member);
    }
}

Note: The proposed name matches the existing API on MemberInfo bool HasSameMetadataDefinitionAs(MemberInfo other)

Usage Examples

The above example of getting the Result of a Task<TResult> object would then look like the following, which would be trim-compatible.

class Runtime
{
    private static readonly MethodInfo s_getResultMethodInfo = typeof(Task<>).GetMethod("get_Result");

    public void Complete(Task task)
    {
        object? result; 
        Type task_type = task.GetType(); 
        if (task_type == typeof(Task)) 
        { 
            result = System.Array.Empty<object>(); 
        } 
        else 
        { 
            result = task_type.GetMemberWithSameMetadataDefinition(s_getResultMethodInfo)?.Invoke(task, System.Array.Empty<object>()); 
        } 
    }
}

See #45727 (comment) for the original suggestion for this API.

cc @MichalStrehovsky @GrabYourPitchforks @steveharter

Metadata

Metadata

Assignees

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.Reflectionlinkable-frameworkIssues associated with delivering a linker friendly framework

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions