views:

536

answers:

4

I'm trying to figure out if it is possible to instantiate and invoke a delegate by name, rather than explicitly. I think the code belows explains it fairly well....I want to accept a function name, and then instantiate the delegate based on that. In the example I use a select case, but I want to eliminate that and just use the methodName argument itself.

Respectfully...please avoid the urge to tell me this is insane and I should be taking some entirely different approach to this. :)

    Private Delegate Sub myDelegate()  

    Private Sub myDelegate_Implementation1()
        'Some code
    End Sub
    Private Sub myDelegate_Implementation2()
        'Some code
    End Sub

    Public Sub InvokeMethod(ByVal methodName As String)
        Dim func As myDelegate = Nothing
        '??? HOW TO GET RID OF THIS SELECT CASE BLOCK?:
        Select Case methodName
            Case "myDelegate_Implementation1"
                func = AddressOf myDelegate_Implementation1
            Case "myDelegate_Implementation2"
                func = AddressOf myDelegate_Implementation2
        End Select
        func.Invoke()
    End Sub

Thanks Keith, exactly what I was looking for. (BFree's approach would work as well in most circumstances though).

Here's the working code in VB:

Public Delegate Sub xxxDelegate()

Sub xxxAnImplementation()

End Sub

Sub zzzDoIt(ByVal xxxImplementerName As String)
    Dim theDelegate As xxxDelegate = CType(System.Delegate.CreateDelegate(GetType(xxxDelegate), Me, xxxImplementerName), xxxDelegate)
    theDelegate.Invoke()
End Sub

Private Sub LoadFunctions()
    Dim thisClass As Type = Type.GetType(Me.GetType.BaseType.FullName.ToString)
    For Each method As MethodInfo In thisClass.GetMethods(System.Reflection.BindingFlags.DeclaredOnly)
        If 1 = 1 OrElse method.Name.Substring(0, 3) = "Get" Then
            Me.ddlCodeSamples.Items.Add(method.Name)
        End If
    Next
End Sub
A: 

Why not use a HashTable instead of a Select statement?

jdigital
+5  A: 

I won't fully answer question, because I'm not sure if what you're asking is possible. What IS possible though, through Reflection, is to Invoke a method given the Method name. IE:

    string methodName = "MyMethod";
    MethodInfo method = this.GetType().GetMethod(methodName);
    method.Invoke(this, null);
BFree
+1 and correct, I'll remove mine
ybo
A: 

BFree's answer works;

My answer is just a suggestion;

Why not just pass an address of method to InvokeMethod instead of passing method name in string?

Module Module1
Sub Main()
    InvokeMethod(AddressOf myDelegate_Implementation1)
    InvokeMethod(AddressOf myDelegate_Implementation2)
End Sub

Public Delegate Sub myDelegate()

Private Sub myDelegate_Implementation1()
    Console.WriteLine("myDelegate_Implementation1")
End Sub
Private Sub myDelegate_Implementation2()
    Console.WriteLine("myDelegate_Implementation2")
End Sub

Public Sub InvokeMethod(ByVal func As myDelegate)
    func()
End Sub
End Module
Sung Meister
+1  A: 

If you have a delegate for the method you can also do this:

public delegate void MethodDelegate( ... ) ...

//create the delegate we expect
(MethodDelegate) Delegate.CreateDelegate(
    typeof( MethodDelegate ), this, "methodName", true );

C#, I know, but the similar will work in VB.

Normally I'd go with @BFree's answer, but this works well when working with event driven reflection - I think this will be slightly quicker if calling the result delegate lots of times.

Keith