ic3b3rg
ic3b3rg

Reputation: 14927

Using Reflection to Invoke an Extension Method

I've created a MyFunc extension (in Module Extensions) for all the base types as well as generic arrays, ICollection(Of T) and Dictionary(Of String,T):

Function MyFunc(Of T)(a() As T) As String
Function MyFunc(Of T)(collection As ICollection(Of T)) As String
Function MyFunc(Of T)(dict As Dictionary(Of String,T)) As String

In most cases, I use the functions directly (i.e. "Test".MyFunc()) but there are late-bound situations for which I'm working on a generic function:

Function LateBoundMyFunc(val As Object) As String
  Dim t As Type = val.GetType
  If TypeOf val Is Array Then
    t = ????
  ElseIf TypeOf val Is ICollection
    t = ????
  ElseIf Typeof val Is Dictionary(Of String,) <- This fails
    t = ????
  End If
  Return CType(GetType(Extensions).GetMethod("MyFunc",New Type(){t}).Invoke(Nothing,New Object(){val}),String)

It's fairly simple to handle the base types, but what do I put in place of the ???? and how do I test for Dictionary(Of String,T)?

Upvotes: 2

Views: 361

Answers (1)

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59101

First, you cannot get generic methods without looping through all methods and selecting the one you want. See this question:

Get a generic method without using GetMethods

Next, you cannot create and invoke a generic method without seating all generic parameters. You must make LateBoundMyFunc a generic method, or alter it in some way to accept a value for the type of T for Dictionary(Of String, T). Once you have the method selected, you'll have to call CreateGenericMethod on it to seat those parameters. This is just how reflections works. You have to do all the work, and it can't figure out types for you.

The last problem is that any Dictionary(Of String, T) will also be a ICollection. So you need to swap the order of those checks.

Upvotes: 1

Related Questions