-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add API to find MethodInfo on instantiated generic type from generic type definition #45771
Comments
@GrabYourPitchforks @steveharter - any thoughts on this API? We've now hit 2 places where this would be useful while annotating the dotnet/runtime libraries. Would you be opposed to moving this forward? |
This makes sense. A prototype and perf numbers would be a next step. We could tighten the semantics to avoid confusion and ensure it is only applicable to obtain a member on a closed generic from an open generic, and not a closed to another closed, and not to address any sort of polymorphic\virtual method lookup: namespace System
{
public class Type
{
//<summary>Searches for the member that matches the specified generic member definition. This is faster than a name-based lookup.</summary>
+ public virtual MemberInfo? GetMemberFromGenericMemberDefinition(MemberInfo member);
}
} |
Here's another +1 for this method. In System.Linq.Expressions, we are getting the ConstructorInfo for runtime/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs Lines 827 to 828 in 8a52f1e
If we had this method, we could do this safely by statically referring to the |
I spent some time yesterday prototyping this API: I'm not finding a super fast way to look up a member based on an existing member. From what I see [MemoryDiagnoser]
public class GetMemberBenchmark
{
private static Type closedNullableType = typeof(Nullable<int>);
private static MethodInfo openNullableGetValue = typeof(Nullable<>).GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public);
[Benchmark]
public MethodInfo OldWay()
{
return closedNullableType.GetMethod("get_Value", BindingFlags.Instance | BindingFlags.Public)!;
}
[Benchmark]
public MethodInfo NewWay()
{
return (MethodInfo)closedNullableType.GetMemberFromGenericMemberDefinition(openNullableGetValue);
}
}
@steveharter @GrabYourPitchforks - any thoughts on the above? |
Thank you for looking into this! We'll probably see bigger differences when I wonder if we could make it fast enough for your case by just inlining what runtime/src/coreclr/System.Private.CoreLib/src/System/Reflection/MemberInfo.Internal.cs Lines 10 to 26 in 69e114c
We can check whether the token and module of the owning type is the same once, and then just keep comparing tokens in the hot loop - it should remove a bunch of unnecessary work. |
Another instance in System.Linq.Expressions. See : #47803 (comment). Lines 183 to 186 in 8a52f1e
|
@eerhardt Any opinion on also marking this blocking? It feels like we're going to inflict the suppression/dynamicdependency pains on the ecosystem if we don't add the API so this would be really nice to have. |
I was holding off to "make room" for other features that are critical to get into Preview4 (which this missed by now since the snap is tomorrow). If this doesn't come up in review in the next 2 weeks, I can mark it blocking. Would that be OK? It is really borderline for me as there are work-arounds right now (even though they aren't great). |
Yup, I just want to make sure this can make it into 6.0 - this pattern looks common enough that people could hit this and I don't like having to tell customers to do suppressions. Incorrect suppressions can jeopardize the "app works fine after trimming if there's no warnings" experience and it's hard to get suppressions right. I want trimming to be a reliable experience. |
Unless the immediate experience is really poor, I'd hold off on marking it blocking. It's already near the top of the backlog since the backlog is ordered by milestone. But if you think it risks slipping and you're feeling some anxiety, definitely feel free to override and mark it blocking! |
I will make sure it makes 6.0. |
namespace System
{
partial class Type
{
public virtual MemberInfo? GetMemberWithSameMetadataDefinitionAs(MemberInfo member);
}
} |
…type definition Fix dotnet#45771
* Add API to find MethodInfo on instantiated generic type from generic type definition Fix #45771 * Rename to GetMemberWithSameMetadataDefinitionAs * Fix a bug for NestedType * Use new method libraries that were working around not having it * Implement GetMemberWithSameMetadataDefinitionAs in mono * Revert JavaScript Runtime changes. * Support inheritance in GetMemberWithSameMetadataDefinitionAs.
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 aTask<TResult>
object today is done with the following code:runtime/src/libraries/System.Private.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Runtime.cs
Lines 345 to 354 in 7b90eac
Instead, we should have a method on
Type
that returns the invokable MethodInfo given the MethodInfo on the generic type definition.Proposed API
Note: The proposed name matches the existing API on MemberInfo
bool HasSameMetadataDefinitionAs(MemberInfo other)
Usage Examples
The above example of getting the
Result
of aTask<TResult>
object would then look like the following, which would be trim-compatible.See #45727 (comment) for the original suggestion for this API.
cc @MichalStrehovsky @GrabYourPitchforks @steveharter
The text was updated successfully, but these errors were encountered: