Skip to content

Commit

Permalink
Fixed ambiguous overloads for ObservableCacheEx.ExpireAfter() and `…
Browse files Browse the repository at this point in the history
…ObservableListEx.ExpireAfter()`. (#822)

* Fixed ambiguous overloads for `ObservableCacheEx.ExpireAfter()`.

Also moved `EnsureUniqueKeys()` into proper order.

* Fixed ambiguous overload for `ObservableListEx.ExpireAfter()`.
  • Loading branch information
JakenVeina authored Jun 6, 2024
1 parent 5f4ddd2 commit 903afc8
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public void RandomizedEditsAndExpirations()

using var subscription = source
.ExpireAfter(
timeSelector: static item => item.Lifetime,
interval: null)
timeSelector: static item => item.Lifetime,
pollingInterval: null)
.Subscribe();

PerformRandomizedEdits(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1301,19 +1301,13 @@ namespace DynamicData
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> ExpireAfter<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Func<TObject, System.TimeSpan?> timeSelector)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(this DynamicData.ISourceCache<TObject, TKey> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(this DynamicData.ISourceCache<TObject, TKey> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.TimeSpan? interval = default)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> ExpireAfter<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.Reactive.Concurrency.IScheduler scheduler)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> ExpireAfter<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.TimeSpan? pollingInterval)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(this DynamicData.ISourceCache<TObject, TKey> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.TimeSpan? pollingInterval, System.Reactive.Concurrency.IScheduler? scheduler)
public static System.IObservable<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(this DynamicData.ISourceCache<TObject, TKey> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.TimeSpan? pollingInterval = default, System.Reactive.Concurrency.IScheduler? scheduler = null)
where TObject : notnull
where TKey : notnull { }
public static System.IObservable<DynamicData.IChangeSet<TObject, TKey>> ExpireAfter<TObject, TKey>(this System.IObservable<DynamicData.IChangeSet<TObject, TKey>> source, System.Func<TObject, System.TimeSpan?> timeSelector, System.TimeSpan? pollingInterval, System.Reactive.Concurrency.IScheduler scheduler)
Expand Down Expand Up @@ -2316,8 +2310,6 @@ namespace DynamicData
where T : notnull { }
public static System.IObservable<DynamicData.IChangeSet<T>> Except<T>(this System.IObservable<DynamicData.IChangeSet<T>> source, params System.IObservable<DynamicData.IChangeSet<T>>[] others)
where T : notnull { }
public static System.IObservable<System.Collections.Generic.IEnumerable<T>> ExpireAfter<T>(this DynamicData.ISourceList<T> source, System.Func<T, System.TimeSpan?> timeSelector, System.Reactive.Concurrency.IScheduler? scheduler = null)
where T : notnull { }
public static System.IObservable<System.Collections.Generic.IEnumerable<T>> ExpireAfter<T>(this DynamicData.ISourceList<T> source, System.Func<T, System.TimeSpan?> timeSelector, System.TimeSpan? pollingInterval = default, System.Reactive.Concurrency.IScheduler? scheduler = null)
where T : notnull { }
public static System.IObservable<DynamicData.IChangeSet<T>> Filter<T>(this System.IObservable<DynamicData.IChangeSet<T>> source, System.Func<T, bool> predicate)
Expand Down
4 changes: 2 additions & 2 deletions src/DynamicData.Tests/Cache/ExpireAfterFixture.ForSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ public void SourceIsNull_ThrowsException()
=> FluentActions.Invoking(() => ObservableCacheEx.ExpireAfter(
source: (null as ISourceCache<TestItem, int>)!,
timeSelector: static _ => default,
interval: null))
pollingInterval: null))
.Should().Throw<ArgumentNullException>();

[Fact]
Expand Down Expand Up @@ -620,7 +620,7 @@ public async Task ThreadPoolSchedulerIsUsedWithPolling_ExpirationIsThreadSafe()
public void TimeSelectorIsNull_ThrowsException()
=> FluentActions.Invoking(() => CreateTestSource().ExpireAfter(
timeSelector: null!,
interval: null))
pollingInterval: null))
.Should().Throw<ArgumentNullException>();

[Fact]
Expand Down
86 changes: 18 additions & 68 deletions src/DynamicData/Cache/ObservableCacheEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,22 @@ public static IObservable<IChangeSet<TObject, TKey>> EditDiff<TObject, TKey>(thi
return new EditDiffChangeSetOptional<TObject, TKey>(source, keySelector, equalityComparer).Run();
}

/// <summary>
/// Ensures there are no duplicated keys in the observable changeset.
/// </summary>
/// <param name="source"> The source change set.</param>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <returns>A changeset which guarantees a key is only present at most once in the changeset.</returns>
public static IObservable<IChangeSet<TObject, TKey>> EnsureUniqueKeys<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
source.ThrowArgumentNullExceptionIfNull(nameof(source));

return new UniquenessEnforcer<TObject, TKey>(source).Run();
}

/// <summary>
/// Signal observers to re-evaluate the specified item.
/// </summary>
Expand Down Expand Up @@ -1447,72 +1463,6 @@ public static IObservable<IChangeSet<TObject, TKey>> ExpireAfter<TObject, TKey>(
pollingInterval: pollingInterval,
scheduler: scheduler);

/// <summary>
/// Automatically removes items from the cache after the time specified by
/// the time selector elapses.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The cache.</param>
/// <param name="timeSelector">The time selector. Return null if the item should never be removed.</param>
/// <param name="scheduler">The scheduler to perform the work on.</param>
/// <returns>An observable of enumerable of the key values which has been removed.</returns>
/// <exception cref="ArgumentNullException">source
/// or
/// timeSelector.</exception>
public static IObservable<IEnumerable<KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(
this ISourceCache<TObject, TKey> source,
Func<TObject, TimeSpan?> timeSelector,
IScheduler? scheduler = null)
where TObject : notnull
where TKey : notnull
=> Cache.Internal.ExpireAfter.ForSource<TObject, TKey>.Create(
source: source,
timeSelector: timeSelector,
scheduler: scheduler);

/// <summary>
/// Automatically removes items from the cache after the time specified by
/// the time selector elapses.
/// </summary>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <param name="source">The cache.</param>
/// <param name="timeSelector">The time selector. Return null if the item should never be removed.</param>
/// <param name="interval">A polling interval. Since multiple timer subscriptions can be expensive,
/// it may be worth setting the interval .
/// </param>
/// <returns>An observable of enumerable of the key values which has been removed.</returns>
/// <exception cref="ArgumentNullException">source
/// or
/// timeSelector.</exception>
public static IObservable<IEnumerable<KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(
this ISourceCache<TObject, TKey> source,
Func<TObject, TimeSpan?> timeSelector,
TimeSpan? interval = null)
where TObject : notnull
where TKey : notnull
=> Cache.Internal.ExpireAfter.ForSource<TObject, TKey>.Create(
source: source,
timeSelector: timeSelector,
pollingInterval: interval);

/// <summary>
/// Ensures there are no duplicated keys in the observable changeset.
/// </summary>
/// <param name="source"> The source change set.</param>
/// <typeparam name="TObject">The type of the object.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <returns>A changeset which guarantees a key is only present at most once in the changeset.</returns>
public static IObservable<IChangeSet<TObject, TKey>> EnsureUniqueKeys<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
where TObject : notnull
where TKey : notnull
{
source.ThrowArgumentNullExceptionIfNull(nameof(source));

return new UniquenessEnforcer<TObject, TKey>(source).Run();
}

/// <summary>
/// Automatically removes items from the cache after the time specified by
/// the time selector elapses.
Expand All @@ -1532,8 +1482,8 @@ public static IObservable<IChangeSet<TObject, TKey>> EnsureUniqueKeys<TObject, T
public static IObservable<IEnumerable<KeyValuePair<TKey, TObject>>> ExpireAfter<TObject, TKey>(
this ISourceCache<TObject, TKey> source,
Func<TObject, TimeSpan?> timeSelector,
TimeSpan? pollingInterval,
IScheduler? scheduler)
TimeSpan? pollingInterval = null,
IScheduler? scheduler = null)
where TObject : notnull
where TKey : notnull
=> Cache.Internal.ExpireAfter.ForSource<TObject, TKey>.Create(
Expand Down
19 changes: 0 additions & 19 deletions src/DynamicData/List/ObservableListEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -652,25 +652,6 @@ public static IObservable<IChangeSet<T>> Except<T>(this IObservableList<IObserva
public static IObservable<IChangeSet<T>> Except<T>(this IObservableList<ISourceList<T>> sources)
where T : notnull => sources.Combine(CombineOperator.Except);

/// <summary>
/// Removes items from the cache according to the value specified by the time selector function.
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
/// <param name="source">The source.</param>
/// <param name="timeSelector">Selector returning when to expire the item. Return null for non-expiring item.</param>
/// <param name="scheduler">The scheduler.</param>
/// <returns>An observable which emits the enumerable of items.</returns>
public static IObservable<IEnumerable<T>> ExpireAfter<T>(
this ISourceList<T> source,
Func<T, TimeSpan?> timeSelector,
IScheduler? scheduler = null)
where T : notnull
=> List.Internal.ExpireAfter<T>.Create(
source: source,
timeSelector: timeSelector,
pollingInterval: null,
scheduler: scheduler);

/// <summary>
/// Removes items from the cache according to the value specified by the time selector function.
/// </summary>
Expand Down

0 comments on commit 903afc8

Please sign in to comment.