
Reactive Extensions (Kurz Rx) ermöglicht das abonnieren von Events. Die eingehenden Daten (EventArgs) werden dann mittels IObservable als Datenstream weitergereicht (push). Die Assertion und/oder Komposition findet dann mittels LINQ statt. Auch Abhängigkeiten zu anderen Events können definiert werden. Das macht Rx zum umschlagbaren .NET-Feature.
Etwas verwirrender ist dabei, das Rx zwei unterschiedliche Methoden dafür zur Verfügung stellt: FromEvent und FromEventPattern.
FromEvent
Ab dem .NET-Framework 3.5 mit C# 3.0 ist ein neuer Delegat dazugekommen: Der Action-Delegat.
Bei Action handelt es sich somit um ein generisches Delegate. Unter .NET-Entwicklern hat dieses Delegate immer mehr an Beliebtheit gefunden. Denn somit wird das schreiben für Events um einiges erleichtert. Denn das schreiben eigener EventHandler und die Abhängigkeit zum Standard EventHandler entfällt. Soll zudem ein Wert als EventArgs übertragen werden, reicht das Zuweisen des Datentyps mittels Generics.
1: class Program
2: {
3: public static event Action<string> IncomingMessage;
4:
5: public static void InvokeMessage(string message)
6: {
7: Action<string> handler = IncomingMessage;
8: if (handler != null) handler(message);
9: }
10:
11: static void Main(string[] args)
12: {
13: IncomingMessage += OnIncomingMessage;
14:
15: InvokeMessage("Hello World");
16:
17: Console.ReadLine();
18: }
19:
20: static void OnIncomingMessage(string value)
21: {
22: Console.WriteLine(value);
23: }
24: }
Listing 1 – Events mittels Action-Delegate zur Verfügung stellen
Für das Abonnieren von Generischen-Events, also sprich ein Event das mit dem Action-Delegate erzeugt wurde, wird die FromEvent-Methode benötigt. Der Einsatz dessen wird in Listing 2 veranschaulicht:
1: class Program
2: {
3: public static event Action<string> IncomingMessage;
4:
5: public static void InvokeMessage(string message)
6: {
7: Action<string> handler = IncomingMessage;
8: if (handler != null) handler(message);
9: }
10:
11: static void Main(string[] args)
12: {
13: var messageService = Observable.FromEvent<string>(o => IncomingMessage += o, o => IncomingMessage -= o);
14: messageService.Subscribe(eventArgs => Console.WriteLine(eventArgs));
15:
16: InvokeMessage("Hello World");
17:
18: Console.ReadLine();
19: }
20: }
Listing 2 – Abonnieren von Events mittels Rx
Daraufhin kann eine LINQ-Abfrage dem Event gestellt werden:
1: class Program
2: {
3: public static event Action<string> IncomingMessage;
4:
5: public static void InvokeMessage(string message)
6: {
7: Action<string> handler = IncomingMessage;
8: if (handler != null) handler(message);
9: }
10:
11: static void Main(string[] args)
12: {
13: var messageService = Observable.FromEvent<string>(o => IncomingMessage += o, o => IncomingMessage -= o);
14:
15: var query = from message in messageService
16: where message.Contains("Hello")
17: select message;
18:
19: query.Subscribe(eventArgs => Console.WriteLine(eventArgs));
20:
21: InvokeMessage("Hello World");
22:
23: Console.ReadLine();
24: }
25: }
Listing 3 – Mit Rx eine LINQ-Abfrage zu einem Event stellen
FromEventPattern
Ganz anders verhält sich das mit der FromEventPattern-Methode. Diese möchte nur Events, die auch nach dem Microsoft Event-Pattern implementiert wurden. Also sprich mit einem fest definierten EventHandler und EventArgs. So wie es zum Beispiel bei Frontend-Technologien (WinForms,WPF und Silverlight) der Fall ist. Sollte man dennoch dazu die FromEvent-Methode verwenden, bekommt man eine nichts aussagende Exception zur Laufzeit.
Wie diese Methode dann verwendet wird, Zeigt Listing 4.
1: internal class Program
2: {
3: public static event EventHandler<MessageEventArgs> IncomingMessage;
4:
5: public static void InvokeMessage(string message)
6: {
7: EventHandler<MessageEventArgs> handler = IncomingMessage;
8: if (handler != null) handler(null, new MessageEventArgs(message));
9: }
10:
11: private static void Main(string[] args)
12: {
13: var messageService = Observable.FromEventPattern<EventHandler<MessageEventArgs>, MessageEventArgs>(o => IncomingMessage += o, o => IncomingMessage -= o);
14: messageService.Subscribe(result => Console.WriteLine(result.EventArgs.Text));
15:
16: InvokeMessage("Hello World");
17:
18: Console.ReadLine();
19: }
20: }
21:
22: public class MessageEventArgs : EventArgs
23: {
24: public string Text { get; private set; }
25:
26: public MessageEventArgs(string text)
27: {
28: Text = text;
29: }
30: }
Listing 4 – Auf das Event-Pattern aufgebaute Events mittels Rx abonnieren
Fazit
Leider erst etwas verwirrend, wenn gleich zwei unterschiedliche Methoden mit dem selben Sinn angeboten werden. Jedoch gab es während der Beta-Phase von Rx nur die FromEventPattern-Methode und die Community misste die Unterstützung für Action enorm. Wichtig ist auf jeden Fall, sollte eine ArgumentException mit der Fehlerbeschreibung “Error binding to target method.” aufdrehten, dann wird es höchstwahrscheinlich nur an der falschen Methode liegen.
Mein Tipp! Kostenloses Video-Training „Einführung in Reactive Extensions“.
Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitten "kicken" sie ihn.
-e28093-FromEvent-und-FromEventPattern.aspx)