Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable the use of default comparer for SortAndBind #879

Merged
merged 3 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do the two IList<T> overloads not have the IComparable<T> requirement upon TObject?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a mistake. Corrected and pushed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'll explain it.

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 IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
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 IObservable<IChangeSet<TObject, TKey>> SortAndBind<TObject, TKey>(
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