Reactive Extensions (Rx) – FromEvent und FromEventPattern

by Gregor Biswanger 16. August 2011 05:48

Rx_Logo_small

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.
kick it on dotnet-kicks.de

Kommentare

Powered by BlogEngine.NET 1.4.5.0
Theme by Extensive SEO

Über den Autor

Gregor Biswanger

Microsoft MVP für Client App Dev
XING

Gregor Biswanger (Microsoft MVP für Client App Dev) ist freier Consultant, Trainer, Autor und Speaker.


Seine Schwerpunkte liegen im Bereich der .NET-Architektur, agilen Prozessen und XAML. Er veröffentlichte vor kurzem seine DVD´s mit Video-Trainings zum Thema „Meine erste Windows 8 App“, „Windows Store Apps mit XAML und C#“ und „WPF 4.5 und Silverlight 5“ bei Addison-Wesley von video2brain.


Biswanger ist auch im Auftrag von Intel GmbH als Technologieberater für die Intel Developer Zone aktiv und ist Leader bei der Ingolstädter .NET Developers Group (INdotNET). 

 

Video über mich:
http://www.youtube.com/watch?v=mx_6SiiLxjk


Basta! 2011 Speaker

CLIPer

MCTS
Windows SharePoint Services 3.0 – Application Development (MCTS)