2016-07-28 11 views
0

Ich versuche, ein Ereignis/Messaging-System zu erstellen, wo die Abonnenten allgemeine Ereignistypen oder bestimmte Ereignistypen abonnieren können.Wie bekomme ich eine Liste von Wörterbuch-Schlüsselabfragen, wo Werte Listen sind?

Ich habe ein Wörterbuch von Ereignistypen, die Listen von Abonnenten dieser Typen enthalten, und, um die Ereignisse an die Abonnenten zu melden, möchte ich eine Liste aller Abonnements in diesen Listen, wo das Abonnement von einem Typ ist das ist gleich oder kann vom Typ des Ereignisses zugewiesen werden; mit anderen Worten, wenn der Wörterbuchschlüssel dies als Kriterium erfüllt.

Wie bekomme ich eine abgeflachte Liste der Elemente von Listen, die von den Schlüsseln eines Wörterbuchs abgefragt werden (mit linq)?


Mein WIP-Code:

private Dictionary<Type, List<SomeEventDelegate>> subscriptions; 

// ...other code... 

public void Dispatch(SomeEvent someEvent) 
    { 
     // This should get the Key-Value pairs... How do I get a flattened list of all items in the values (which are lists themselves)? 
     List<SomeEventDelegate> subscribers = 
      from subscription in subscriptions 
      where subscription.Key.IsAssignableFrom(someEvent.GetType()) 
      select subscription; 

     //After I have the flattened list, I will dispatch the event to each subscriber here, in a foreach loop. 
    } 
+0

Auf einer Seite zur Kenntnis, ich glaube nicht, dass Sie sollte das überhaupt tun. Sie müssen die Abonnenten nicht so verwalten, das ist in Delegierten und Ereignissen eingebaut. Wenn Sie mehr Kontrolle benötigen, gibt es dafür Rahmen, die es richtig machen. –

+0

@JeffMercado Für meine spezifischen Bedürfnisse müssen die Abonnenten unabhängig von den Ereignisquellenobjekten sein und müssen nur über die Ereignistypen Bescheid wissen, um diese Ereignisse zu abonnieren. (Sie können je nach Ereignistyp einen Verweis auf das auslösende/Quellenobjekt erhalten, aber das ist nicht notwendig oder insgesamt garantiert) --- Ich bin jedoch neu bei C# -Ereignissen und mag kritische Informationen vermissen, die beeinflussen oder vollständig sein können ändere diese Anforderung oder meine Implementierung. Wenn Sie stark vermuten, dass dies der Fall ist, rufen Sie mich bitte im Chat an, um weiter zu diskutieren! Vielen Dank! – XenoRo

Antwort

2

SelectMany die Arbeit machen sollte:

List<SomeEventDelegate> subscribers = 
    subscriptions.Where(kvp => 
     kvp.Key.IsAssignableFrom(someEvent.GetType()) 
    ).SelectMany(kvp => kvp.Value) 
    .ToList(); 

Sie tun es nur mit der verketteten-Methode-Aufruf-Syntax. Sie übergeben es ein Lambda, das eine IEnumerable<T> aus dem Parameter auswählt, und es fügt alle Aufzählungen, die es von jedem Element in der Abfrage erfasst, in eine große flache Abfrage zusammen, die es zurückgibt.

+0

fehlte 'als Liste ' am Ende der Kette, aber anders als das, funktioniert * perfekt *! Vielen Dank Ed! =) – XenoRo

+0

@AlmightyR Hoppla! Ich denke, einfach ToList() sollte es tun, da Value ist IEnumerable '. –

+0

Noch besser! =) --- (Und ja, ich bin sehr neu in der Verwendung von linq ...) – XenoRo

1

Wenn Sie die Abfragesyntax bevorzugen (also nicht die Mühe, welche genaue Methode verwendet wird), warum Sie nicht nur Ihre Abfrage weiter:

List<SomeEventDelegate> subscribers = 
     (from subscription in subscriptions 
     where subscription.Key.IsAssignableFrom(someEvent.GetType()) 
     from subscriber in subscription.Value 
     select subscriber) 
     .ToList(); 
+0

Während dies den Syntax-Stil meines ursprünglichen Codes beibehalten würde, ist es nicht so lesbar wie die Lösung von Ed's Antwort (IMO). Dennoch ist ein +1 für die Alternative verdient. – XenoRo