123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- // 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.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.Runtime.ExceptionServices;
- using System.Threading.Tasks;
- #pragma warning disable 0659
- #pragma warning disable 0661
- namespace System.Reactive
- {
- /// <summary>
- /// Indicates the type of a notification.
- /// </summary>
- public enum NotificationKind
- {
- /// <summary>
- /// Represents an OnNext notification.
- /// </summary>
- OnNext,
- /// <summary>
- /// Represents an OnError notification.
- /// </summary>
- OnError,
- /// <summary>
- /// Represents an OnCompleted notification.
- /// </summary>
- OnCompleted,
- }
- /// <summary>
- /// Represents a notification to an observer.
- /// </summary>
- /// <typeparam name="T">The type of the elements received by the observer.</typeparam>
- #if !NO_SERIALIZABLE
- [Serializable]
- #endif
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2218:OverrideGetHashCodeOnOverridingEquals", Justification = "Resembles a discriminated union with finite number of subclasses (external users shouldn't create their own subtypes), each of which does override GetHashCode itself.")]
- public abstract class Notification<T> : IEquatable<Notification<T>>
- {
- /// <summary>
- /// Default constructor used by derived types.
- /// </summary>
- protected internal Notification()
- {
- }
- /// <summary>
- /// Returns the value of an OnNext notification or throws an exception.
- /// </summary>
- public abstract T Value { get; }
- /// <summary>
- /// Returns a value that indicates whether the notification has a value.
- /// </summary>
- public abstract bool HasValue { get; }
- /// <summary>
- /// Returns the exception of an OnError notification or returns <c>null</c>.
- /// </summary>
- public abstract Exception Exception { get; }
- /// <summary>
- /// Gets the kind of notification that is represented.
- /// </summary>
- public abstract NotificationKind Kind { get; }
- /// <summary>
- /// Represents an OnNext notification to an observer.
- /// </summary>
- #if !NO_DEBUGGER_ATTRIBUTES
- [DebuggerDisplay("OnNext({Value})")]
- #endif
- #if !NO_SERIALIZABLE
- [Serializable]
- #endif
- internal sealed class OnNextNotification : Notification<T>
- {
- /// <summary>
- /// Constructs a notification of a new value.
- /// </summary>
- public OnNextNotification(T value)
- {
- Value = value;
- }
- /// <summary>
- /// Returns the value of an OnNext notification.
- /// </summary>
- public override T Value { get; }
- /// <summary>
- /// Returns <c>null</c>.
- /// </summary>
- public override Exception Exception => null;
- /// <summary>
- /// Returns <c>true</c>.
- /// </summary>
- public override bool HasValue => true;
- /// <summary>
- /// Returns <see cref="NotificationKind.OnNext"/>.
- /// </summary>
- public override NotificationKind Kind => NotificationKind.OnNext;
- /// <summary>
- /// Returns the hash code for this instance.
- /// </summary>
- public override int GetHashCode() => EqualityComparer<T>.Default.GetHashCode(Value);
- /// <summary>
- /// Indicates whether this instance and a specified object are equal.
- /// </summary>
- public override bool Equals(Notification<T> other)
- {
- if (ReferenceEquals(this, other))
- return true;
- if (ReferenceEquals(other, null))
- return false;
- if (other.Kind != NotificationKind.OnNext)
- return false;
- return EqualityComparer<T>.Default.Equals(Value, other.Value);
- }
- /// <summary>
- /// Returns a string representation of this instance.
- /// </summary>
- public override string ToString() => String.Format(CultureInfo.CurrentCulture, "OnNext({0})", Value);
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- public override void Accept(IObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- observer.OnNext(Value);
- }
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Task indicating the completion of invoking the observer method.</returns>
- public override Task AcceptAsync(IAsyncObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnNextAsync(Value);
- }
- #if NOTYET
- /// <summary>
- /// Invokes the observer's method corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(IObserver<T, TResult> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnNext(Value);
- }
- #endif
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- onNext(Value);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onNext(Value);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task indicating the completion of invoking the delegate.</returns>
- public override Task AcceptAsync(Func<T, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onNext(Value);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the notification handler delegates.</typeparam>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task containing the result produced by the observation.</returns>
- public override Task<TResult> AcceptAsync<TResult>(Func<T, Task<TResult>> onNext, Func<Exception, Task<TResult>> onError, Func<Task<TResult>> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onNext(Value);
- }
- }
- /// <summary>
- /// Represents an OnError notification to an observer.
- /// </summary>
- #if !NO_DEBUGGER_ATTRIBUTES
- [DebuggerDisplay("OnError({Exception})")]
- #endif
- #if !NO_SERIALIZABLE
- [Serializable]
- #endif
- internal sealed class OnErrorNotification : Notification<T>
- {
- /// <summary>
- /// Constructs a notification of an exception.
- /// </summary>
- public OnErrorNotification(Exception exception)
- {
- Exception = exception;
- }
- /// <summary>
- /// Throws the exception.
- /// </summary>
- public override T Value { get { ExceptionDispatchInfo.Capture(Exception).Throw(); return default(T); } }
- /// <summary>
- /// Returns the exception.
- /// </summary>
- public override Exception Exception { get; }
- /// <summary>
- /// Returns <c>false</c>.
- /// </summary>
- public override bool HasValue => false;
- /// <summary>
- /// Returns <see cref="NotificationKind.OnError"/>.
- /// </summary>
- public override NotificationKind Kind => NotificationKind.OnError;
- /// <summary>
- /// Returns the hash code for this instance.
- /// </summary>
- public override int GetHashCode() => Exception.GetHashCode();
- /// <summary>
- /// Indicates whether this instance and other are equal.
- /// </summary>
- public override bool Equals(Notification<T> other)
- {
- if (ReferenceEquals(this, other))
- return true;
- if (ReferenceEquals(other, null))
- return false;
- if (other.Kind != NotificationKind.OnError)
- return false;
- return Equals(Exception, other.Exception);
- }
- /// <summary>
- /// Returns a string representation of this instance.
- /// </summary>
- public override string ToString() => String.Format(CultureInfo.CurrentCulture, "OnError({0})", Exception.GetType().FullName);
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- public override void Accept(IObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- observer.OnError(Exception);
- }
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Task indicating the completion of invoking the observer method.</returns>
- public override Task AcceptAsync(IAsyncObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnErrorAsync(Exception);
- }
- #if NOTYET
- /// <summary>
- /// Invokes the observer's method corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(IObserver<T, TResult> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnError(Exception);
- }
- #endif
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- onError(Exception);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onError(Exception);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task indicating the completion of invoking the delegate.</returns>
- public override Task AcceptAsync(Func<T, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onError(Exception);
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the notification handler delegates.</typeparam>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task containing the result produced by the observation.</returns>
- public override Task<TResult> AcceptAsync<TResult>(Func<T, Task<TResult>> onNext, Func<Exception, Task<TResult>> onError, Func<Task<TResult>> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onError(Exception);
- }
- }
- /// <summary>
- /// Represents an OnCompleted notification to an observer.
- /// </summary>
- #if !NO_DEBUGGER_ATTRIBUTES
- [DebuggerDisplay("OnCompleted()")]
- #endif
- #if !NO_SERIALIZABLE
- [Serializable]
- #endif
- internal sealed class OnCompletedNotification : Notification<T>
- {
- /// <summary>
- /// Constructs a notification of the end of a sequence.
- /// </summary>
- public OnCompletedNotification()
- {
- }
- /// <summary>
- /// Throws an <see cref="InvalidOperationException"/>.
- /// </summary>
- public override T Value { get { throw new InvalidOperationException("An OnCompleted notification does not have a value."); } }
- /// <summary>
- /// Returns <c>null</c>.
- /// </summary>
- public override Exception Exception => null;
- /// <summary>
- /// Returns <c>false</c>.
- /// </summary>
- public override bool HasValue => false;
- /// <summary>
- /// Returns <see cref="NotificationKind.OnCompleted"/>.
- /// </summary>
- public override NotificationKind Kind => NotificationKind.OnCompleted;
- /// <summary>
- /// Returns the hash code for this instance.
- /// </summary>
- public override int GetHashCode() => typeof(T).GetHashCode() ^ 8510;
- /// <summary>
- /// Indicates whether this instance and other are equal.
- /// </summary>
- public override bool Equals(Notification<T> other)
- {
- if (ReferenceEquals(this, other))
- return true;
- if (ReferenceEquals(other, null))
- return false;
- return other.Kind == NotificationKind.OnCompleted;
- }
- /// <summary>
- /// Returns a string representation of this instance.
- /// </summary>
- public override string ToString() => "OnCompleted()";
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- public override void Accept(IObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- observer.OnCompleted();
- }
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Task indicating the completion of invoking the observer method.</returns>
- public override Task AcceptAsync(IAsyncObserver<T> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnCompletedAsync();
- }
- #if NOTYET
- /// <summary>
- /// Invokes the observer's method corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(IObserver<T, TResult> observer)
- {
- if (observer == null)
- throw new ArgumentNullException(nameof(observer));
- return observer.OnCompleted();
- }
- #endif
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- public override void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- onCompleted();
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Result produced by the observation.</returns>
- public override TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onCompleted();
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task indicating the completion of invoking the delegate.</returns>
- public override Task AcceptAsync(Func<T, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onCompleted();
- }
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the notification handler delegates.</typeparam>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task containing the result produced by the observation.</returns>
- public override Task<TResult> AcceptAsync<TResult>(Func<T, Task<TResult>> onNext, Func<Exception, Task<TResult>> onError, Func<Task<TResult>> onCompleted)
- {
- if (onNext == null)
- throw new ArgumentNullException(nameof(onNext));
- if (onError == null)
- throw new ArgumentNullException(nameof(onError));
- if (onCompleted == null)
- throw new ArgumentNullException(nameof(onCompleted));
- return onCompleted();
- }
- }
- /// <summary>
- /// Determines whether the current <see cref="Notification{T}"/> object has the same observer message payload as a specified <see cref="Notification{T}"/> value.
- /// </summary>
- /// <param name="other">An object to compare to the current <see cref="Notification{T}"/> object.</param>
- /// <returns><c>true</c> if both <see cref="Notification{T}"/> objects have the same observer message payload; otherwise, <c>false</c>.</returns>
- /// <remarks>
- /// Equality of <see cref="Notification{T}"/> objects is based on the equality of the observer message payload they represent, including the notification Kind and the Value or Exception (if any).
- /// This means two <see cref="Notification{T}"/> objects can be equal even though they don't represent the same observer method call, but have the same Kind and have equal parameters passed to the observer method.
- /// In case one wants to determine whether two <see cref="Notification{T}"/> objects represent the same observer method call, use Object.ReferenceEquals identity equality instead.
- /// </remarks>
- public abstract bool Equals(Notification<T> other);
- /// <summary>
- /// Determines whether the two specified <see cref="Notification{T}"/> objects have the same observer message payload.
- /// </summary>
- /// <param name="left">The first <see cref="Notification{T}"/> to compare, or <c>null</c>.</param>
- /// <param name="right">The second <see cref="Notification{T}"/> to compare, or <c>null</c>.</param>
- /// <returns><c>true</c> if the first <see cref="Notification{T}"/> value has the same observer message payload as the second <see cref="Notification{T}"/> value; otherwise, <c>false</c>.</returns>
- /// <remarks>
- /// Equality of <see cref="Notification{T}"/> objects is based on the equality of the observer message payload they represent, including the notification Kind and the Value or Exception (if any).
- /// This means two <see cref="Notification{T}"/> objects can be equal even though they don't represent the same observer method call, but have the same Kind and have equal parameters passed to the observer method.
- /// In case one wants to determine whether two <see cref="Notification{T}"/> objects represent the same observer method call, use Object.ReferenceEquals identity equality instead.
- /// </remarks>
- public static bool operator ==(Notification<T> left, Notification<T> right)
- {
- if (ReferenceEquals(left, right))
- return true;
- if ((object)left == null || (object)right == null)
- return false;
- return left.Equals(right);
- }
- /// <summary>
- /// Determines whether the two specified <see cref="Notification{T}"/> objects have a different observer message payload.
- /// </summary>
- /// <param name="left">The first <see cref="Notification{T}"/> to compare, or <c>null</c>.</param>
- /// <param name="right">The second <see cref="Notification{T}"/> to compare, or <c>null</c>.</param>
- /// <returns><c>true</c> if the first <see cref="Notification{T}"/> value has a different observer message payload as the second <see cref="Notification{T}"/> value; otherwise, <c>false</c>.</returns>
- /// <remarks>
- /// Equality of <see cref="Notification{T}"/> objects is based on the equality of the observer message payload they represent, including the notification Kind and the Value or Exception (if any).
- /// This means two <see cref="Notification{T}"/> objects can be equal even though they don't represent the same observer method call, but have the same Kind and have equal parameters passed to the observer method.
- /// In case one wants to determine whether two <see cref="Notification{T}"/> objects represent a different observer method call, use Object.ReferenceEquals identity equality instead.
- /// </remarks>
- public static bool operator !=(Notification<T> left, Notification<T> right) => !(left == right);
- /// <summary>
- /// Determines whether the specified System.Object is equal to the current <see cref="Notification{T}"/>.
- /// </summary>
- /// <param name="obj">The System.Object to compare with the current <see cref="Notification{T}"/>.</param>
- /// <returns><c>true</c> if the specified System.Object is equal to the current <see cref="Notification{T}"/>; otherwise, <c>false</c>.</returns>
- /// <remarks>
- /// Equality of <see cref="Notification{T}"/> objects is based on the equality of the observer message payload they represent, including the notification Kind and the Value or Exception (if any).
- /// This means two <see cref="Notification{T}"/> objects can be equal even though they don't represent the same observer method call, but have the same Kind and have equal parameters passed to the observer method.
- /// In case one wants to determine whether two <see cref="Notification{T}"/> objects represent the same observer method call, use Object.ReferenceEquals identity equality instead.
- /// </remarks>
- public override bool Equals(object obj) => Equals(obj as Notification<T>);
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- public abstract void Accept(IObserver<T> observer);
- /// <summary>
- /// Invokes the observer's method corresponding to the notification.
- /// </summary>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Task indicating the completion of invoking the observer method.</returns>
- public abstract Task AcceptAsync(IAsyncObserver<T> observer);
- #if NOTYET
- /// <summary>
- /// Invokes the observer's method corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the observer's notification handlers.</typeparam>
- /// <param name="observer">Observer to invoke the notification on.</param>
- /// <returns>Result produced by the observation.</returns>
- public abstract TResult Accept<TResult>(IObserver<T, TResult> observer);
- #endif
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- public abstract void Accept(Action<T> onNext, Action<Exception> onError, Action onCompleted);
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the notification handler delegates.</typeparam>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Result produced by the observation.</returns>
- public abstract TResult Accept<TResult>(Func<T, TResult> onNext, Func<Exception, TResult> onError, Func<TResult> onCompleted);
- /// <summary>
- /// Invokes the delegate corresponding to the notification.
- /// </summary>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task indicating the completion of invoking the delegate.</returns>
- public abstract Task AcceptAsync(Func<T, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted);
- /// <summary>
- /// Invokes the delegate corresponding to the notification and returns the produced result.
- /// </summary>
- /// <typeparam name="TResult">The type of the result returned from the notification handler delegates.</typeparam>
- /// <param name="onNext">Delegate to invoke for an OnNext notification.</param>
- /// <param name="onError">Delegate to invoke for an OnError notification.</param>
- /// <param name="onCompleted">Delegate to invoke for an OnCompleted notification.</param>
- /// <returns>Task containing the result produced by the observation.</returns>
- public abstract Task<TResult> AcceptAsync<TResult>(Func<T, Task<TResult>> onNext, Func<Exception, Task<TResult>> onError, Func<Task<TResult>> onCompleted);
- #if NOTYET
- /// <summary>
- /// Returns an observable sequence with a single notification, using the immediate scheduler.
- /// </summary>
- /// <returns>The observable sequence that surfaces the behavior of the notification upon subscription.</returns>
- public IObservable<T> ToObservable() => ToObservable(ImmediateScheduler.Instance);
- /// <summary>
- /// Returns an observable sequence with a single notification.
- /// </summary>
- /// <param name="scheduler">Scheduler to send out the notification calls on.</param>
- /// <returns>The observable sequence that surfaces the behavior of the notification upon subscription.</returns>
- public IObservable<T> ToObservable(IScheduler scheduler)
- {
- if (scheduler == null)
- throw new ArgumentNullException(nameof(scheduler));
- return new AnonymousObservable<T>(observer => scheduler.Schedule(() =>
- {
- Accept(observer);
- if (Kind == NotificationKind.OnNext)
- {
- observer.OnCompleted();
- }
- }));
- }
- #endif
- }
- /// <summary>
- /// Provides a set of static methods for constructing notifications.
- /// </summary>
- public static class Notification
- {
- /// <summary>
- /// Creates an object that represents an OnNext notification to an observer.
- /// </summary>
- /// <typeparam name="T">The type of the elements received by the observer. Upon dematerialization of the notifications into an observable sequence, this type is used as the element type for the sequence.</typeparam>
- /// <param name="value">The value contained in the notification.</param>
- /// <returns>The OnNext notification containing the value.</returns>
- public static Notification<T> CreateOnNext<T>(T value)
- {
- return new Notification<T>.OnNextNotification(value);
- }
- /// <summary>
- /// Creates an object that represents an OnError notification to an observer.
- /// </summary>
- /// <typeparam name="T">The type of the elements received by the observer. Upon dematerialization of the notifications into an observable sequence, this type is used as the element type for the sequence.</typeparam>
- /// <param name="error">The exception contained in the notification.</param>
- /// <returns>The OnError notification containing the exception.</returns>
- /// <exception cref="ArgumentNullException"><paramref name="error"/> is null.</exception>
- public static Notification<T> CreateOnError<T>(Exception error)
- {
- if (error == null)
- throw new ArgumentNullException(nameof(error));
- return new Notification<T>.OnErrorNotification(error);
- }
- /// <summary>
- /// Creates an object that represents an OnCompleted notification to an observer.
- /// </summary>
- /// <typeparam name="T">The type of the elements received by the observer. Upon dematerialization of the notifications into an observable sequence, this type is used as the element type for the sequence.</typeparam>
- /// <returns>The OnCompleted notification.</returns>
- public static Notification<T> CreateOnCompleted<T>()
- {
- return new Notification<T>.OnCompletedNotification();
- }
- }
- }
- #pragma warning restore 0659
- #pragma warning restore 0661
|