ここで私は建物を完成させました。それは私にとってかなりうまくいく。最初の部分は、2つのセットの違いを計算し報告するための汎用クラスです。
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));
これで2組のペアが作成されます。私は現在のセットにのみある観測に加入したいとき
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();
});
にだから今、私はこのような何かを
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));
そして最後に、この、...
_items
.PairwiseSetComparison()
.Merge(i => i.Delete.Select(_ => i))
.Subscribe(i=> /* user clicked Delete on item i */)
これを行うもう1つの方法は、リスト内の各項目のDelete ICommandに、ユーザーが呼び出すときに実際に委任を実行することです。そうすれば、コマンドが呼び出されたときに実際に購読する必要はありません。私は自分のリストにあるアイテムを周囲にはまったく気づかないでおくのが好きです。
'IObservable'だけでなく 'IObservable >'に 'ImmutableList'がある理由を説明できますか? –
Enigmativity
現在のリスト全体を、observableの値ごとにプッシュしていれば、そのアイテムが以前にプッシュされたものから欠けているかどうかを確認するだけです - 知っておくと 'IObservable 'は必要ありませんアイテムが削除されたとき。あなたは説明を助けることができますか? –
Enigmativity
リストの各項目は、Edit、MoveUp、MoveDown、Deleteのようなコマンドを持つビューモデルです。削除すると、あなたを混乱させることになります。ユーザーがリスト内の特定の項目でMoveDownをクリックしたときを知りたい。ユーザーがアイテムを追加したり削除したりすると、リストが頻繁に変更され、現在リストにあるアイテムに関連するイベントだけをリスンしたいと考えています。 – JustinM