2009-03-05 4 views
2

Ich versuche herauszufinden, ob es möglich ist, einen Delegaten anhand des Namens und nicht explizit explizit zu instanziieren und aufzurufen. Ich denke, der Code unten erklärt es ziemlich gut .... Ich möchte einen Funktionsnamen akzeptieren und dann den Delegierten basierend darauf instanziieren. Im Beispiel verwende ich einen Select Case, aber ich möchte das eliminieren und einfach das Argument methodName selbst verwenden.Möglich, einen Delegaten nach Namen zu instanziieren und aufzurufen?

Hochachtungsvoll ... Bitte vermeiden Sie den Drang, mir zu sagen, dass dies verrückt ist, und ich sollte einen ganz anderen Ansatz dazu machen. :)

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 

Dank Keith, genau das, was ich gesucht habe. (BFree Ansatz würde aber in den meisten Fällen auch funktionieren).

Hier ist der Arbeits 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 

Antwort

1

Wenn Sie einen Delegaten für die Methode, die Sie auch dies tun können:

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

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

C#, ich weiß, aber die ähnlich wird in VB arbeiten.

Normalerweise würde ich mit der Antwort von @BFree gehen, aber das funktioniert gut, wenn ich mit ereignisgesteuerter Reflexion arbeite - ich denke, das wird etwas schneller sein, wenn ich den Ergebnisdelegaten viele Male aufrufen werde.

0

Warum nicht eine HashTable verwenden statt einer Select-Anweisung?

5

Ich werde die Frage nicht vollständig beantworten, weil ich nicht sicher bin, ob das, was Sie fragen, möglich ist. Durch Reflection ist es jedoch möglich, eine Methode mit dem Methodennamen aufzurufen. IE:

string methodName = "MyMethod"; 
    MethodInfo method = this.GetType().GetMethod(methodName); 
    method.Invoke(this, null); 
+0

+1 und richtig, ich werde meins entfernen – ybo

0

BFree's answer funktioniert;

Meine Antwort ist nur ein Vorschlag;

Warum nicht einfach eine Adresse der Methode an InvokeMethod übergeben, anstatt den Methodennamen in der Zeichenfolge zu übergeben?

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 
Verwandte Themen