The recording of the first ever ReactiveUI virtual conference is available on our YouTube Channel.

ReactiveCompositeCollections

One of the options available in the reactive ecosystem is the ReactiveCompositeCollections project by Brad Phelan which introduces a new ICompositeCollection<T> that works just like you would expect with LINQ. You can use Select, SelectMany, Where just like with IEnumerable<T> or IObservable<T> and the result of all these operators is another ICompositeCollection<T>

The library lives at Reactive Composite Collections (github) and is available from NuGet at Reactive Composite Collections (nuget)

Example

Here's a unit test that models a typical scenario:

  • a filter that a user can update via some UI binding.
  • a set of source data updated at runtime and needs to be combined
  • we wish to create a new dynamic list composed from the filter and the source lists.
public class FilterHolder : ReactiveObject
{
    private Func<int,bool> _Filter;
    public Func<int,bool> Filter { get => _Filter; set => this.RaiseAndSetIfChanged( ref _Filter, value ); }
}


[Fact]
public void DynamicFilterWithRxUIShouldWork()
{
    var sourceList0 = new CompositeSourceList<int>();
    var sourceList1 = new CompositeSourceList<int>();

    var filter = new FilterHolder {Filter = v => v > 5};

    // Using LINQ we can express the intent of the composition
    // and filtering very succinctly and using an API that
    // is consistent with IEnumerable and RX Extensions
    var target =
        from fn in filter.WhenAnyValue( p=>p.Filter )
        from s in new [] {sourceList0,  sourceList1 }.Concat()
        where fn(s)
        select s;

    sourceList0.AddRange( new []{0,1,2,3,4,5,6,7,8,9,10} );

    // Convert to an observable collection for testing purposes
    using (var oc = target.CreateObservableCollection( EqualityComparer<int>.Default ))
    {
        // Set the filter to be everything greater than 5
        oc.Should().Equal( 6, 7, 8, 9, 10 );
        sourceList0.Clear();
        oc.Should().Equal();

        sourceList0.AddRange( new []{0,1} );
        sourceList1.AddRange( new []{9,10} );

        oc.Should().Equal( 9, 10);

        // Set the filter to be everything less than 5
        filter.Filter =  v=>v<5;
        oc.Should().Equal( 0, 1);
    }
}

For more details head on over to Reactive Composite Collections (github)