// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
using System.Collections;
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace System.Reactive
{
// CONSIDER: Deprecate this functionality or invest in an asynchronous variant.
///
/// Represents an object that retains the elements of the observable sequence and signals the end of the sequence.
///
/// The type of elements received from the source sequence.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "By design; Observable suffix takes precedence.")]
[Experimental]
public class ListObservable : IList, IObservable
{
private readonly IDisposable subscription;
private readonly AsyncSubject subject = new AsyncSubject();
private readonly List results = new List();
///
/// Constructs an object that retains the values of source and signals the end of the sequence.
///
/// The observable sequence whose elements will be retained in the list.
/// is null .
public ListObservable(IObservable source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
subscription = source.Subscribe(results.Add, subject.OnError, subject.OnCompleted);
}
private void Wait()
{
subject.DefaultIfEmpty().Wait();
}
///
/// Returns the last value of the observable sequence.
///
public T Value
{
get
{
Wait();
if (results.Count == 0)
{
throw new InvalidOperationException(Strings_Linq.NO_ELEMENTS);
}
return results[results.Count - 1];
}
}
///
/// Determines the index of a specific item in the ListObservable.
///
/// The element to determine the index for.
/// The index of the specified item in the list; -1 if not found.
public int IndexOf(T item)
{
Wait();
return results.IndexOf(item);
}
///
/// Inserts an item to the ListObservable at the specified index.
///
/// The index to insert the item at.
/// The item to insert in the list.
public void Insert(int index, T item)
{
Wait();
results.Insert(index, item);
}
///
/// Removes the ListObservable item at the specified index.
///
/// The index of the item to remove.
public void RemoveAt(int index)
{
Wait();
results.RemoveAt(index);
}
///
/// Gets or sets the element at the specified index.
///
/// The index of the item to retrieve or set.
public T this[int index]
{
get
{
Wait();
return results[index];
}
set
{
Wait();
results[index] = value;
}
}
///
/// Adds an item to the ListObservable.
///
/// The item to add to the list.
public void Add(T item)
{
Wait();
results.Add(item);
}
///
/// Removes all items from the ListObservable.
///
public void Clear()
{
Wait();
results.Clear();
}
///
/// Determines whether the ListObservable contains a specific value.
///
/// The item to search for in the list.
/// true if found; false otherwise.
public bool Contains(T item)
{
Wait();
return results.Contains(item);
}
///
/// Copies the elements of the ListObservable to an System.Array, starting at a particular System.Array index.
///
/// The array to copy elements to.
/// The start index in the array to start copying elements to.
public void CopyTo(T[] array, int arrayIndex)
{
Wait();
results.CopyTo(array, arrayIndex);
}
///
/// Gets the number of elements contained in the ListObservable.
///
public int Count
{
get
{
Wait();
return results.Count;
}
}
///
/// Gets a value that indicates whether the ListObservable is read-only.
///
public bool IsReadOnly
{
get { return false; }
}
///
/// Removes the first occurrence of a specific object from the ListObservable.
///
/// The item to remove from the list.
/// true if the item was found; false otherwise.
public bool Remove(T item)
{
Wait();
return results.Remove(item);
}
///
/// Returns an enumerator that iterates through the collection.
///
/// Enumerator over the list.
public IEnumerator GetEnumerator()
{
Wait();
return results.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
///
/// Subscribes an observer to the ListObservable which will be notified upon completion.
///
/// The observer to send completion or error messages to.
/// The disposable resource that can be used to unsubscribe.
/// is null .
public IDisposable Subscribe(IObserver observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
return StableCompositeDisposable.Create(subscription, subject.Subscribe(observer));
}
}
}