LINQ to Events - declarative work with asynchronous interface

    I came across a very interesting extension for LINQ that allows declaratively working with an asynchronous interface ( ). Now the extension exists as part of the Silverlight Toolkit (Rx framework), but will later become part of .NET 4.0 (System.Reactive.dll).

    The idea is to erase the boundaries between IEnumerable and IObservable interfaces (read between Iterator and Observer patterns). Asynchronous events are represented as a sequence of data returned as if by yield return. And this, in turn, allows you to work with this sequence through LINQ in a functional, declarative style.

    For example, you can use LINQ to formulate expressions about dragging controls:

    IObservable> draggingEvent =
        from mouseLeftDownEvent in control.GetMouseLeftDown()
        from mouseMoveEvent in control.GetMouseMove().Until(control.GetMouseLeftUp())
        select mouseMoveEvent;

    The expression reads as follows: for each click on the left mouse button, get each mouse move event until the left mouse button is depressed.

    In this way, from allows you to declaratively describe the sequence of events. Otherwise, it would be necessary to create a state machine and set the flag for clicking on the left mouse button. And in the mouse movement handler, test this flag and change the behavior of the handler depending on it. Using the Rx framework allows you to describe a sequence of events declaratively and not introduce additional variables.

    In a similar way, you can test the GUI where transitions from state to state are not instantaneous, but occur with animation, the end of which must be waited before making access to the control properties.

    Rating rating = new Rating();
    IObservable test =
          .DoAsync(() => TestPanel.Children.Add(rating)) // добавить контрол на панель
          .WaitFor(TestPanel.GetLayoutUpdated()) // подождать пока появится
          .DoAsync(() => rating.Value = 1.0) // установить свойство
                .GetActualValueChanged() // ждать пока не установится
                .SkipWhile(actualValueChangedEvent => // новое значение свойства
                   actualValueChangedEvent.EventArgs.NewValue != rating.Value))
          .Assert(() => rating.GetRatingItems().Last().ActualValue == 1.0); // Assert

    // очистка ресурсов по завершению теста
    test.Subscribe(() => TestPanel.Children.Remove(rating));

    The author of the original post promises to highlight cross-thread interaction using this framework in the near future.

    Areas of use

    • Building a spacecraft for the visual user interface.
    • Coordinate Workflow Events.
    • Coordinate messages with peripherals. Including with the network (web services) and with any asynchronous IO.
    • Work with chains of events.

    Adaptation for WPF

    There seems to be no code branch adapted for WPF yet, but promise to add in .NET 4.0. However, now you can take the raw and dig deeper manually.

    Bindable LINQ

    The development of an idea is the implementation of binding to declaratively described chains of events. When a dependent property changes, the GUI redraws to reflect the change. In Rx this is not now. However, a similar connection with INotifyPropertyChanged is in the following projects (I have not looked at the projects themselves yet):

    Also popular now: