Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1404 lines
95 KiB
C#

// 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.Threading;
namespace System.Reactive.Linq
{
public static partial class Observable
{
#region + FromEventPattern +
#region Strongly typed
#region Action<EventHandler>
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern(addHandler, removeHandler);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern(addHandler, removeHandler);
}
#endif
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler, IScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(addHandler, removeHandler, scheduler);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler, IScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(addHandler, removeHandler, scheduler);
}
#endif
#endregion
#region Action<TDelegate>
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on a supplied event delegate type, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern<TDelegate, TEventArgs>(addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on a supplied event delegate type, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TDelegate, TEventArgs>(addHandler, removeHandler, scheduler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler&lt;TEventArgs&gt;"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="conversion">A function used to convert the given event handler to a delegate compatible with the underlying .NET event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="conversion"/> or <paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Func<EventHandler<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (conversion == null)
throw new ArgumentNullException("conversion");
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern<TDelegate, TEventArgs>(conversion, addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler&lt;TEventArgs&gt;"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="conversion">A function used to convert the given event handler to a delegate compatible with the underlying .NET event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="conversion"/> or <paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Func<EventHandler<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (conversion == null)
throw new ArgumentNullException("conversion");
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TDelegate, TEventArgs>(conversion, addHandler, removeHandler, scheduler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on a supplied event delegate type with a strongly typed sender parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TDelegate, TSender, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern<TDelegate, TSender, TEventArgs>(addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on a supplied event delegate type with a strongly typed sender parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TDelegate, TSender, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TDelegate, TSender, TEventArgs>(addHandler, removeHandler, scheduler);
}
#endregion
#region Action<EventHandler<TEventArgs>>
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler&lt;TEventArgs&gt;"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Action<EventHandler<TEventArgs>> addHandler, Action<EventHandler<TEventArgs>> removeHandler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEventPattern<TEventArgs>(addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event, conforming to the standard .NET event pattern based on <see cref="EventHandler&lt;TEventArgs&gt;"/>, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Action<EventHandler<TEventArgs>> addHandler, Action<EventHandler<TEventArgs>> removeHandler, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TEventArgs>(addHandler, removeHandler, scheduler);
}
#endregion
#endregion
#region Reflection
#region Instance events
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with an <see cref="EventArgs"/> parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(object target, string eventName)
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern(target, eventName);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(object target, string eventName)
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern(target, eventName);
}
#endif
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with an <see cref="EventArgs"/> parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(object target, string eventName, IScheduler scheduler)
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(target, eventName, scheduler);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(object target, string eventName, IScheduler scheduler)
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(target, eventName, scheduler);
}
#endif
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern<TEventArgs>(target, eventName);
}
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(object target, string eventName, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TEventArgs>(target, eventName, scheduler);
}
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with a strongly typed sender and strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's first argument type is not assignable to TSender. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern<TSender, TEventArgs>(target, eventName);
}
/// <summary>
/// Converts an instance .NET event, conforming to the standard .NET event pattern with a strongly typed sender and strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the target object type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="target"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's first argument type is not assignable to TSender. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(object target, string eventName, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (target == null)
throw new ArgumentNullException("target");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TSender, TEventArgs>(target, eventName, scheduler);
}
#endregion
#region Static events
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with an <see cref="EventArgs"/> parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(Type type, string eventName)
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern(type, eventName);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName)
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern(type, eventName);
}
#endif
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with an <see cref="EventArgs"/> parameter, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
#if !NO_EVENTARGS_CONSTRAINT
public static IObservable<EventPattern<EventArgs>> FromEventPattern(Type type, string eventName, IScheduler scheduler)
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(type, eventName, scheduler);
}
#else
public static IObservable<EventPattern<object>> FromEventPattern(Type type, string eventName, IScheduler scheduler)
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern(type, eventName, scheduler);
}
#endif
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern<TEventArgs>(type, eventName);
}
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TEventArgs>(Type type, string eventName, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TEventArgs>(type, eventName, scheduler);
}
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with a strongly typed sender and strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's first argument type is not assignable to TSender. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEventPattern, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEventPattern, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
return s_impl.FromEventPattern<TSender, TEventArgs>(type, eventName);
}
/// <summary>
/// Converts a static .NET event, conforming to the standard .NET event pattern with a strongly typed sender and strongly typed event arguments, to an observable sequence.
/// Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// Reflection is used to discover the event based on the specified type and the specified event name.
/// For conversion of events that don't conform to the standard .NET event pattern, use any of the FromEvent overloads instead.
/// </summary>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="type">Type that exposes the static event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="eventName"/> or <paramref name="scheduler"/> is null.</exception>
/// <exception cref="InvalidOperationException">The event could not be found. -or- The event does not conform to the standard .NET event pattern. -or- The event's first argument type is not assignable to TSender. -or- The event's second argument type is not assignable to TEventArgs.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEventPattern calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEventPattern that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEventPattern"/>
public static IObservable<EventPattern<TSender, TEventArgs>> FromEventPattern<TSender, TEventArgs>(Type type, string eventName, IScheduler scheduler)
#if !NO_EVENTARGS_CONSTRAINT
where TEventArgs : EventArgs
#endif
{
if (type == null)
throw new ArgumentNullException("type");
if (eventName == null)
throw new ArgumentNullException("eventName");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEventPattern<TSender, TEventArgs>(type, eventName, scheduler);
}
#endregion
#endregion
#endregion
#region + FromEvent +
#region Action<TDelegate>
/// <summary>
/// Converts a .NET event to an observable sequence, using a conversion function to obtain the event delegate. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="conversion">A function used to convert the given event handler to a delegate compatible with the underlying .NET event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="conversion"/> or <paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEvent, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEvent, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
{
if (conversion == null)
throw new ArgumentNullException("conversion");
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEvent<TDelegate, TEventArgs>(conversion, addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event to an observable sequence, using a conversion function to obtain the event delegate. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="conversion">A function used to convert the given event handler to a delegate compatible with the underlying .NET event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="conversion"/> or <paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEvent that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
{
if (conversion == null)
throw new ArgumentNullException("conversion");
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEvent<TDelegate, TEventArgs>(conversion, addHandler, removeHandler, scheduler);
}
/// <summary>
/// Converts a .NET event to an observable sequence, using a supplied event delegate type. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEvent, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEvent, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEvent<TDelegate, TEventArgs>(addHandler, removeHandler);
}
/// <summary>
/// Converts a .NET event to an observable sequence, using a supplied event delegate type. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEvent that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEvent<TDelegate, TEventArgs>(addHandler, removeHandler, scheduler);
}
#endregion
#region Action<Action<TEventArgs>>
/// <summary>
/// Converts a generic Action-based .NET event to an observable sequence. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEvent, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEvent, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TEventArgs>(Action<Action<TEventArgs>> addHandler, Action<Action<TEventArgs>> removeHandler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEvent<TEventArgs>(addHandler, removeHandler);
}
/// <summary>
/// Converts a generic Action-based .NET event to an observable sequence. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEvent that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<TEventArgs> FromEvent<TEventArgs>(Action<Action<TEventArgs>> addHandler, Action<Action<TEventArgs>> removeHandler, IScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEvent<TEventArgs>(addHandler, removeHandler, scheduler);
}
#endregion
#region Action<Action>
/// <summary>
/// Converts an Action-based .NET event to an observable sequence. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// The current <see cref="SynchronizationContext"/> is captured during the call to FromEvent, and is used to post add and remove handler invocations.
/// This behavior ensures add and remove handler operations for thread-affine events are accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// If no SynchronizationContext is present at the point of calling FromEvent, add and remove handler invocations are made synchronously on the thread
/// making the Subscribe or Dispose call, respectively.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
/// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
/// more concise and easier to understand.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<Unit> FromEvent(Action<Action> addHandler, Action<Action> removeHandler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
return s_impl.FromEvent(addHandler, removeHandler);
}
/// <summary>
/// Converts an Action-based .NET event to an observable sequence. Each event invocation is surfaced through an OnNext message in the resulting sequence.
/// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
/// </summary>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <param name="scheduler">The scheduler to run the add and remove event handler logic on.</param>
/// <returns>The observable sequence that contains the event argument objects passed to the invocations of the underlying .NET event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> or <paramref name="scheduler"/> is null.</exception>
/// <remarks>
/// <para>
/// Add and remove handler invocations are made whenever the number of observers grows beyond zero.
/// As such, an event handler may be shared by multiple simultaneously active observers, using a subject for multicasting.
/// </para>
/// <para>
/// Add and remove handler invocations are run on the specified scheduler. This behavior allows add and remove handler operations for thread-affine events to be
/// accessed from the same context, as required by some UI frameworks.
/// </para>
/// <para>
/// It's recommended to lift FromEvent calls outside event stream query expressions. This best practice reduces clutter of bridging code inside queries,
/// making the query expressions more concise and easier to understand. This has additional benefits for overloads of FromEvent that omit the IScheduler
/// parameter. For more information, see the remarks section on those overloads.
/// </para>
/// </remarks>
/// <seealso cref="Observable.ToEvent"/>
public static IObservable<Unit> FromEvent(Action<Action> addHandler, Action<Action> removeHandler, IScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException("addHandler");
if (removeHandler == null)
throw new ArgumentNullException("removeHandler");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.FromEvent(addHandler, removeHandler, scheduler);
}
#endregion
#endregion
}
}