1

I need to know how to find an extension method of a given Type, given a method name. The usual reflection methods do not work.

For example, the type System.Data.DataTable, when calling GetMembers, does not return AsEnumerable in the results.

To confirm this, I ran:

          Dim Query = From MemberInfo As MemberInfo 
                      In GetType(DataTable).GetMembers 
                      Select MemberName = MemberInfo.Name 
                      Order By MemberName 
          For Each MemberName As String In Query.ToList
            Debug.WriteLine(MemberName)
          Next

Note that System.Data.DataSetExtensions is added as a reference, and there is a "using" (Imports) for System.Data

I am looking for the right code to get the MemberInfo for AsEnumerable.

Also note that I will not know the Type at runtime, I'm just using this as a concrete example, so I can't hard-code the solution for DataTable. I do realize the problem lies elsewhere, is not specific to DataTable methods, but I think by concrete example of a problem / solution I can extrapolate that to work with every Type.

EDIT: MY SOLUTION

Calling Code:

  Public Function GetMember(Type As Type, MemberName As String) As MemberInfo
    Return If(Type.GetMember(MemberName).FirstOrDefault, GetExtensionMethod(Type, MemberName))
  End Function

Library Code:

  ''' <summary>
  ''' 
  ''' </summary>
  ''' <param name="ExtendedType">
  ''' The type that was extended by extension methods
  ''' </param>
  ''' <param name="MethodName"></param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function GetExtensionMethod(ExtendedType As Type, MethodName As String) As MethodInfo
    GetExtensionMethod = GetExtensionMethod(ExtendedType.Assembly, ExtendedType, MethodName)
    If GetExtensionMethod IsNot Nothing Then Exit Function

    For Each Assembly As Assembly In AppDomain.CurrentDomain.GetAssemblies
      GetExtensionMethod = GetExtensionMethod(Assembly, ExtendedType, MethodName)
      If GetExtensionMethod IsNot Nothing Then Exit Function
    Next
  End Function

  ''' <summary>
  ''' 
  ''' </summary>
  ''' <param name="Assembly"></param>
  ''' <param name="ExtendedType">
  ''' The type that was extended by extension methods
  ''' </param>
  ''' <param name="MethodName"></param>
  ''' <returns></returns>
  Public Function GetExtensionMethod(Assembly As Assembly, ExtendedType As Type, MethodName As String) As MethodInfo
    Return GetExtensionMethods(Assembly, ExtendedType).FirstOrDefault(Function(x) x.Name = MethodName)
  End Function

  ''' <summary>
  ''' 
  ''' </summary>
  ''' <param name="Assembly"></param>
  ''' <param name="ExtendedType">
  ''' The type that was extended by extension methods
  ''' </param>
  ''' <returns></returns>
  ''' <remarks>
  ''' Reflection's GetMembers does not return extension methods
  ''' </remarks>
  Public Function GetExtensionMethods(Assembly As Assembly, ExtendedType As Type) As IEnumerable(Of MethodInfo)
    Dim Query = From Type As Type
                In Assembly.GetTypes()
                Where Type.IsSealed AndAlso
                Not Type.IsGenericType AndAlso
                Not Type.IsNested
                From Method As MethodInfo
                In Type.GetMethods(BindingFlags.[Static] Or BindingFlags.[Public] Or BindingFlags.NonPublic)
                Where Method.IsDefined(GetType(ExtensionAttribute), False)
                Where Method.GetParameters()(0).ParameterType = ExtendedType
                Select Method
    Return Query
  End Function
toddmo
  • 20,682
  • 14
  • 97
  • 107

1 Answers1

2

This is because AsEnumerable is an extension method provided by DataTableExtensions class. You need to call it as if it were a plain static method:

Dim T As Type
T = TypeOf DataTableExtensions
Dim M As Reflection.MethodInfo = T.GetMethod("AsEnumerable")
...

I need to be able to discover the MemberInfo...

There is no general way to discover all extension methods without an exhaustive walk of all classes in assemblies that you supply, looking for all accessible static methods, and checking their compatibility with a specific parameter type of the first parameter and an ExtensionAttribute.

This Q&A gives more information on discovering extension methods through reflection: link.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks, but I need code example. Sorry, but I need a general solution that can work with all such situations. I need to be able to discover the `MemberInfo`, because the following code `Invoke`s it. – toddmo Dec 31 '14 at 16:02
  • Thanks for the code example, but how can I discover that `DataTableExtensions` is related to `DataTable`? – toddmo Dec 31 '14 at 16:04
  • The right extension method is going to have as the first argument the `Type` I'm interested in (in this case `DataTable`) as the first parameter, correct? – toddmo Dec 31 '14 at 16:10
  • @toddmo - you can't, there is no real relationship between an extension method and the type that it extends or the class that the extension method is defined on. You can check for the existence of the `ExtensionAttribute` (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.extensionattribute(v=vs.110).aspx) on a class or method and check if the first parameter is the type that you want to find extension methods for. – JulianR Dec 31 '14 at 16:10
  • 2
    @toddmo basically, yes; extension methods are also always static, and will have a particular attribute (`ExtensionAttribute`) added automatically – Marc Gravell Dec 31 '14 at 16:11