Skip to content

Commit

Permalink
Add Type.GetMethod overload that takes Name, BindingFlags, and Parame…
Browse files Browse the repository at this point in the history
…ter Types (#44529)

* Add Type.GetMethod overload that takes Name, BindingFlags, and Parameter Types

Adding overloads to GetConstructor and GetMethod that don't take a Binder or parameter modifiers.

Fix #42753
  • Loading branch information
eerhardt authored Nov 11, 2020
1 parent 4a8cddb commit e5eccd8
Show file tree
Hide file tree
Showing 19 changed files with 221 additions and 93 deletions.
39 changes: 39 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@ public ConstructorInfo? TypeInitializer
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
public ConstructorInfo? GetConstructor(Type[] types) => GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);

/// <summary>
/// Searches for a constructor whose parameters match the specified argument types, using the specified binding constraints.
/// </summary>
/// <param name="bindingAttr">
/// A bitwise combination of the enumeration values that specify how the search is conducted.
/// -or-
/// Default to return null.
/// </param>
/// <param name="types">
/// An array of Type objects representing the number, order, and type of the parameters for the constructor to get.
/// -or-
/// An empty array of the type <see cref="Type"/> (that is, Type[] types = Array.Empty{Type}()) to get a constructor that takes no parameters.
/// -or-
/// <see cref="EmptyTypes"/>.
/// </param>
/// <returns>
/// A <see cref="ConstructorInfo"/> object representing the constructor that matches the specified requirements, if found; otherwise, null.
/// </returns>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public ConstructorInfo? GetConstructor(BindingFlags bindingAttr, Type[] types) => GetConstructor(bindingAttr, binder: null, types, modifiers: null);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public ConstructorInfo? GetConstructor(BindingFlags bindingAttr, Binder? binder, Type[] types, ParameterModifier[]? modifiers) => GetConstructor(bindingAttr, binder, CallingConventions.Any, types, modifiers);

Expand Down Expand Up @@ -221,6 +242,24 @@ public ConstructorInfo? TypeInitializer
return GetMethodImpl(name, bindingAttr, null, CallingConventions.Any, null, null);
}

/// <summary>
/// Searches for the specified method whose parameters match the specified argument types, using the specified binding constraints.
/// </summary>
/// <param name="name">The string containing the name of the method to get.</param>
/// <param name="bindingAttr">
/// A bitwise combination of the enumeration values that specify how the search is conducted.
/// -or-
/// Default to return null.
/// </param>
/// <param name="types">
/// An array of <see cref="Type"/> objects representing the number, order, and type of the parameters for the method to get.
/// -or-
/// An empty array of <see cref="Type"/> objects (as provided by the <see cref="EmptyTypes"/> field) to get a method that takes no parameters.
/// </param>
/// <returns>An object representing the method that matches the specified requirements, if found; otherwise, null.</returns>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
public MethodInfo? GetMethod(string name, BindingFlags bindingAttr, Type[] types) => GetMethod(name, bindingAttr, binder: null, types, modifiers: null);

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
public MethodInfo? GetMethod(string name, Type[] types) => GetMethod(name, types, null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ internal static bool IsNonAttributedTypeValidForSerialization(Type type)
else
{
return (type.IsVisible &&
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null) != null);
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>()) != null);
}
}

Expand Down Expand Up @@ -1368,7 +1368,7 @@ private void SetKeyValuePairAdapterFlags(Type type)
{
_isKeyValuePairAdapter = true;
_keyValuePairGenericArguments = type.GetGenericArguments();
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) }, null);
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) });
_getKeyValuePairMethodInfo = type.GetMethod("GetKeyValuePair", Globals.ScanAllMembers)!;
}
}
Expand Down Expand Up @@ -1408,7 +1408,7 @@ internal MethodInfo? GetKeyValuePairMethodInfo
if (!IsISerializable)
return null;

ConstructorInfo? ctor = UnderlyingType.GetConstructor(Globals.ScanAllMembers, null, SerInfoCtorArgs, null);
ConstructorInfo? ctor = UnderlyingType.GetConstructor(Globals.ScanAllMembers, SerInfoCtorArgs);
if (ctor == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.SerializationInfo_ConstructorNotFound, DataContract.GetClrTypeFullName(UnderlyingType))));

Expand All @@ -1425,7 +1425,7 @@ internal MethodInfo? GetKeyValuePairMethodInfo
if (type.IsValueType)
return null;

ConstructorInfo? ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null);
ConstructorInfo? ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>());
if (ctor == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.NonAttributedSerializableTypesMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type))));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ internal Type GetCollectionElementType()
enumeratorType = GetEnumeratorMethod.ReturnType;
}

MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
if (getCurrentMethod == null)
{
if (enumeratorType.IsInterface)
Expand Down Expand Up @@ -1145,7 +1145,7 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
ConstructorInfo? defaultCtor = null;
if (!type.IsValueType)
{
defaultCtor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null);
defaultCtor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>());
if (defaultCtor == null && constructorRequired)
{
// All collection types could be considered read-only collections except collection types that are marked [Serializable].
Expand Down Expand Up @@ -1331,7 +1331,7 @@ private static void GetCollectionMethods(Type type, Type interfaceType, Type[] a

if (addMethodOnInterface)
{
addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public, null, addMethodTypeArray, null);
addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public, addMethodTypeArray);
if (addMethod == null || addMethod.GetParameters()[0].ParameterType != addMethodTypeArray[0])
{
FindCollectionMethodsOnInterface(type, interfaceType, ref addMethod, ref getEnumeratorMethod);
Expand Down Expand Up @@ -1359,12 +1359,12 @@ private static void GetCollectionMethods(Type type, Type interfaceType, Type[] a
else
{
// GetMethod returns Add() method with parameter closest matching T in assignability/inheritance chain
addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, addMethodTypeArray, null);
addMethod = type.GetMethod(Globals.AddMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, addMethodTypeArray);
}

if (getEnumeratorMethod == null)
{
getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
if (getEnumeratorMethod == null || !Globals.TypeOfIEnumerator.IsAssignableFrom(getEnumeratorMethod.ReturnType))
{
Type? ienumerableInterface = interfaceType.GetInterfaces().Where(t => t.FullName!.StartsWith("System.Collections.Generic.IEnumerable")).FirstOrDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ internal MethodInfo? ParseMethod
{
if (!_parseMethodSet)
{
MethodInfo? method = UnderlyingType.GetMethod(Globals.ParseMethodName, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
MethodInfo? method = UnderlyingType.GetMethod(Globals.ParseMethodName, BindingFlags.Public | BindingFlags.Static, new Type[] { typeof(string) });

if (method != null && method.ReturnType == UnderlyingType)
{
Expand Down Expand Up @@ -1979,7 +1979,7 @@ private static void ImportKnownTypeAttributes(Type? type, Dictionary<Type, Type>
if (methodName.Length == 0)
DataContract.ThrowInvalidDataContractException(SR.Format(SR.KnownTypeAttributeEmptyString, DataContract.GetClrTypeFullName(type)), type);

MethodInfo? method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null);
MethodInfo? method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>());
if (method == null)
DataContract.ThrowInvalidDataContractException(SR.Format(SR.KnownTypeAttributeUnknownMethod, methodName, DataContract.GetClrTypeFullName(type)), type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public static PropertyInfo CollectionItemNameProperty

public static ConstructorInfo ExtensionDataObjectCtor => s_extensionDataObjectCtor ??
(s_extensionDataObjectCtor =
typeof(ExtensionDataObject).GetConstructor(Globals.ScanAllMembers, null, Array.Empty<Type>(), null))!;
typeof(ExtensionDataObject).GetConstructor(Globals.ScanAllMembers, Array.Empty<Type>()))!;

public static PropertyInfo ExtensionDataProperty => s_extensionDataProperty ??
(s_extensionDataProperty = typeof(IExtensibleDataObject).GetProperty("ExtensionData")!);
Expand Down Expand Up @@ -167,7 +167,7 @@ public static MethodInfo GetUninitializedObjectMethod
{
if (s_getUninitializedObjectMethod == null)
{
s_getUninitializedObjectMethod = typeof(XmlFormatReaderGenerator).GetMethod("UnsafeGetUninitializedObject", Globals.ScanAllMembers, null, new Type[] { typeof(Type) }, null);
s_getUninitializedObjectMethod = typeof(XmlFormatReaderGenerator).GetMethod("UnsafeGetUninitializedObject", Globals.ScanAllMembers, new Type[] { typeof(Type) });
Debug.Assert(s_getUninitializedObjectMethod != null);
}
return s_getUninitializedObjectMethod;
Expand All @@ -180,7 +180,7 @@ public static MethodInfo IsStartElementMethod0
{
if (s_isStartElementMethod0 == null)
{
s_isStartElementMethod0 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, null, Array.Empty<Type>(), null);
s_isStartElementMethod0 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, Array.Empty<Type>());
Debug.Assert(s_isStartElementMethod0 != null);
}
return s_isStartElementMethod0;
Expand All @@ -192,7 +192,7 @@ public static MethodInfo IsStartElementMethod2
{
if (s_isStartElementMethod2 == null)
{
s_isStartElementMethod2 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
s_isStartElementMethod2 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) });
Debug.Assert(s_isStartElementMethod2 != null);
}
return s_isStartElementMethod2;
Expand Down Expand Up @@ -371,7 +371,7 @@ public static MethodInfo WriteAttributeStringMethod
{
if (s_writeAttributeStringMethod == null)
{
s_writeAttributeStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteAttributeString", Globals.ScanAllMembers, null, new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) }, null);
s_writeAttributeStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteAttributeString", Globals.ScanAllMembers, new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) });
Debug.Assert(s_writeAttributeStringMethod != null);
}
return s_writeAttributeStringMethod;
Expand All @@ -383,7 +383,7 @@ public static MethodInfo WriteEndElementMethod
{
if (s_writeEndElementMethod == null)
{
s_writeEndElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteEndElement", Globals.ScanAllMembers, null, Array.Empty<Type>(), null);
s_writeEndElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteEndElement", Globals.ScanAllMembers, Array.Empty<Type>());
Debug.Assert(s_writeEndElementMethod != null);
}
return s_writeEndElementMethod;
Expand Down Expand Up @@ -431,7 +431,7 @@ public static MethodInfo WriteStartElementMethod
{
if (s_writeStartElementMethod == null)
{
s_writeStartElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
s_writeStartElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) });
Debug.Assert(s_writeStartElementMethod != null);
}
return s_writeStartElementMethod;
Expand All @@ -444,7 +444,7 @@ public static MethodInfo WriteStartElementStringMethod
{
if (s_writeStartElementStringMethod == null)
{
s_writeStartElementStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(string), typeof(string) }, null);
s_writeStartElementStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, new Type[] { typeof(string), typeof(string) });
Debug.Assert(s_writeStartElementStringMethod != null);
}
return s_writeStartElementStringMethod;
Expand All @@ -457,7 +457,7 @@ public static MethodInfo ParseEnumMethod
{
if (s_parseEnumMethod == null)
{
s_parseEnumMethod = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(Type), typeof(string) }, null);
s_parseEnumMethod = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, new Type[] { typeof(Type), typeof(string) });
Debug.Assert(s_parseEnumMethod != null);
}
return s_parseEnumMethod;
Expand All @@ -470,7 +470,7 @@ public static MethodInfo GetJsonMemberNameMethod
{
if (s_getJsonMemberNameMethod == null)
{
s_getJsonMemberNameMethod = typeof(XmlObjectSerializerReadContextComplexJson).GetMethod("GetJsonMemberName", Globals.ScanAllMembers, null, new Type[] { typeof(XmlReaderDelegator) }, null);
s_getJsonMemberNameMethod = typeof(XmlObjectSerializerReadContextComplexJson).GetMethod("GetJsonMemberName", Globals.ScanAllMembers, new Type[] { typeof(XmlReaderDelegator) });
Debug.Assert(s_getJsonMemberNameMethod != null);
}
return s_getJsonMemberNameMethod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ private void ResetExpectedElements(BitFlagsGenerator expectedElements, int index

private void ReadISerializable(ClassDataContract classContract)
{
ConstructorInfo? ctor = classContract.UnderlyingType.GetConstructor(Globals.ScanAllMembers, null, JsonFormatGeneratorStatics.SerInfoCtorArgs, null);
ConstructorInfo? ctor = classContract.UnderlyingType.GetConstructor(Globals.ScanAllMembers, JsonFormatGeneratorStatics.SerInfoCtorArgs);
if (ctor == null)
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.SerializationInfo_ConstructorNotFound, DataContract.GetClrTypeFullName(classContract.UnderlyingType))));
_ilg.LoadAddress(_objectLocal);
Expand Down Expand Up @@ -573,11 +573,11 @@ private void ReadCollection(CollectionDataContract collectionContract)
{
case CollectionKind.GenericDictionary:
type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments());
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null)!;
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>())!;
break;
case CollectionKind.Dictionary:
type = Globals.TypeOfHashtable;
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null)!;
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>())!;
break;
case CollectionKind.Collection:
case CollectionKind.GenericCollection:
Expand Down
Loading

0 comments on commit e5eccd8

Please sign in to comment.