-
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
[Discussion] MetadataLoadContext & runtime reflection #27800
Comments
cc @jkotas |
Yes, we know that mapping the reflection-only types back to the regular ones is likely to be common. Adding helper APIs to make the mapping easier sounds reasonable to me. cc @steveharter |
@jkotas I'm not able to find a way to get a RuntimePropertyInfo given a MetadataToken and a Module, not sure why module exposes few Resolve* methods, but a ResolveProperty is missing and ResolveMember for property throws. Is there any specific reason or can we add public MethodBase ResolveProperty(int metadataToken) => ResolveProperty(metadataToken, null, null);
public virtual MethodBase ResolveProperty(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { throw NotImplemented.ByDesign; } in class Module and implement them in RuntimeModule? So far the conversion from reflection-only property to runtime PropertyInfo is the only one not available, if this is available, then this api addition can move forward. |
The mapping via token works only if the runtime assembly and MetadataLoadContext assembly are exactly the same. If they are not exactly the same (e.g. the MetadataLoadContext operates on reference assemblies), the mapping has to be done by name. I think these APIs should transparently handle both cases. The mapping via token for properties then becomes just missing minor performance optimization that can be worked on independently. |
@jkotas you mean something similar to this? Type ToRuntimeType(this RoType type, Module module)
{
if (module != null)
{
return module.ResolveType(type.MetadataToken);
}
// Slow path
return Type.GetType(type.AssemblyQualifiedName, true, false);
}
Field ToRuntimeField(this RoField field, Module module)
{
if (module != null)
{
return module.ResolveField(field.MetadataToken);
}
// Slow path
BindingFlags flags;
if (field.IsPublic)
{
flags = BindingFlags.Public;
}
else
{
flags = BindingFlags.NonPublic;
}
if (field.IsStatic)
{
flags |= BindingFlags.Static;
}
else
{
flags |= BindingFlags.Instance;
}
return Type.GetType(type.AssemblyQualifiedName, true, false).GetField(field.Name, flags);
} |
Yes, something like this. The fast path may need to be more robust - what would guarantee that the type or field is actually from the exact module passed in? |
@jkotas Yes I know, I will try to come up with something for this, we also have another issue, how can we expose this (extension?) method because all the Ro* reflection types are internal, so ATM I don't know where to expose these methods. Maybe we can add a new class that exposes a What do you think about this one? P.S. To make the mapping via runtime token work for properties, we need to look into exposing a |
Going from ROTypes to runtime types can be done in a robust way (the same assembly must already be loaded) but this particular feature appears to be for performance and per discussion with @GrabYourPitchforks this won't meet the bar for 5.0 especially since we are planning to improve runtime reflection performance for key scenarios via #31895. |
Question/Idea
I'm following TypeLoader implementation and I would like to know if there will be a way to quickly get a runtime reflection counterpart (e.g. get a RuntimePropertyInfo from a RoProperty) form the most used (IMHO) reflection types e.g. PropertyInfo, FieldInfo, MethodInfo, TypeInfo.
I poked around a bit and looks like for some types is kind of easy to get the runtime counterpart using
MetadataToken
e.g.Motivation
Reflection is used a lot, and it's known to be a bit slow, so I created a couple of benchmark to compare reflection and typeloader implementation to compare them.
My benchmark are iterating over all types defined in mscorlib doing different level of inspection (only inspecting types, inspecting all properties for each type, all fields and all methods) below you can find the benchmark result
Benchamrk code is here I'm using Linqpad to run it and I'm using
System.Reflection.TypeLoader
from corefx-lab version 0.1.0-preview2-181102-1,The benchmark shows that typeloader is way faster when we start inspecting properties/fields/methods. The downside of typeloader is that we cannot use it's reflection types to e.g. invoke a method or get a field value because typeloader is supposed to be a replacement (or alternative to) Assembly.ReflectionOnlyLoad according to this, but a lot of libraries (I'm thinking about EF Core, MVC just to name few) are doing extensive reflection work on loaded assemblies that can be mostly satisfied by typeloader and after all the discovery is done, they require the full fledged reflection to be able to perform runtime invocation, so the ability to swap e.g. a typeloader's methodInfo to a runtimemethodinfo would be cool and would make it possible to use typeloader for the discovery phase, making it a lot faster and less memory intensive (see the allocated memory for the method discovery above) and then swap to runtime reflection to perform all the runtime work required (method invocation, get/set properties and so on).
I made few quick test and I was able to get a RuntimeField and RuntimeType easilly, I'm having some trouble with RuntimePropertyInfo, I will keep poking around here.
What do you think about this?
The text was updated successfully, but these errors were encountered: