2010-09-18 10 views
6

Utworzyłem konsolę do mojej gry w XNA i mam delegata na kiedy wprowadzono polecenie. W tej chwili delegat zwraca wartość bool. Zadeklarowałem zdarzenie wewnątrz klasy Console (która zwraca wartość false), a następnie zasubskrybowałem to wydarzenie z innych klas. Chodzi o to, że jeśli żadna z klas subskrybujących to zdarzenie nie zwróci wartości true, przyjmuje się, że użytkownik wprowadził niepoprawne polecenie. Jeśli jednak co najmniej jedna z subskrybowanych klas zwróci wartość true, to polecenie zostanie uznane za prawidłowe.C# "LUB" wydarzenie deleguje zwrot bool

W tej chwili, tylko jedna klasa jest brana pod uwagę przy zwracaniu wartości true lub false, czy istnieje sposób, w jaki mogę spojrzeć na wartości zwracane wszystkich subskrybujących klas, a następnie LUB ich wynik?

Dzięki,

+1

Przyjemne Q - AFAIK proste zadanie zawsze zwróci wynik tylko ostatniego subskrybenta. – StuartLC

Odpowiedz

3

wyobraziłem go tak jak ja postawione pytanie: P

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

if (!handled) { } // Command Unrecognized 

Gdzie jest moja CommandProcessed zdarzenie klas subskrybować.
Mój uczestnik bierze dwa argumenty: gametime i ciąg poleceń.

+0

Tak - musiałem rozwiązać ten sam problem ostatnio w celu sprawdzenia poprawności łańcuchowej. Bitowy lub operator nie powoduje zwarcia tak jak operator boolowski lub operator. – arootbeer

6

od wewnątrz klasy, który deklaruje zdarzenie można pobrać pw-listę przypadku (zakładając zdarzenie pole podobny). Wywołanie każdego z nich osobno pozwoli ci sprawdzić wartość zwrotu każdego subskrybenta do zdarzenia.

Na przykład:

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); 
} 

W tym przykładzie, każdy abonent zostanie poinformowany o wypadku - nie występuje zwarcie, czy któryś z nich odpowie twierdząco. To zachowanie można łatwo zmienić w razie potrzeby, usuwając wywołanie ToList().

Szczerze mówiąc, nie lubię wydarzeń, które zwracają wartości; ich semantyka nie jest oczywista dla subskrybentów. Chciałbym zmienić projekt, jeśli w ogóle możliwe.

EDYCJA: Poprawiono błąd wymuszający pełne wykonanie sekwencji na podstawie komentarza Timwi.

+2

Nie przyszło mi do głowy, aby użyć LINQ do tego. Niezła odpowiedź. –

+0

Spojrzałem na dwa różne projekty i to było czystsze z nich obu. Jest to dość łatwe do zrozumienia i wdrożenia. Nie znam LinQ, ale znalazłem alternatywne rozwiązanie, tak jak to opisano poniżej. – Dave

+0

@Dave: opublikowane przeze mnie alternatywne rozwiązanie ma ten sam pomysł, co moja odpowiedź - wystarczy uzyskać dostęp do listy inwokacji. Wspaniały. – Ani

0

Zgadzam się z problemem dotyczącym wydarzeń zwracających wartości, ponieważ wydaje mi się, że również mnie. Jednak alternatywa to można utworzyć nową klasę CommandEventArgs:

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

następnie użycie instancji tej metody do wywołania zdarzenia, a następnie, jeśli słuchacz rozpoznaje komendy mieć go ustawić Valid true. Dlatego jeśli po wywołaniu Valid nadal jest fałszywa, oznacza to, że polecenie nie zostało rozpoznane.

ten sposób .NET obsługuje zdarzenia klawiatury ustawione KeyEventArgs.Handled true tłumić wszelkie dalsze działania, aby stać z imprezy.