Reactive Extensions (Rx) Explained Presenter: Kevin Grossnicklaus August 5 th, 2011
Agenda Introductions Talk Additional Resources Conclusion
Introductions Kevin Grossnicklaus – ArchitectNow- (2009-Present) President – Washington University - CAIT Program ( ) Instructor – SSE - ( ) Chief Architect Software Development Practice Twitter: blog.architectnow.net blog.architectnow.net Blog: blog.architectnow.netblog.architectnow.net
EXPECTATIONS
Expectations Experience with.NET development – Samples will be in C# 4.0 – VS 2010 will be used Basic familiarity with LINQ and some Async programming Lambda Expressions will be used
INTRODUCTION TO RX
IEnumerable/IEnumerator interface IEnumerable { IEnumerator GetEnumerator(); } interface IEnumerator : IDisposable { bool MoveNext(); T Current { get; } void Reset(); }
Iterating Collections var items = new string[] { “Hello”, “World” }; foreach (var x in items) { //interact with each piece of data } //we can now assume we are done //we must also handle exceptions
IObservable/IObserver interface IObservable { IDisposable Subscribe(IObserver observer); } interface IObserver { void OnNext(T value); void OnError(Exception ex); void OnCompleted(); }
IObservable/IObserver var _data = new string[] { "Hello", "World" }; var _observable = _data.ToObservable(); var _observer = _observable.Subscribe(x => Console.WriteLine(x)); var _observer2 = _observable.Subscribe( x => Console.WriteLine(x), () => Console.WriteLine("Completed")); var _observer3 = _observable.Subscribe( x => Console.WriteLine(x), ex => Console.WriteLine("Exception: " + ex.Message), () => Console.WriteLine("Completed")); _observer2.Dispose();
Getting Rx Installed NuGet – Easiest and quickest Rx Home Page: – Simply add a reference to: – System.Reactive.DLL Available for: – Full Framework (WPF, WinForms, server side ASP.NET, MVC, etc) – Silverlight 3 and 4 – JavaScript – Windows 7 Phone – Xbox/XNA
OBSERVABLE EXTENSIONS
Subjects using System.Reactive.Subjects; var _subject = new Subject (); var _observer = _subject.Subscribe(x => Console.WriteLine(x)); _subject.OnNext("Rx"); _subject.OnNext("will"); _subject.OnNext("save"); _subject.OnNext("me"); _subject.OnNext("some"); _subject.OnNext("headaches"); _subject.OnCompleted(); _observer.Dispose();
Subscribing public static class ObservableExtensions { public static IDisposable Subscribe (this IObservable source); public static IDisposable Subscribe (this IObservable source, Action onNext); public static IDisposable Subscribe (this IObservable source, Action onNext, Action onError); public static IDisposable Subscribe (this IObservable source, Action onNext, Action onCompleted); public static IDisposable Subscribe (this IObservable source, Action onNext, Action onError, Action onCompleted); }
Creation of Observables //simply call OnComplete var empty = Observable.Empty (); //Call OnNext(“Value”) and then call OnComplete var obReturn = Observable.Return("Value"); //Raise no events var never = Observable.Never (); //Call OnException with the specified expection var throws = Observable.Throw (new Exception()); //Specify a delegate to be called when anyone subscribes var createSample = Observable.Create ( observable => { observable.OnNext("a"); observable.OnNext("b"); observable.OnCompleted(); return () => Console.WriteLine("Observer has unsubscribed"); });
Creation of Observables (Cont…) //Create a range of numbers var range = Observable.Range(10, 15); //publish a count from 0 every specified time period var interval = Observable.Interval(TimeSpan.FromMilliseconds(250)); //Never call “Next” but call “Complete” when the long running operation is done var longOperation = Observable.Start( x =>..do something that takes awhile.. ); //Generate a collection much like for (i=5, i<15, i+3) return i.ToString(); var generated = Observable.Generate(5, i => i i.ToString(), i => i + 3); //simply convert an existing collection or array (IEnumerable) to IObservable var converted = MyCollection.ToObservable();
Rx LINQ Operators Where Select First FirstOrDefault Last LastOrDefault Single Count Min Max Sum Where GroupBy Take TakeUntil Skip DistinctUntilChanged Buffer Throttle Sample Delay Until TimeOut..etc…etc…etc…
RX AND.NET EVENTS
The “Old Way” txtSample.TextChanged += new TextChangedEventHandler(txtSample_TextChanged); //txtSample.TextChanged - = new TextChangedEventHandler(txtSample_TextChanged); private string _lastValue = string.Empty; void txtSample_TextChanged(object sender, TextChangedEventArgs e) { var _currentValue = ((TextBox)sender).Text; if (_currentValue.Length > 5 && _currentValue != _lastValue) { _lastValue = _currentValue; lstData.Items.Add(_currentValue); }
The “New Way” var _textChanged = Observable.FromEventPattern (txtSample, "TextChanged").Select(x => ((TextBox)x.Sender).Text); var _longText = _textChanged.Where(x => x.Length > 5).DistinctUntilChanged().Throttle(TimeSpan.FromSeconds(.5)); _longText.ObserveOnDispatcher().Subscribe(x => lstData.Items.Add(x));
ADDITIONAL TOPICS
Additional Topics Threading – Scheduler Async Pattern Attaching/Detaching When should I use Rx?
FINAL THOUGHTS
Additional Resources Rx Homepage – Rx Beginners Guide (Tutorials, Videos, etc) – Great Keynote Overview – programming-blues programming-blues Team Blog – Community Rx Wiki – Channel 9 Videos – RxSandbox – Great Blog Series by Lee Campbell –
Next Steps…