2010-09-18 5 views
6

Ich habe eine Konsole für mein Spiel in XNA erstellt, und ich habe einen Delegierten für, wenn ein Befehl eingegeben wurde. Im Moment gibt der Delegierte einen bool Wert zurück. Ich habe ein Ereignis innerhalb der Console-Klasse deklariert (das false zurückgibt) und dann dieses Ereignis von anderen Klassen abonniert. Die Idee ist, wenn keine der Klassen, die dieses Ereignis abonnieren, Wahr zurückgibt, wird angenommen, dass der Benutzer einen ungültigen Befehl eingegeben hat. Wenn jedoch mindestens eine der abonnierten Klassen true zurückgibt, wird angenommen, dass der Befehl gültig ist.C# „oder“ Ereignis Delegierten Rückkehr Bool

Momentan wird nur eine Klasse für die Rückgabe von true oder false berücksichtigt. Gibt es eine Möglichkeit, die Rückgabewerte aller abonnierenden Klassen und deren Ergebnis zu betrachten?

Danke,

+1

Nizza Q - nur AFAIK eine einfache Zuordnung wird das Ergebnis des letzten Teilnehmers immer wieder zurückkehren. – StuartLC

Antwort

3

ich es herausgefunden, wie ich diese Frage gestellt: P

bool handled = false; 
foreach (Delegate d in CommandProcessed.GetInvocationList()) 
    handled |= (bool) d.DynamicInvoke (gameTime, command.ToString()); 

if (!handled) { } // Command Unrecognized 

Wo CommandProcessed mein Fall ist, dass Klassen zu abonnieren.
Mein Delegat akzeptiert zwei Argumente: Spielzeit und Befehlszeichenfolge.

+0

Yep - Ich musste dieses Problem kürzlich für die verkettete Validierung lösen. Der bitweise oder Operator schließt nicht wie der boolesche oder Operator ab. – arootbeer

6

Von innerhalb der Klasse, die das Ereignis deklariert, können Sie den Aufruf-Liste der Veranstaltung abgerufen werden (ein feldartigen Ereignis vorausgesetzt). Wenn Sie jede einzelne davon aufrufen, können Sie den Rückgabewert jedes Abonnenten für das Ereignis überprüfen.

Zum Beispiel:

public event Func<bool> MyEvent = delegate { return false; }; 

...  

private bool EmitMyEventAndReturnIfAnySubscriberReturnsTrue() 
{ 
    return MyEvent.GetInvocationList() 
        .Cast<Func<bool>>() 
        .Select(method => method()) 
        .ToList() //Warning: Has side-effects 
        .Any(ret => ret); 
} 

In diesem Beispiel wird jeder Teilnehmer der Veranstaltung informiert - kein Kurzschluss auftritt, wenn einer von ihnen bejahend reagiert. Dieses Verhalten kann bei Bedarf leicht geändert werden, indem der Anruf zu ToList() entfernt wird.

Um aber um ehrlich zu sein, ich weiß nicht wirklich wie Ereignisse, die Werte zurückgeben; ihre Semantik ist für Abonnenten nicht offensichtlich. Ich würde das Design wenn irgend möglich ändern.

EDIT: Korrigierte Fehler in Zwingen vollständige Ausführung der Sequenz basiert auf Timwi Kommentar.

+2

Wäre mir nicht eingefallen, LINQ dafür zu verwenden. Gute Antwort. –

+0

Ich schaute auf zwei verschiedene Designs und das war der Reiniger von beiden. Und es ist ziemlich einfach zu verstehen und zu implementieren. Ich bin mit LinQ nicht vertraut, aber ich habe eine alternative Lösung gefunden, wie ich unten beschrieben habe. – Dave

+0

@Dave: Die alternative Lösung, die Sie gepostet haben, hat die gleiche Idee wie meine Antwort - der Trick besteht darin, auf die Aufrufliste zuzugreifen. Groß. – Ani

0

Ich stimme mit dem Problem zu Ereignissen Werte zurückgegeben werden, wie es auch mir scheint aus. Doch eine Alternative ist es, Sie eine neue Klasse CommandEventArgs schaffen könnten:

class CommandEventArgs : EventArgs 
{ 
    public DateTime GameTime {get; set; } 
    public string Command {get; set;} 
    public bool Valid {get; set;} 
} 

dann eine Instanz dieser Methode verwenden, um das Ereignis zu rufen und dann, wenn der Hörer den Befehl haben erkennt es Valid auf true gesetzt. Wenn Valid nach dem Aufruf immer noch falsch ist, wissen Sie, dass der Befehl nicht erkannt wurde. Diese

ist, wie .NET behandelt Ereignisse Tastatur Sie KeyEventArgs.Handled auf true gesetzt weitere Maßnahmen zur Unterdrückung mit dem Ereignis geschehen.