これは何
UniRx.ReactiveDictionary
からR3
+ObservableCollections.ObservableDictionary
に乗り換えるメモです。
ObservableCollectionsとは
過去にこちらでまとめているので参考にしてください。
R3と連携する方法はこのあたりを参考にして下さい。
ReadOnlyなReactiveなDictionaryが欲しい
UniRx.ReactiveDictionary
の代替としてR3
+ObservableCollections.ObservableDictionary
が使えるのですが、ReadOnly化して公開することができません。(UniRx.IReactiveDictionary
に相当するものが無い)
そのため無理やりですがReadOnlyに変換してみます。
ReadOnlyObservableDictionary
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ObservableCollections;
using R3;
namespace ObservableCollectionsExt
{
public class ReadOnlyObservableDictionary<TKey, TValue>
: IReadOnlyObservableDictionary<TKey, TValue> where TKey : notnull
{
private ObservableDictionary<TKey, TValue> observableDictionary;
public ReadOnlyObservableDictionary(ObservableDictionary<TKey, TValue> observableDictionary)
{
this.observableDictionary = observableDictionary;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => observableDictionary.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int Count => observableDictionary.Count;
public bool ContainsKey(TKey key) => observableDictionary.ContainsKey(key);
public bool TryGetValue(TKey key, out TValue value) => observableDictionary.TryGetValue(key, out value);
public TValue this[TKey key] => observableDictionary[key];
public IEnumerable<TKey> Keys => observableDictionary.Select(x => x.Key);
public IEnumerable<TValue> Values => observableDictionary.Select(x => x.Value);
public Observable<CollectionAddEvent<KeyValuePair<TKey, TValue>>> ObserveAdd()
=> observableDictionary.ObserveAdd();
public Observable<int> ObserveCountChanged(bool notifyCurrentCount = false)
=> observableDictionary.ObserveCountChanged();
public Observable<CollectionRemoveEvent<KeyValuePair<TKey, TValue>>> ObserveRemove()
=> observableDictionary.ObserveRemove();
public Observable<CollectionReplaceEvent<KeyValuePair<TKey, TValue>>> ObserveReplace()
=> observableDictionary.ObserveReplace();
public Observable<Unit> ObserveReset()
=> observableDictionary.ObserveReset();
}
public interface IReadOnlyObservableDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
Observable<CollectionAddEvent<KeyValuePair<TKey, TValue>>> ObserveAdd();
Observable<int> ObserveCountChanged(bool notifyCurrentCount = false);
Observable<CollectionRemoveEvent<KeyValuePair<TKey, TValue>>> ObserveRemove();
Observable<CollectionReplaceEvent<KeyValuePair<TKey, TValue>>> ObserveReplace();
Observable<Unit> ObserveReset();
}
public static class ObservableCollectionsExt
{
public static IReadOnlyObservableDictionary<TKey, TValue> ToReadOnlyObservableDictionary<TKey, TValue>(
this ObservableDictionary<TKey, TValue> observableDictionary)
where TKey : notnull
=> new ReadOnlyObservableDictionary<TKey, TValue>(observableDictionary);
}
}
使い方
using ObservableCollections;
using ObservableCollectionsExt;
using R3;
// オリジナル
var original = new ObservableDictionary<int, string>();
// ReadOnly化
var readOnlyDic = original.ToReadOnlyObservableDictionary();
// オリジナルと同じ様に参照可能
readOnlyDic.ObserveAdd().Subscribe(x=> Console.WriteLine(x));
readOnlyDic.ObserveRemove().Subscribe(x=> Console.WriteLine(x));
readOnlyDic.ObserveReplace().Subscribe(x=> Console.WriteLine(x));
readOnlyDic.ObserveCountChanged().Subscribe(Console.WriteLine);
original[0] = "1";
original[0] = "2";
original[1] = "3";
original[4] = "4";
original.Remove(0);
original.Clear();
original[1] = "aa";
Console.WriteLine(readOnlyDic[1]);
感想
- ReadonlyなObservableDictionaryは欲しいから用意してみた
- ただし変換時にクラスをインスタンス化するためコストあり
- 使うならキャッシュして使い回すようにしましょう