Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Kanamori <AtsushiKan@users.noreply.github.com>2017-08-31 00:08:32 +0300
committerGitHub <noreply@github.com>2017-08-31 00:08:32 +0300
commitab453715f6ec1c8e3533061527a3fbd3eed167d4 (patch)
tree432def6c1f5f49bb3c3cb757c1998edf0551e4ac /src/System.Private.Reflection.Core
parent37c57b983fbdcc89214e1cf1f5d2b634f166eb8c (diff)
Update Type.GetMethods() to be generics friendly. (#4420)
The complete specs and rationale are in the top comment of https://github.com/dotnet/corefx/issues/16567 but the short version is: - New Type.GetMethod() overloads with a "genericParameterCount" parameter. Only considers methods with that number of generic parameters. - New api: Type.MakeGenericMethodParameter(int position) Create a Type representing an unbound generic method parameter (just an index, no constraints or container information.) Without this, GetMethod() isn't very useable for searching for generic methods. - New api: Type.IsSignatureType Indicates whether a Type object was created by MakeGenericMethodParameter() or constructed from one via MakeArrayType, MakeByRefType, etc. Sample usage: class Horror { public void Moo(int x, int[] y) {} public void Moo<T>(T x, T[] y) {} public void Moo<T>(int x, int[] y) {} public void Moo<T,U>(T x, U[] y) {} // <-- We want this one. public void Moo<T,U>(int x, int[] y) {} } Type horror = typeof(Horror); Type theT = Type.MakeGenericMethodParameter(0); Type theU = Type.MakeGenericMethodParameter(1); MethodInfo moo = horror.GetMethod("Moo", genericParameterCount: 2, new Type[] { theT, theU.MakeArrayType() });
Diffstat (limited to 'src/System.Private.Reflection.Core')
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs1
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/EcmaFormat/EcmaFormatMethodCommon.cs10
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs1
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs11
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs1
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs15
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs21
12 files changed, 51 insertions, 19 deletions
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs
index c92b8e729..d8abe89fc 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs
@@ -128,7 +128,7 @@ namespace System.Reflection.Runtime.BindingFlagSupport
for (int i = 0; i < parameterInfos.Length; i++)
{
// a null argument type implies a null arg which is always a perfect match
- if ((object)argumentTypes[i] != null && !parameterInfos[i].ParameterType.Equals(argumentTypes[i]))
+ if ((object)argumentTypes[i] != null && !argumentTypes[i].MatchesParameterTypeExactly(parameterInfos[i]))
return false;
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs
index 849d1fae9..2e5af22b9 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs
@@ -147,6 +147,7 @@ namespace System.Reflection.Runtime.TypeInfos
public sealed override bool IsInstanceOfType(object o) => base.IsInstanceOfType(o);
public sealed override bool IsSerializable => base.IsSerializable;
public sealed override bool IsEquivalentTo(Type other) => base.IsEquivalentTo(other); // Note: If we enable COM type equivalence, this is no longer the correct implementation.
+ public sealed override bool IsSignatureType => base.IsSignatureType;
public sealed override IEnumerable<ConstructorInfo> DeclaredConstructors => base.DeclaredConstructors;
public sealed override IEnumerable<EventInfo> DeclaredEvents => base.DeclaredEvents;
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/EcmaFormat/EcmaFormatMethodCommon.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/EcmaFormat/EcmaFormatMethodCommon.cs
index 8249cc3c7..e44ba9459 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/EcmaFormat/EcmaFormatMethodCommon.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/EcmaFormat/EcmaFormatMethodCommon.cs
@@ -31,13 +31,7 @@ namespace System.Reflection.Runtime.MethodInfos.EcmaFormat
//
internal struct EcmaFormatMethodCommon : IRuntimeMethodCommon<EcmaFormatMethodCommon>, IEquatable<EcmaFormatMethodCommon>
{
- public bool IsGenericMethodDefinition
- {
- get
- {
- return _method.GetGenericParameters().Count > 0;
- }
- }
+ public bool IsGenericMethodDefinition => GenericParameterCount != 0;
public MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant)
{
@@ -77,6 +71,8 @@ namespace System.Reflection.Runtime.MethodInfos.EcmaFormat
}
}
+ public int GenericParameterCount => _method.GetGenericParameters().Count;
+
public RuntimeTypeInfo[] GetGenericTypeParametersWithSpecifiedOwningMethod(RuntimeNamedMethodInfo<EcmaFormatMethodCommon> owningMethod)
{
GenericParameterHandleCollection genericParameters = _method.GetGenericParameters();
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs
index cba285542..df1de5e97 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs
@@ -49,6 +49,7 @@ namespace System.Reflection.Runtime.MethodInfos
MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant);
bool IsGenericMethodDefinition { get; }
+ int GenericParameterCount { get; }
bool HasSameMetadataDefinitionAs(TRuntimeMethodCommon other);
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs
index e44cf627b..ba7d93981 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs
@@ -28,14 +28,7 @@ namespace System.Reflection.Runtime.MethodInfos.NativeFormat
//
internal struct NativeFormatMethodCommon : IRuntimeMethodCommon<NativeFormatMethodCommon>, IEquatable<NativeFormatMethodCommon>
{
- public bool IsGenericMethodDefinition
- {
- get
- {
- Method method = MethodHandle.GetMethod(Reader);
- return method.GenericParameters.GetEnumerator().MoveNext();
- }
- }
+ public bool IsGenericMethodDefinition => GenericParameterCount != 0;
public MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[] methodArguments, MemberInfo exceptionPertainant)
{
@@ -85,6 +78,8 @@ namespace System.Reflection.Runtime.MethodInfos.NativeFormat
}
}
+ public int GenericParameterCount => MethodHandle.GetMethod(Reader).GenericParameters.Count;
+
public RuntimeTypeInfo[] GetGenericTypeParametersWithSpecifiedOwningMethod(RuntimeNamedMethodInfo<NativeFormatMethodCommon> owningMethod)
{
Method method = MethodHandle.GetMethod(Reader);
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs
index cbab726c4..6819af1d7 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs
@@ -76,6 +76,8 @@ namespace System.Reflection.Runtime.MethodInfos
return _genericMethodDefinition.GetHashCode();
}
+ public sealed override int GenericParameterCount => _genericMethodDefinition.GenericParameterCount;
+
public sealed override MethodInfo GetGenericMethodDefinition()
{
return _genericMethodDefinition;
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs
index 1423d21f7..f841945f6 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs
@@ -29,6 +29,7 @@ namespace System.Reflection.Runtime.MethodInfos
public sealed override bool IsConstructedGenericMethod { get { throw NotImplemented.ByDesign; } }
public sealed override bool IsGenericMethod { get { throw NotImplemented.ByDesign; } }
public sealed override bool IsGenericMethodDefinition { get { throw NotImplemented.ByDesign; } }
+ public sealed override int GenericParameterCount { get { throw NotImplemented.ByDesign; } }
public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) { throw NotImplemented.ByDesign; }
public sealed override MethodImplAttributes MethodImplementationFlags { get { throw NotImplemented.ByDesign; } }
public sealed override Module Module { get { throw NotImplemented.ByDesign; } }
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
index c3a3bba32..d285ab069 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
@@ -149,6 +149,8 @@ namespace System.Reflection.Runtime.MethodInfos
return RuntimeGenericArgumentsOrParameters.CloneTypeArray();
}
+ public abstract override int GenericParameterCount { get; }
+
public abstract override MethodInfo GetGenericMethodDefinition();
public sealed override MethodBody GetMethodBody()
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
index d276fa34e..40df076c1 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs
@@ -115,6 +115,8 @@ namespace System.Reflection.Runtime.MethodInfos
}
}
+ public sealed override int GenericParameterCount => _common.GenericParameterCount;
+
public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments)
{
#if ENABLE_REFLECTION_TRACE
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
index b4c30e740..e439b4501 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs
@@ -109,6 +109,8 @@ namespace System.Reflection.Runtime.MethodInfos
}
}
+ public sealed override int GenericParameterCount => 0;
+
public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments)
{
throw new InvalidOperationException(SR.Format(SR.Arg_NotGenericMethodDefinition, this));
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs
index a5b162518..25cc02987 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs
@@ -55,12 +55,23 @@ namespace System.Reflection.Runtime.TypeInfos
protected sealed override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
{
+ return GetMethodImplCommon(name, GenericParameterCountAny, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ protected sealed override MethodInfo GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return GetMethodImplCommon(name, genericParameterCount, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ private MethodInfo GetMethodImplCommon(string name, int genericParameterCount, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
Debug.Assert(name != null);
// GetMethodImpl() is a funnel for two groups of api. We can distinguish by comparing "types" to null.
if (types == null)
{
// Group #1: This group of api accept only a name and BindingFlags. The other parameters are hard-wired by the non-virtual api entrypoints.
+ Debug.Assert(genericParameterCount == GenericParameterCountAny);
Debug.Assert(binder == null);
Debug.Assert(callConvention == CallingConventions.Any);
Debug.Assert(modifiers == null);
@@ -73,6 +84,8 @@ namespace System.Reflection.Runtime.TypeInfos
ListBuilder<MethodInfo> candidates = new ListBuilder<MethodInfo>();
foreach (MethodInfo candidate in queryResult)
{
+ if (genericParameterCount != GenericParameterCountAny && genericParameterCount != candidate.GenericParameterCount)
+ continue;
if (candidate.QualifiesBasedOnParameterCount(bindingAttr, callConvention, types))
candidates.Add(candidate);
}
@@ -186,6 +199,8 @@ namespace System.Reflection.Runtime.TypeInfos
private TypeComponentsCache Cache => _lazyCache ?? (_lazyCache = new TypeComponentsCache(this));
private volatile TypeComponentsCache _lazyCache;
+
+ private const int GenericParameterCountAny = -1;
}
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs
index 9c6270678..3919b5f58 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs
@@ -430,17 +430,33 @@ namespace System.Reflection.Runtime.TypeInfos
// In a pay-for-play world, this can cause needless MissingMetadataExceptions. There is no harm in creating
// the Type object for an inconsistent generic type - no EEType will ever match it so any attempt to "invoke" it
// will throw an exception.
+ bool foundSignatureType = false;
RuntimeTypeInfo[] runtimeTypeArguments = new RuntimeTypeInfo[typeArguments.Length];
for (int i = 0; i < typeArguments.Length; i++)
{
- RuntimeTypeInfo runtimeTypeArgument = typeArguments[i] as RuntimeTypeInfo;
+ RuntimeTypeInfo runtimeTypeArgument = runtimeTypeArguments[i] = typeArguments[i] as RuntimeTypeInfo;
if (runtimeTypeArgument == null)
{
if (typeArguments[i] == null)
throw new ArgumentNullException();
+
+ if (typeArguments[i].IsSignatureType)
+ {
+ foundSignatureType = true;
+ }
else
+ {
throw new PlatformNotSupportedException(SR.PlatformNotSupported_MakeGenericType); // "PlatformNotSupported" because on desktop, passing in a foreign type is allowed and creates a RefEmit.TypeBuilder
+ }
}
+ }
+
+ if (foundSignatureType)
+ return ReflectionAugments.MakeGenericSignatureType(this, typeArguments);
+
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ RuntimeTypeInfo runtimeTypeArgument = runtimeTypeArguments[i];
// Desktop compatibility: Treat generic type definitions as a constructed generic type using the generic parameters as type arguments.
if (runtimeTypeArgument.IsGenericTypeDefinition)
@@ -448,9 +464,8 @@ namespace System.Reflection.Runtime.TypeInfos
if (runtimeTypeArgument.IsByRefLike)
throw new TypeLoadException(SR.CannotUseByRefLikeTypeInInstantiation);
-
- runtimeTypeArguments[i] = runtimeTypeArgument;
}
+
return this.GetConstructedGenericType(runtimeTypeArguments);
}