【问题标题】:Create a IObservableList from a list of IObservable从 IObservable 列表创建 IObservableList
【发布时间】:2019-04-04 09:32:05
【问题描述】:

我正在寻找实现IObservable<IReadOnlyList<T>> IList<IObservable<T>> 的反应式对象。

就是这样,我希望能够写:

var list = new MyReactiveList<int>();
var item = new Subject<int>();
list.Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));
list.Add(item);
item.OnNext(1); // Will print out [1]

【问题讨论】:

    标签: c# system.reactive dynamic-data


    【解决方案1】:

    首先,您在问题中发布的代码无法编译。我已尽我所能修复它:

    var list = new MyReactiveList<int>();
    var item = new Subject<int>();
    list.Subscribe(values => Console.WriteLine($"[{string.Join(", ", values)}]"));
    list.Add(item);
    item.OnNext(1); // Will print out [1]
    

    现在的练习只是实现class MyReactiveList&lt;T&gt; : IObservable&lt;IReadOnlyList&lt;T&gt;&gt;, IList&lt;IObservable&lt;T&gt;&gt;。这很简单,但唯一的问题是以某种方式将可变的List&lt;IObservable&lt;T&gt;&gt; 转换为IObservable&lt;IReadOnlyList&lt;T&gt;&gt;,这样当列表发生变化时,observable 会自行更新。

    这里是:

    public class MyReactiveList<T> : IObservable<IReadOnlyList<T>>, IList<IObservable<T>>
    {
        private List<IObservable<T>> _list = new List<IObservable<T>>();
    
        private Subject<Unit> _update = new Subject<Unit>();
    
        public IDisposable Subscribe(IObserver<IReadOnlyList<T>> observer) =>
            _update
                .Select(_ => _list.CombineLatest().Select(x => new ReadOnlyList<T>(x)))
                .Switch()
                .Subscribe(observer);
    
        public IObservable<T> this[int index]
        {
            get => _list[index];
            set
            {
                _list[index] = value;
                _update.OnNext(Unit.Default);
            }
        }
    
        public int Count => _list.Count;
    
        public bool IsReadOnly => false;
    
        public void Add(IObservable<T> item)
        {
            _list.Add(item);
            _update.OnNext(Unit.Default);
        }
    
        public void Clear()
        {
            _list.Clear();
            _update.OnNext(Unit.Default);
        }
    
        public bool Contains(IObservable<T> item) => _list.Contains(item);
    
        public void CopyTo(IObservable<T>[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }
    
        public IEnumerator<IObservable<T>> GetEnumerator() => _list.GetEnumerator();
    
        public int IndexOf(IObservable<T> item) => _list.IndexOf(item);
    
        public void Insert(int index, IObservable<T> item)
        {
            _list.Insert(index, item);
            _update.OnNext(Unit.Default);
        }
    
        public bool Remove(IObservable<T> item)
        {
            var removed = _list.Remove(item);
            _update.OnNext(Unit.Default);
            return removed;
        }
    
        public void RemoveAt(int index)
        {
            _list.RemoveAt(index);
            _update.OnNext(Unit.Default);
        }
    
        IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
    }
    
    public class ReadOnlyList<T> : IReadOnlyList<T>
    {
        public ReadOnlyList(IEnumerable<T> items) { _list.AddRange(items); }
    
        private List<T> _list = new List<T>();
    
        public T this[int index] => _list[index];
    
        public int Count => _list.Count;
    
        public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
    
        IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
    }
    

    注意:实现自己的 observables 不是一个好主意 - 很容易弄错它们并创建不能很好地处理并发的代码。

    【讨论】:

    • 谢谢,我修复了问题中的列表类型参数。
    • @Orace - 我不喜欢我的代码_list.CombineLatest().Select(x =&gt; new ReadOnlyList&lt;T&gt;(x))。你能解释一下你希望用这些类型实现什么,以便我找到更好的方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2023-03-06
    相关资源
    最近更新 更多