Abmelden von Delegaten, die über das Schlüsselwort ref an die Subskriptionsmethode übergeben wurden?

9

Ich habe folgende Klasse:

%Vor%

Ich habe eine Weile gesucht und es scheint, dass ein mit dem Schlüsselwort ref übergebenes Argument nicht gespeichert werden kann. Der Versuch, das Quellenargument zu einer Liste hinzuzufügen oder einer Feldvariablen zuzuweisen, erlaubt es nicht, einen Verweis auf die ursprüngliche Referenz des Delegaten beizubehalten. also meine Fragen sind:

  • Gibt es eine Möglichkeit, sich von allen Quellen abzumelden, ohne ihre Referenzen erneut zu übergeben?
  • Wenn nicht, wie kann die Klasse geändert werden, um sie zu unterstützen, aber die Subskription trotzdem beibehalten, indem ein Delegierter über eine Methode übergeben wird?
  • Ist es möglich, dies ohne Reflection zu erreichen?
  • Ist es möglich, dies zu erreichen, ohne den Delegaten / das Ereignis in einer Klasse zu verpacken und dann die Klasse als Parameter für das Abonnement zu übergeben?

Danke.

BEARBEITEN: Es scheint, dass ohne das Verwenden eines Wrappers oder einer Reflektion keine Lösung für das gegebene Problem existiert. Meine Absicht war, die Klasse so portabel wie möglich zu machen, ohne Delegierte in Hilfsklassen einzubinden. Danke allen für die Beiträge.

    
user1098567 14.12.2011, 19:58
quelle

6 Antworten

1

Bearbeiten : Ok, das war eine schlechte Idee, also zurück zu den Grundlagen:

Ich empfehle das Erstellen einer Wrapper-Klasse über eine Aktion:

%Vor%

Und Umstrukturierung Ihrer ursprünglichen Klasse, um mit Wrappern zu arbeiten:

%Vor%

Jetzt sollten Sie die gewünschten Ergebnisse erhalten.

    
Tudor 14.12.2011, 20:05
quelle
0
%Vor%     
Wiktor Zychla 14.12.2011 20:06
quelle
0

Ich würde vorschlagen, dass die Subscription-Methode eine Implementierung einer SubscriptionHelper-Klasse zurückgeben sollte, die IDisposable implementiert. Eine einfache Implementierung wäre, dass SubscriptionHelper einen Verweis auf die Subskriptionsliste und eine Kopie des Subskriptionsdelegaten enthält. Die Subskriptionsliste selbst wäre eine List & lt; SubscriptionHelper & gt; und die Dispose-Methode für SubscriptionHelper würde sich selbst aus der Liste entfernen. Beachten Sie, dass jedes Abonnement einen anderen SubscriptionHelper zurückgibt, wenn derselbe Delegat mehrmals abonniert wird. Das Aufrufen von Dispose auf einem SubscriptionHelper bricht das Abonnement ab, für das es zurückgegeben wurde.

Solch ein Ansatz wäre viel sauberer als die Delegate.Combine / Delegate.Remove-Methode, die vom normalen .net-Muster verwendet wird, deren Semantik sehr merkwürdig werden kann, wenn ein Versuch unternommen wird, Delegierte mit mehreren Zielen zu abonnieren und abzubestellen.

    
supercat 14.12.2011 20:25
quelle
0

BEARBEITEN:

Ja, meine schlechten - Delegaten sind unveränderliche Typen, also wird das Hinzufügen einer Methode zu einer Aufrufliste tatsächlich eine neue Delegateninstanz erzeugen.

Was zu einer Antwort nein auf Ihre Frage führt. Um den Delegaten abzubestellen, müssen Sie die Methode Broadcast aus der Aufrufliste des Stellvertreters entfernen. Dies bedeutet, dass ein neuer Delegat erstellt und dem ursprünglichen Feld oder der ursprünglichen Variablen zugewiesen wird. Sie können jedoch nicht auf das Original zugreifen, wenn Sie die Methode Subscribe nicht mehr verwenden. Außerdem kann es andere Kopien des ursprünglichen Feldes / der Original-Variable geben, die Ihre Methode in der Aufrufliste haben. Und es gibt keine Möglichkeit für Sie, alle zu kennen und ihre Werte zu ändern.

Ich würde vorschlagen, eine Schnittstelle zu dem Ereignis für Ihren Zweck zu deklarieren. Dies wird ein ziemlich flexibler Ansatz sein.

%Vor%

Ursprüngliche Antwort

Gibt es einen bestimmten Grund, warum Sie source delegate als ref übergeben? Sie benötigen dies, wenn Sie beispielsweise einen anderen Delegaten von der Methode zurückgeben möchten.

Ansonsten ist der Delegat ein Referenztyp, also können Sie ihn abonnieren, ohne ihn als ref ...

zu übergeben     
AlexD 14.12.2011 20:20
quelle
0

Es ist ziemlich einfach, aber es gibt ein paar Fallstricke. Wenn Sie einen Verweis auf die Quellobjekte speichern, wie in den meisten Beispielen bisher vorgeschlagen, wird das Objekt nicht als Garbage Collection erfasst. Der beste Weg, dies zu vermeiden, ist eine WeakReference, die es dem GC ermöglicht, ordnungsgemäß zu arbeiten.

Alles, was Sie tun müssen, ist:

1) Fügen Sie der Klasse eine Quellenliste hinzu:

%Vor%

2) Fügen Sie die Quelle zur Liste hinzu:

%Vor%

3) Und dann implementieren Sie einfach entsorgen:

%Vor%

Das heißt, es gibt auch die Frage, warum die Aktion als Referenz bestanden werden muss. Im aktuellen Code gibt es dafür keinen Grund. Wie auch immer, es hat keinen Einfluss auf das Problem oder die Lösung.

    
Bruno Brant 14.12.2011 21:25
quelle
0

Vielleicht, statt zu versuchen, einen Verweis auf den Delegaten zu speichern, haben Sie, was Subskribenten ruft, den Verweis auf das Objekt mit dem Delegaten, um Aktionen für das Abonnement und die Abmeldung zu erstellen. Es ist ein zusätzlicher Parameter, aber es ist immer noch einfach.

%Vor%

Und ein Beispiel abonnieren.

%Vor%     
Mike McFarland 10.01.2012 18:38
quelle