The Pattern<T>
is an odd kind of message that we can use to create flattened sequences of values sourcing from multiple sources.
As we have already seen in the Combining operators section of
Chapter 3,
Reactive Extension Programming, we can use the Zip
operator to create a single output from multiple sources:
var values2 = Observable.Range(0, 100).Where(x => x % 2 == 0); var values3 = Observable.Range(0, 100).Where(x => x % 3 == 0); var values5 = Observable.Range(0, 100).Where(x => x % 5 == 0); //flatten sourcing sequences into a new sequence //based on the sourcing message index var zip = values2.Zip(values3, values5, (a, b, c) => new { a, b, c }); Console.WriteLine("Zip:"); zip.Subscribe(x => Console.WriteLine(x));
Other than the Zip
operator, the Rx library give us the ability to create Pattern
, a group of messages sourcing from different sequences at the same speed by correlating messages with their index in the sourcing sequence.
Here is an example:
//create a pattern by grouping messages based on their index var pattern = values2.And(values3).And(values5) //then produce a single output .Then((a, b, c) => new { a, b, c }); //creates a sequence from the pattern var then = Observable.When(pattern); Console.WriteLine("Then:"); then.Subscribe(x => Console.WriteLine(x));
The key operators of the preceding example are And
, Then
, and When
. The And
operator creates the pattern from the sourcing sequences. Multiple uses of the And
operator will increase the sourcing sequence's availability, making it later available to the Then
operator. The Then
operator will shape all the sourcing messages into a single message similar to what happens with the selector Action
of the Zip
operator. The difference is that the And
operator produces an output we can store somewhere, flow somehow, or schedule in time, while the selector Action
of the Zip
operator offers less programmability.
At the end of the example, the Observable.When
operator will flatten the pattern into an observable sequence usable as we're now used to. Just to be clear, the Pattern
class is unable to directly interact with the core Rx interfaces.
Another interesting feature is the ability to flatten multiple patterns within the When
operator.
Here is an example:
//multiple patterns var values7 = Observable.Range(0, 100).Where(x => x % 7 == 0); var values9 = Observable.Range(0, 100).Where(x => x % 9 == 0); var values11 = Observable.Range(0, 100).Where(x => x % 11 == 0); var pattern79 = values7.And(values9).And(values11).Then((a, b, c) => new { a, b, c, }); //flatten multiple sourcing pattern into a new sequence var then79 = Observable.When(pattern, pattern79); //the message order will follow the sourcing patterns message index Console.WriteLine("Then79:"); then79.Subscribe(x => Console.WriteLine(x));
As is evident in this last example, although the Zip
operator is very powerful, the implementation based on Pattern
made with the And
/Then
/When
operators may give a higher programmability level and a great flexibility to use in our applications.
3.135.206.254