// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Reactive.Concurrency;
using System.Reactive.Linq;
namespace System.Reactive.Subjects
{
///
/// Provides a set of static methods for creating subjects.
///
public static class Subject
{
///
/// Creates a subject from the specified observer and observable.
///
/// The type of the elements received by the observer.
/// The type of the elements produced by the observable sequence.
/// The observer used to send messages to the subject.
/// The observable used to subscribe to messages sent from the subject.
/// Subject implemented using the given observer and observable.
/// or is null.
public static ISubject Create(IObserver observer, IObservable observable)
{
if (observer == null)
throw new ArgumentNullException("observer");
if (observable == null)
throw new ArgumentNullException("observable");
return new AnonymousSubject(observer, observable);
}
///
/// Synchronizes the messages sent to the subject.
///
/// The type of the elements received by the subject.
/// The type of the elements produced by the subject.
/// The subject to synchronize.
/// Subject whose messages are synchronized.
/// is null.
public static ISubject Synchronize(ISubject subject)
{
if (subject == null)
throw new ArgumentNullException("subject");
return new AnonymousSubject(Observer.Synchronize(subject), subject);
}
///
/// Synchronizes the messages sent to the subject and notifies observers on the specified scheduler.
///
/// The type of the elements received by the subject.
/// The type of the elements produced by the subject.
/// The subject to synchronize.
/// Scheduler to notify observers on.
/// Subject whose messages are synchronized and whose observers are notified on the given scheduler.
/// or is null.
public static ISubject Synchronize(ISubject subject, IScheduler scheduler)
{
if (subject == null)
throw new ArgumentNullException("subject");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return new AnonymousSubject(Observer.Synchronize(subject), subject.ObserveOn(scheduler));
}
class AnonymousSubject : ISubject
{
private readonly IObserver _observer;
private readonly IObservable _observable;
public AnonymousSubject(IObserver observer, IObservable observable)
{
_observer = observer;
_observable = observable;
}
public void OnCompleted()
{
_observer.OnCompleted();
}
public void OnError(Exception error)
{
if (error == null)
throw new ArgumentNullException("error");
_observer.OnError(error);
}
public void OnNext(T value)
{
_observer.OnNext(value);
}
public IDisposable Subscribe(IObserver observer)
{
if (observer == null)
throw new ArgumentNullException("observer");
//
// [OK] Use of unsafe Subscribe: non-pretentious wrapping of an observable sequence.
//
return _observable.Subscribe/*Unsafe*/(observer);
}
}
}
}