Skip to content

Commit

Permalink
Enable the use of default comparer for SortAndBind (#879)
Browse files Browse the repository at this point in the history
* Enable the use of default comparer for SortAndBind

* Enhance sort and bind comments

* Add restrain to SortAndBind list overloads where no comparer is specified
  • Loading branch information
RolandPheasant committed Mar 20, 2024
1 parent ba58742 commit 27d4011
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1760,9 +1760,21 @@ namespace DynamicData
public static System.IObservable<DynamicData.ISortedChangeSet<TObject, TKey>> Sort<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.IObservable<System.Collections.Generic.IComparer<TObject>> comparerObservable, System.IObservable<System.Reactive.Unit> resorter, DynamicData.SortOptimisations sortOptimisations = 0, int resetThreshold = 100)
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)
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)
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, System.Collections.Generic.IList<TObject> targetList, 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, 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, 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 { }
Expand Down
30 changes: 27 additions & 3 deletions src/DynamicData.Tests/Cache/SortAndBindFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using DynamicData.Binding;
using DynamicData.Tests.Domain;
using FluentAssertions;
using Mono.Cecil;
using Xunit;

namespace DynamicData.Tests.Cache;
Expand All @@ -28,6 +27,19 @@ protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Perso
}
}

// Bind to a list using default comparer
public sealed class SortAndBindToListDefaultComparer : SortAndBindFixture

{
protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Person> List) SetUpTests()
{
var list = new List<Person>(100);
var aggregator = _source.Connect().SortAndBind(list).AsAggregator();

return (aggregator, list);
}
}

// Bind to an observable collection
public sealed class SortAndBindToObservableCollection : SortAndBindFixture

Expand All @@ -36,11 +48,11 @@ protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Perso
{
var list = new ObservableCollection<Person>(new List<Person>(100));
var aggregator = _source.Connect().SortAndBind(list, _comparer).AsAggregator();

return (aggregator, list);
}
}


// Bind to a readonly observable collection
public sealed class SortAndBindToReadOnlyObservableCollection: SortAndBindFixture
{
Expand All @@ -64,6 +76,17 @@ protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Perso
}
}

// Bind to a readonly observable collection - using default comparer
public sealed class SortAndBindToReadOnlyObservableCollectionDefaultComparer : SortAndBindFixture
{
protected override (ChangeSetAggregator<Person, string> Aggregrator, IList<Person> List) SetUpTests()
{
var aggregator = _source.Connect().SortAndBind(out var list).AsAggregator();

return (aggregator, list);
}
}

public sealed class SortAndBindWithResetOptions: IDisposable
{

Expand Down Expand Up @@ -144,7 +167,7 @@ public abstract class SortAndBindFixture : IDisposable
private readonly ChangeSetAggregator<Person, string> _results;
private readonly IList<Person> _boundList;

protected readonly IComparer<Person> _comparer = SortExpressionComparer<Person>.Ascending(p => p.Age).ThenByAscending(p => p.Name);
protected readonly IComparer<Person> _comparer = Person.DefaultComparer;
protected readonly ISourceCache<Person, string> _source = new SourceCache<Person, string>(p => p.Key);


Expand Down Expand Up @@ -531,3 +554,4 @@ public void Dispose()
_results.Dispose();
}
}

9 changes: 8 additions & 1 deletion src/DynamicData.Tests/Domain/Person.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public enum Color
Violet,
}

public class Person : AbstractNotifyPropertyChanged, IEquatable<Person>
public class Person : AbstractNotifyPropertyChanged, IEquatable<Person>, IComparable<Person>
{
private int _age;
private int? _ageNullable;
Expand Down Expand Up @@ -215,4 +215,11 @@ public int GetHashCode(Person obj)
}
}
}

// Implemented for SortAndBindFixture.
public static IComparer<Person> DefaultComparer { get; } = SortExpressionComparer<Person>
.Ascending(p => p.Age)
.ThenByAscending(p => p.Name);

public int CompareTo(Person? other) => DefaultComparer.Compare(this, other);
}
70 changes: 67 additions & 3 deletions src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,39 @@ namespace DynamicData;
public static partial class ObservableCacheEx
{
/// <summary>
/// Bind sorted data to the specified readonly observable collection.
/// Bind sorted data to the specified collection, for an object which implements IComparable<typeparamref name="TObject"></typeparamref>>.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="targetList">The list to bind to.</param>
/// <returns>An observable which will emit change sets.</returns>
public static IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
this IObservable<IChangeSet<TObject, TKey>> source,
IList<TObject> targetList)
where TObject : notnull, IComparable<TObject>
where TKey : notnull =>
source.SortAndBind(targetList, DynamicDataOptions.SortAndBind);

/// <summary>
/// Bind sorted data to the specified collection, for an object which implements IComparable<typeparamref name="TObject"></typeparamref>>.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="targetList">The list to bind to.</param>
/// <param name="options">Bind and sort default options.</param>
/// <returns>An observable which will emit change sets.</returns>
public static IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
this IObservable<IChangeSet<TObject, TKey>> source,
IList<TObject> targetList,
SortAndBindOptions options)
where TObject : notnull, IComparable<TObject>
where TKey : notnull =>
source.SortAndBind(targetList, Comparer<TObject>.Default, options);

/// <summary>
/// Bind sorted data to the specified collection.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
Expand All @@ -27,10 +59,10 @@ public static partial class ObservableCacheEx
IComparer<TObject> comparer)
where TObject : notnull
where TKey : notnull =>
new SortAndBind<TObject, TKey>(source, comparer, DynamicDataOptions.SortAndBind, targetList).Run();
source.SortAndBind(targetList, comparer, DynamicDataOptions.SortAndBind);

/// <summary>
/// Bind sorted data to the specified readonly observable collection.
/// Bind sorted data to the specified collection.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
Expand All @@ -48,6 +80,38 @@ public static partial class ObservableCacheEx
where TKey : notnull =>
new SortAndBind<TObject, TKey>(source, comparer, options, targetList).Run();

/// <summary>
/// Bind sorted data to the specified readonly observable collection for an object which implements IComparable<typeparamref name="TObject"></typeparamref>>.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="readOnlyObservableCollection">The resulting read only observable collection.</param>
/// <returns>An observable which will emit change sets.</returns>
public static IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
this IObservable<IChangeSet<TObject, TKey>> source,
out ReadOnlyObservableCollection<TObject> readOnlyObservableCollection)
where TObject : notnull, IComparable<TObject>
where TKey : notnull =>
source.SortAndBind(out readOnlyObservableCollection, Comparer<TObject>.Default, DynamicDataOptions.SortAndBind);

/// <summary>
/// Bind sorted data to the specified readonly observable collection for an object which implements IComparable<typeparamref name="TObject"></typeparamref>>.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The source.</param>
/// <param name="readOnlyObservableCollection">The resulting read only observable collection.</param>
/// <param name="options">Bind and sort default options.</param>
/// <returns>An observable which will emit change sets.</returns>
public static IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
this IObservable<IChangeSet<TObject, TKey>> source,
out ReadOnlyObservableCollection<TObject> readOnlyObservableCollection,
SortAndBindOptions options)
where TObject : notnull, IComparable<TObject>
where TKey : notnull =>
source.SortAndBind(out readOnlyObservableCollection, Comparer<TObject>.Default, options);

/// <summary>
/// Bind sorted data to the specified readonly observable collection.
/// </summary>
Expand Down

0 comments on commit 27d4011

Please sign in to comment.