Add observable read only list implementation

This commit is contained in:
John Gross
2017-10-03 11:44:35 -07:00
parent 4f1a03811a
commit 7ba6fb5a2e
2 changed files with 80 additions and 3 deletions

View File

@@ -30,6 +30,20 @@ namespace Torch
return source as IReadOnlyList<T> ?? new ReadOnlyCollection<T>(source);
}
/// <summary>
/// Returns a read-only wrapped <see cref="IList{T}"/> and proxies its <see cref="INotifyPropertyChanged"/> and <see cref="INotifyCollectionChanged"/> events.
/// </summary>
public static IReadOnlyList<T> AsReadOnlyObservable<T>(this IList<T> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (source is INotifyPropertyChanged && source is INotifyCollectionChanged)
return new ObservableReadOnlyList<T>(source);
throw new InvalidOperationException("The given list is not observable.");
}
/// <summary>
/// Returns a read-only wrapped <see cref="IDictionary{TKey, TValue}"/>
/// </summary>
@@ -40,14 +54,68 @@ namespace Torch
return source as IReadOnlyDictionary<TKey, TValue> ?? new ReadOnlyDictionary<TKey, TValue>(source);
}
/// <summary>
/// Returns a read-only wrapped <see cref="IDictionary{TKey,TValue}"/> and proxies its <see cref="INotifyPropertyChanged"/> and <see cref="INotifyCollectionChanged"/> events.
/// </summary>
public static IReadOnlyDictionary<TKey, TValue> AsReadOnlyObservable<TKey, TValue>(this IDictionary<TKey, TValue> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (source is INotifyPropertyChanged && source is INotifyCollectionChanged)
return new ObservableReadOnlyDictionary<TKey, TValue>(source);
throw new InvalidOperationException("The given dictionary is not observable.");
}
sealed class ObservableReadOnlyDictionary<TKey, TValue> : ViewModel, IReadOnlyDictionary<TKey, TValue>
sealed class ObservableReadOnlyList<T> : ViewModel, IReadOnlyList<T>, IDisposable
{
private IList<T> _list;
public ObservableReadOnlyList(IList<T> list)
{
_list = list;
if (_list is INotifyPropertyChanged p)
p.PropertyChanged += OnPropertyChanged;
if (_list is INotifyCollectionChanged c)
c.CollectionChanged += OnCollectionChanged;
}
public void Dispose()
{
if (_list is INotifyPropertyChanged p)
p.PropertyChanged -= OnPropertyChanged;
if (_list is INotifyCollectionChanged c)
c.CollectionChanged -= OnCollectionChanged;
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChanged(e);
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e.PropertyName);
}
/// <inheritdoc />
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_list).GetEnumerator();
/// <inheritdoc />
public int Count => _list.Count;
/// <inheritdoc />
public T this[int index] => _list[index];
}
sealed class ObservableReadOnlyDictionary<TKey, TValue> : ViewModel, IReadOnlyDictionary<TKey, TValue>, IDisposable
{
private readonly IDictionary<TKey, TValue> _dictionary;
@@ -62,6 +130,15 @@ namespace Torch
c.CollectionChanged += OnCollectionChanged;
}
public void Dispose()
{
if (_dictionary is INotifyPropertyChanged p)
p.PropertyChanged -= OnPropertyChanged;
if (_dictionary is INotifyCollectionChanged c)
c.CollectionChanged -= OnCollectionChanged;
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnCollectionChanged(e);

View File

@@ -34,7 +34,7 @@ namespace Torch.Managers
#pragma warning restore 649
/// <inheritdoc />
public IReadOnlyDictionary<Guid, ITorchPlugin> Plugins => _plugins.AsReadOnly();
public IReadOnlyDictionary<Guid, ITorchPlugin> Plugins => _plugins.AsReadOnlyObservable();
public event Action<IReadOnlyCollection<ITorchPlugin>> PluginsLoaded;