2009-06-04 8 views
7

Ich habe festgestellt, dass die Delegate-Klasse eine Target-Eigenschaft hat, die (vermutlich) die Instanz zurückgibt, für die die Delegate-Methode ausgeführt wird. Ich möchte so etwas wie dies zu tun:Wie erstellt man einen Delegaten für eine Instanzmethode mit einem Nullziel?

void PossiblyExecuteDelegate(Action<int> method) 
{ 
    if (method.Target == null) 
    { 
     // delegate instance target is null 
     // do something 
    } 
    else 
    { 
     method(10); 
     // do something else 
    } 
} 

Wenn es nennt, mag ich, wie etwas zu tun ist:

class A 
{ 
    void Method(int a) {} 

    static void Main(string[] args) 
    { 
     A a = null; 
     Action<int> action = a.Method; 
     PossiblyExecuteDelegate(action); 
    } 
} 

Aber ich bekomme ein Argument (Delegierten zu einer Instanz Methode kein null haben kann: ‚Dieses ') wenn ich versuche, den Delegierten zu konstruieren. Was ich machen möchte und wie kann ich das machen?

+0

Warum möchten Sie dies tun? Sie haben Instanzen, die null sind? –

Antwort

15

Ahah! found it!

Sie können eine offene Instanz delegieren erstellen CreateDelegate Überlastung Verwendung eines Delegaten mit dem impliziten ‚dies‘ erste Argument explizit angegeben werden: Es ist möglich, mit Delegate.CreateDelegate

delegate void OpenInstanceDelegate(A instance, int a); 

class A 
{ 
    public void Method(int a) {} 

    static void Main(string[] args) 
    { 
     A a = null; 
     MethodInfo method = typeof(A).GetMethod("Method"); 
     OpenInstanceDelegate action = (OpenInstanceDelegate)Delegate.CreateDelegate(typeof(OpenInstanceDelegate), a, method); 

     PossiblyExecuteDelegate(action); 
    } 
} 
+0

Ja, da ich meine eigene Antwort bearbeitet habe, ist dies mit Reflektion möglich, aber nicht mit standardmäßig kompiliertem .NET-Code. Ist es Ihre Sorge, dass die Menschen Sie als Delegierte nachdenklicher Delegationen passieren werden? –

1

Um dies zu tun, müssten Sie eine static-Methode an PossiblyExecuteDelegate() übergeben. Dies wird Ihnen eine nullTarget geben.

class A 
{ 
    void Method(int a) {} 
    static void Method2(int a) {} 

    static void Main(string[] args) 
    { 
     PossiblyExecuteDelegate(A.Method2); 

     A a = new A(); 

     PossiblyExecuteDelegate(a.Method); 
    } 
} 

Edit: Es ist möglich, einen Delegierten zu einer Instanz-Methode durch Reflexion ohne Ziel zu passieren, aber nicht Standard kompilierten Code.

+0

Ich meine testen, ob die Instanz Methode auf eine Null-Instanz aufgerufen würde, wenn es aufgerufen wurde. Das Problem ist, die Instanz an erster Stelle zu bekommen. Ich erinnere mich, etwas über offene Delegierte gelesen zu haben, aber ich kann jetzt weder verstecken, noch Haare davon finden ... – thecoop

+0

Ich habe die Dokumente wiedergefunden - Sie können einen offenen Instanz-Delegaten mit einer Delegate.CreateDelegate-Überladung erstellen (eine Antwort mit Details gepostet)) – thecoop

+0

@thecoop: Ja, ich hätte darauf hinweisen sollen, dass dies mit Reflektion möglich wäre, aber nicht mit kompilierungszeit-sicherem Code. Antwort bearbeitet. –

0

, genau mit der Überlastung mit der Unterschrift: CreateDelegate (Type, object, MethodInfo)

Wenn Sie „null“ für den zweiten Parameter (Ziel) angeben dann müssen Sie einen zusätzlichen Parameter in den Delegattyp setzen, dass gibt den Instanztyp, und wh Wenn Sie den Delegaten aufrufen, muss die Instanz als erstes Argument übergeben werden, gefolgt von den "echten" Parametern der Methode.

class Test 
{ 
    public int AddStrings(string a, string b) 
    { 
     return int.Parse(a) + int.Parse(b); 
    } 

    static void Main() 
    { 
     var test = new Test(); 
     var methodInfo = test.GetType().GetMethod("AddStrings"); 
     // note the first extra parameter of the Func, is the owner type 
     var delegateType = typeof(Func<Test, string, string, int>); 
     var del = Delegate.CreateDelegate(delegateType, null, methodInfo); 

     var result = (int)del.DynamicInvoke(test, "39", "3"); 
    } 
} 
Verwandte Themen