這是我最終建立的。它對我來說工作得很好。第一部分是計算和報告兩組之間差異的通用類。
public class SetComparison<T>
{
private Lazy<IImmutableSet<T>> _added;
private Lazy<IImmutableSet<T>> _removed;
private Lazy<IImmutableSet<T>> _intersection;
public SetComparison(IEnumerable<T> previous, IEnumerable<T> current)
{
if (previous == null) throw new ArgumentNullException(nameof(previous));
if (current == null) throw new ArgumentNullException(nameof(current));
Previous = previous.ToImmutableHashSet();
Current = current.ToImmutableHashSet();
_added = new Lazy<IImmutableSet<T>>(() => Current.Except(Previous));
_removed = new Lazy<IImmutableSet<T>>(() => Previous.Except(Current));
_intersection = new Lazy<IImmutableSet<T>>(() => Current.Intersect(Previous));
}
public IImmutableSet<T> Previous { get; }
public IImmutableSet<T> Current { get; }
public IImmutableSet<T> Added => _added.Value;
public IImmutableSet<T> Removed => _removed.Value;
public IImmutableSet<T> Intersection => _intersection.Value;
}
這是一個通用的運營商,如F#成對採取序列,並把它變成一系列重疊的項目配對的。
public static IObservable<TResult> Pairwise<TSource, TResult>(
this IObservable<TSource> source,
Func<TSource, TSource, TResult> resultSelector) =>
source.Scan(
(default(TSource), default(TSource)),
(pair, current) => (pair.Item2, current))
.Skip(1)
.Select(p => resultSelector(p.Item1, p.Item2));
而這現在成對的兩組。
public static IObservable<SetComparison<T>> PairwiseSetComparison<T, TCollection>(this IObservable<TCollection> source) where TCollection : IEnumerable<T> =>
source
.Pairwise((a, b) => new SetComparison<T>(a, b));
public static IObservable<SetComparison<T>> PairwiseSetComparison<T>(this IObservable<ImmutableArray<T>> source) =>
source.Pairwise((a, b) => new SetComparison<T>(a, b));
最後這一點,
public static IObservable<TResult> Merge<TResult, T>(this IObservable<SetComparison<T>> source, Func<T, IObservable<TResult>> result) =>
source
.Publish(s =>
{
var additions = s.SelectMany(i => i.Added);
var removals = s.SelectMany(i => i.Removed);
return
additions
.Select(add => result(add).TakeUntil(removals.Where(rem => rem.Equals(add))))
.Merge();
});
所以現在當我想訂閱了僅在當前設置,我做這樣的事情觀測...
_items
.PairwiseSetComparison()
.Merge(i => i.Delete.Select(_ => i))
.Subscribe(i=> /* user clicked Delete on item i */)
完成這一切的另一種方法是在用戶調用它時,讓列表中的每個項目上的Delete ICommand實際運行一些委託。這樣,我不必在命令被調用時實際訂閱。儘管如此,我更願意將我的清單中的物品完全不知道他們的周圍環境。
你能解釋一下爲什麼你在'IObservable>'中有'ImmutableList',而不僅僅是'IObservable '? –
Enigmativity
在我看來,如果您要爲整個當前列表推送每個可觀察值的值,那麼您只需要查看該項目是否從以前推送的項目中缺失 - 無需「IObservable Delete」知道該項目被刪除時。你能幫忙解釋一下嗎? –
Enigmativity
列表中的每個項目都是帶有Edit,MoveUp,MoveDown和Delete等命令的視圖模型 - 刪除一個令您感到困惑。我想知道用戶何時點擊列表中任何特定項目的MoveDown。該列表經常隨着用戶添加和刪除項目而發生變化,我只想偵聽與列表中當前項目相關的事件。 – JustinM