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

Bugfix/forbid null items #706

Merged
merged 2 commits into from
Jul 22, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/DynamicData.Tests/Cache/AutoRefreshFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@ public void AutoRefreshFromObservable()
[Fact]
public void MakeSelectMagicWorkWithObservable()
{
var initialItem = new IntHolder { Value = 1, Description = "Initial Description" };
var initialItem = new IntHolder(1, "Initial Description");

var sourceList = new SourceList<IntHolder>();
sourceList.Add(initialItem);

var descriptionStream = sourceList.Connect().AutoRefresh(intHolder => intHolder!.Description).Transform(intHolder => intHolder!.Description, true).Do(x => { }) // <--- Add break point here to check the overload fixes it
.Bind(out ReadOnlyObservableCollection<string?> resultCollection);
.Bind(out ReadOnlyObservableCollection<string> resultCollection);

using (descriptionStream.Subscribe())
{
Expand All @@ -109,11 +109,17 @@ public void MakeSelectMagicWorkWithObservable()

public class IntHolder : AbstractNotifyPropertyChanged
{
public string? _description_;
public string _description_;

public int _value;

public string? Description
public IntHolder(int value, string description)
{
_value = value;
_description_ = description;
}

public string Description
{
get => _description_;
set => SetAndRaise(ref _description_, value);
Expand Down
1 change: 1 addition & 0 deletions src/DynamicData.Tests/Cache/ObservableChangeSetFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ public void LoadsAndDisposeUsingDisposableAsync()

private void SubscribeAndAssert<TObject, TKey>(IObservable<IChangeSet<TObject, TKey>> observableChangeset, bool expectsError = false, Action<IObservableCache<TObject, TKey>>? checkContentAction = null)
where TKey : notnull
where TObject : notnull
{
Exception? error = null;
bool complete = false;
Expand Down
12 changes: 0 additions & 12 deletions src/DynamicData.Tests/Cache/TransformFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,6 @@ public void SameKeyChanges()
onlyItemInCache.Should().Be(lastTransformed, "Incorrect transform result");
}

[Fact]
public void TransformToNull()
{
using var source = new SourceCache<Person, string>(p => p.Name);
using var results = new ChangeSetAggregator<PersonWithGender?, string>(source.Connect().Transform((Func<Person, PersonWithGender?>)(p => null)));
source.AddOrUpdate(new Person("Adult1", 50));

results.Messages.Count.Should().Be(1, "Should be 1 updates");
results.Data.Count.Should().Be(1, "Should be 1 item in the cache");
results.Data.Items.First().Should().Be(null, "Should be same person");
}

[Fact]
public void Update()
{
Expand Down
13 changes: 0 additions & 13 deletions src/DynamicData.Tests/Cache/TransformFixtureParallel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,6 @@ public void SameKeyChanges()
onlyItemInCache.Should().Be(lastTransformed, "Incorrect transform result");
}

[Fact]
public void TransformToNull()
{
using var source = new SourceCache<Person, string>(p => p.Name);
using var results = new ChangeSetAggregator<PersonWithGender?, string>(source.Connect()
.Transform((Func<Person, PersonWithGender?>)(p => null), new ParallelisationOptions(ParallelType.Parallelise)));
source.AddOrUpdate(new Person("Adult1", 50));

results.Messages.Count.Should().Be(1, "Should be 1 updates");
results.Data.Count.Should().Be(1, "Should be 1 item in the cache");
results.Data.Items.First().Should().Be(null, "Should be same person");
}

[Fact]
public void Update()
{
Expand Down
1 change: 1 addition & 0 deletions src/DynamicData.Tests/List/CreationFixtures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public void Create()
}

private void SubscribeAndAssert<T>(IObservable<IChangeSet<T>> observableChangeset, bool expectsError = false)
where T : notnull
{
Exception? error = null;
bool complete = false;
Expand Down
2 changes: 1 addition & 1 deletion src/DynamicData.Tests/List/SortFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public ListItem(int number)
Number = number;
}

public int CompareTo([AllowNull] ListItem other) => DefaultComparer.Compare(this, other);
public int CompareTo(ListItem? other) => DefaultComparer.Compare(this, other);

}
}
Expand Down
13 changes: 0 additions & 13 deletions src/DynamicData.Tests/List/TransformFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,6 @@ public void SameKeyChanges()
_results.Data.Count.Should().Be(10, "Should result in 10 records");
}

[Fact]
public void TransformToNull()
{
using var source = new SourceList<Person>();
using var results = new ChangeSetAggregator<PersonWithGender?>(source.Connect()
.Transform((Func<Person, PersonWithGender?>)(p => null)));
source.Add(new Person("Adult1", 50));

results.Messages.Count.Should().Be(1, "Should be 1 updates");
results.Data.Count.Should().Be(1, "Should be 1 item in the cache");
results.Data.Items.First().Should().Be(null, "Should be same person");
}

[Fact]
public void Update()
{
Expand Down
2 changes: 2 additions & 0 deletions src/DynamicData/Aggregation/AggregateEnumerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace DynamicData.Aggregation;

internal class AggregateEnumerator<T> : IAggregateChangeSet<T>
where T : notnull
{
private readonly IChangeSet<T> _source;

Expand Down Expand Up @@ -64,6 +65,7 @@ IEnumerator IEnumerable.GetEnumerator()

[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Same name, different generics.")]
internal class AggregateEnumerator<TObject, TKey> : IAggregateChangeSet<TObject>
where TObject : notnull
where TKey : notnull
{
private readonly IChangeSet<TObject, TKey> _source;
Expand Down
4 changes: 4 additions & 0 deletions src/DynamicData/Aggregation/AggregationEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public static class AggregationEx
/// <param name="source">The source.</param>
/// <returns>The aggregated change set.</returns>
public static IObservable<IAggregateChangeSet<TObject>> ForAggregation<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
if (source is null)
Expand All @@ -39,6 +40,7 @@ public static class AggregationEx
/// <param name="source">The source.</param>
/// <returns>The aggregated change set.</returns>
public static IObservable<IAggregateChangeSet<TObject>> ForAggregation<TObject>(this IObservable<IChangeSet<TObject>> source)
where TObject : notnull
{
if (source is null)
{
Expand Down Expand Up @@ -87,6 +89,7 @@ public static IObservable<T> InvalidateWhen<T>(this IObservable<T> source, IObse
/// <param name="removeAction">The remove action.</param>
/// <returns>An observable with the accumulated value.</returns>
internal static IObservable<TResult> Accumulate<TObject, TResult>(this IObservable<IChangeSet<TObject>> source, TResult seed, Func<TObject, TResult> accessor, Func<TResult, TResult, TResult> addAction, Func<TResult, TResult, TResult> removeAction)
where TObject : notnull
{
return source.ForAggregation().Accumulate(seed, accessor, addAction, removeAction);
}
Expand All @@ -105,6 +108,7 @@ public static IObservable<T> InvalidateWhen<T>(this IObservable<T> source, IObse
/// <param name="removeAction">The remove action.</param>
/// <returns>An observable with the accumulated value.</returns>
internal static IObservable<TResult> Accumulate<TObject, TKey, TResult>(this IObservable<IChangeSet<TObject, TKey>> source, TResult seed, Func<TObject, TResult> accessor, Func<TResult, TResult, TResult> addAction, Func<TResult, TResult, TResult> removeAction)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Accumulate(seed, accessor, addAction, removeAction);
Expand Down
20 changes: 20 additions & 0 deletions src/DynamicData/Aggregation/AvgEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, int> valueSelector, int emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -42,6 +43,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, int?> valueSelector, int emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -59,6 +61,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, long> valueSelector, long emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -76,6 +79,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, long?> valueSelector, long emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -93,6 +97,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, double> valueSelector, double emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -110,6 +115,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, double?> valueSelector, double emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -127,6 +133,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<decimal> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, decimal> valueSelector, decimal emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -144,6 +151,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<decimal> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, decimal?> valueSelector, decimal emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -161,6 +169,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<float> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, float> valueSelector, float emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -178,6 +187,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<float> Avg<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source, Func<TObject, float?> valueSelector, float emptyValue = 0)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
Expand All @@ -194,6 +204,7 @@ public static class AvgEx
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, int> valueSelector, int emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -209,6 +220,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, int?> valueSelector, int emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -224,6 +236,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, long> valueSelector, long emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -239,6 +252,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, long?> valueSelector, long emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -254,6 +268,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, double> valueSelector, double emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -269,6 +284,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, double?> valueSelector, double emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -284,6 +300,7 @@ public static IObservable<double> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<decimal> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, decimal> valueSelector, decimal emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -299,6 +316,7 @@ public static IObservable<decimal> Avg<T>(this IObservable<IChangeSet<T>> source
/// An observable of averages.
/// </returns>
public static IObservable<decimal> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, decimal?> valueSelector, decimal emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -314,6 +332,7 @@ public static IObservable<decimal> Avg<T>(this IObservable<IChangeSet<T>> source
/// An observable of averages.
/// </returns>
public static IObservable<float> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, float> valueSelector, float emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand All @@ -329,6 +348,7 @@ public static IObservable<float> Avg<T>(this IObservable<IChangeSet<T>> source,
/// An observable of averages.
/// </returns>
public static IObservable<float> Avg<T>(this IObservable<IChangeSet<T>> source, Func<T, float?> valueSelector, float emptyValue = 0)
where T : notnull
{
return source.ForAggregation().Avg(valueSelector, emptyValue);
}
Expand Down
6 changes: 6 additions & 0 deletions src/DynamicData/Aggregation/CountEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static class CountEx
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<int> Count<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Count();
Expand All @@ -32,6 +33,7 @@ public static class CountEx
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<int> Count<TObject>(this IObservable<IChangeSet<TObject>> source)
where TObject : notnull
{
return source.ForAggregation().Count();
}
Expand Down Expand Up @@ -68,6 +70,7 @@ public static IObservable<int> Count<TObject>(this IObservable<IDistinctChangeSe
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<bool> IsEmpty<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Count().StartWith(0).Select(count => count == 0);
Expand All @@ -81,6 +84,7 @@ public static IObservable<int> Count<TObject>(this IObservable<IDistinctChangeSe
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<bool> IsEmpty<TObject>(this IObservable<IChangeSet<TObject>> source)
where TObject : notnull
{
return source.ForAggregation().Count().StartWith(0).Select(count => count == 0);
}
Expand All @@ -94,6 +98,7 @@ public static IObservable<bool> IsEmpty<TObject>(this IObservable<IChangeSet<TOb
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<bool> IsNotEmpty<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
return source.ForAggregation().Count().StartWith(0).Select(count => count > 0);
Expand All @@ -107,6 +112,7 @@ public static IObservable<bool> IsEmpty<TObject>(this IObservable<IChangeSet<TOb
/// <param name="source">The source.</param>
/// <returns>An observable which emits the count.</returns>
public static IObservable<bool> IsNotEmpty<TObject>(this IObservable<IChangeSet<TObject>> source)
where TObject : notnull
{
return source.ForAggregation().Count().StartWith(0).Select(count => count > 0);
}
Expand Down