Skip to content

Commit

Permalink
Observable comparers for SortAndBind (#884)
Browse files Browse the repository at this point in the history
* Observable comparers for SortAndBind

* Observable comparers for SortAndBind - test fixture
  • Loading branch information
RolandPheasant authored Mar 24, 2024
1 parent 5114d01 commit 6f45aa3
Show file tree
Hide file tree
Showing 5 changed files with 390 additions and 127 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ dotnet_diagnostic.SA1112.severity = error
dotnet_diagnostic.SA1113.severity = error
dotnet_diagnostic.SA1114.severity = error
dotnet_diagnostic.SA1115.severity = error
dotnet_diagnostic.SA1116.severity = error
dotnet_diagnostic.SA1116.severity = none
dotnet_diagnostic.SA1117.severity = error
dotnet_diagnostic.SA1118.severity = none
dotnet_diagnostic.SA1119.severity = error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1772,18 +1772,30 @@ namespace DynamicData
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Collections.Generic.IList<TObject> targetList, System.Collections.Generic.IComparer<TObject> comparer)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Collections.Generic.IList<TObject> targetList, System.IObservable<System.Collections.Generic.IComparer<TObject>> comparerChanged)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, out System.Collections.ObjectModel.ReadOnlyObservableCollection<TObject> readOnlyObservableCollection, DynamicData.Binding.SortAndBindOptions options)
where TObject : notnull, System.IComparable<TObject>
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, out System.Collections.ObjectModel.ReadOnlyObservableCollection<TObject> readOnlyObservableCollection, System.Collections.Generic.IComparer<TObject> comparer)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, out System.Collections.ObjectModel.ReadOnlyObservableCollection<TObject> readOnlyObservableCollection, System.IObservable<System.Collections.Generic.IComparer<TObject>> comparerChanged)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Collections.Generic.IList<TObject> targetList, System.Collections.Generic.IComparer<TObject> comparer, DynamicData.Binding.SortAndBindOptions options)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Collections.Generic.IList<TObject> targetList, System.IObservable<System.Collections.Generic.IComparer<TObject>> comparerChanged, DynamicData.Binding.SortAndBindOptions options)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, out System.Collections.ObjectModel.ReadOnlyObservableCollection<TObject> readOnlyObservableCollection, System.Collections.Generic.IComparer<TObject> comparer, DynamicData.Binding.SortAndBindOptions options)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, out System.Collections.ObjectModel.ReadOnlyObservableCollection<TObject> readOnlyObservableCollection, System.IObservable<System.Collections.Generic.IComparer<TObject>> comparerChanged, DynamicData.Binding.SortAndBindOptions options)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.ISortedChangeSet<TObject, TKey>> SortBy<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Func<TObject, System.IComparable> expression, DynamicData.Binding.SortDirection sortOrder = 0, DynamicData.SortOptimisations sortOptimisations = 0, int resetThreshold = 100)
where TObject : notnull
where TKey : notnull { }
Expand Down
111 changes: 111 additions & 0 deletions src/DynamicData.Tests/Cache/SortAndBindObservableFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using DynamicData.Binding;
using DynamicData.Tests.Domain;
using FluentAssertions;
using Xunit;

namespace DynamicData.Tests.Cache;


// Bind to a readonly observable collection
public sealed class SortAndBindObservableToReadOnlyObservableCollection : SortAndBindObservableFixture
{
protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Person> List) SetUpTests()
{
var aggregator = Cache.Connect().SortAndBind(out var list, ComparerObservable).AsAggregator();

return (aggregator, list);
}
}

// Bind to a list
public sealed class SortAndBindObservableToList : SortAndBindObservableFixture
{
protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Person> List) SetUpTests()
{
var list = new List<Person>(100);
var aggregator = Cache.Connect().SortAndBind(list, ComparerObservable).AsAggregator();

return (aggregator, list);
}
}

public abstract class SortAndBindObservableFixture : IDisposable
{
protected readonly ISourceCache<Person, string> Cache = new SourceCache<Person, string>(p => p.Name);


private readonly RandomPersonGenerator _generator = new();

private readonly ChangeSetAggregator<Person, string> _results;
private readonly IList<Person> _boundList;
private readonly SortExpressionComparer<Person> _oldestComparer = SortExpressionComparer<Person>.Descending(p => p.Age).ThenByAscending(p => p.Name);
private readonly SortExpressionComparer<Person> _defaultComparer = SortExpressionComparer<Person>.Ascending(p => p.Name).ThenByAscending(p => p.Age);


[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "By Design.")]
protected readonly BehaviorSubject<IComparer<Person>> ComparerObservable;


protected SortAndBindObservableFixture()
{
ComparerObservable = new BehaviorSubject<IComparer<Person>>(_defaultComparer);

// It's ok in this case to call VirtualMemberCallInConstructor

#pragma warning disable CA2214
// ReSharper disable once VirtualMemberCallInConstructor
var args = SetUpTests();
#pragma warning restore CA2214

// bind and sort in one hit

_results = args.Aggregrator;
_boundList = args.List;
}

protected abstract (ChangeSetAggregator<Person, string> Aggregrator, IList<Person> List) SetUpTests();


[Fact]
public void SortInitialBatch()
{
var people = _generator.Take(100).ToArray();
Cache.AddOrUpdate(people);

var defaultOrder = people.OrderBy(p => p, _defaultComparer).ToList();
_boundList.SequenceEqual(defaultOrder).Should().BeTrue();
}


[Fact]
public void ChangeSort()
{
var people = _generator.Take(100).ToArray();
Cache.AddOrUpdate(people);

// change to oldest first sort
ComparerObservable.OnNext(_oldestComparer);

var oldestFirst = people.OrderBy(p => p, _oldestComparer).ToList();
_boundList.SequenceEqual(oldestFirst).Should().BeTrue();

// and back again
ComparerObservable.OnNext(_defaultComparer);

var defaultOrder = people.OrderBy(p => p, _defaultComparer).ToList();
_boundList.SequenceEqual(defaultOrder).Should().BeTrue();
}


public void Dispose()
{
Cache.Dispose();
_results.Dispose();
ComparerObservable.OnCompleted();
}

}
Loading

0 comments on commit 6f45aa3

Please sign in to comment.