Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Reactive
{
/// <summary>
/// Marks the program elements that are experimental. This class cannot be inherited.
/// </summary>
[Experimental, AttributeUsage(AttributeTargets.All, AllowMultiple=false, Inherited=true)]
public sealed class ExperimentalAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
#if SIGNED
#if MONODROID || MONOTOUCH
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
#elif SIGNENHANCED // Key 272 for .NET 4.5 and beyond
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger, PublicKey=002400000c80000014010000060200000024000052534131000800000100010085aad0bef0688d1b994a0d78e1fd29fc24ac34ed3d3ac3fb9b3d0c48386ba834aa880035060a8848b2d8adf58e670ed20914be3681a891c9c8c01eef2ab22872547c39be00af0e6c72485d7cfd1a51df8947d36ceba9989106b58abe79e6a3e71a01ed6bdc867012883e0b1a4d35b1b5eeed6df21e401bb0c22f2246ccb69979dc9e61eef262832ed0f2064853725a75485fa8a3efb7e027319c86dec03dc3b1bca2b5081bab52a627b9917450dfad534799e1c7af58683bdfa135f1518ff1ea60e90d7b993a6c87fd3dd93408e35d1296f9a7f9a97c5db56c0f3cc25ad11e9777f94d138b3cea53b9a8331c2e6dcb8d2ea94e18bf1163ff112a22dbd92d429a")]
#else // Key 35 for older platforms
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
#endif
#else
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Reactive.Debugger")]
#endif

View File

@@ -0,0 +1,38 @@
using System;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Security;
[assembly: AssemblyTitle("System.Reactive.Experimental")]
// Notice: same description as in the .nuspec files; see Source/Rx/Setup/NuGet
[assembly: AssemblyDescription("Reactive Extensions Experimental Library containing unstable and infrequently used functionality.")]
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Retail")]
#endif
[assembly: AssemblyCompany("Microsoft Open Technologies, Inc.")]
[assembly: System.Reactive.Experimental]
[assembly: AssemblyProduct("Reactive Extensions")]
[assembly: AssemblyCopyright("\x00a9 Microsoft Open Technologies, Inc. All rights reserved.")]
[assembly: NeutralResourcesLanguage("en-US")]
#if !PLIB
[assembly: ComVisible(false)]
#endif
[assembly: CLSCompliant(true)]
#if HAS_APTCA && NO_CODECOVERAGE
[assembly: AllowPartiallyTrustedCallers]
#endif
// ===========================================================================
// DO NOT EDIT OR REMOVE ANYTHING BELOW THIS COMMENT.
// Version numbers are automatically generated in the msbuild files based on regular expressions
// ===========================================================================
[assembly: AssemblyVersion("2.2.0.0")]
[assembly: AssemblyFileVersion("2.2.0.0")]
[assembly: AssemblyInformationalVersion("2.2.0.0")]

View File

@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Reactive
{
class BinaryObserver<TLeft, TRight> : IObserver<Either<Notification<TLeft>, Notification<TRight>>>
{
public BinaryObserver(IObserver<TLeft> leftObserver, IObserver<TRight> rightObserver)
{
LeftObserver = leftObserver;
RightObserver = rightObserver;
}
public BinaryObserver(Action<Notification<TLeft>> left, Action<Notification<TRight>> right)
: this(left.ToObserver(), right.ToObserver())
{
}
public IObserver<TLeft> LeftObserver { get; private set; }
public IObserver<TRight> RightObserver { get; private set; }
void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnNext(Either<Notification<TLeft>, Notification<TRight>> value)
{
value.Switch(left => left.Accept(LeftObserver), right => right.Accept(RightObserver));
}
void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnError(Exception exception)
{
}
void IObserver<Either<Notification<TLeft>, Notification<TRight>>>.OnCompleted()
{
}
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reactive.Concurrency;
namespace System.Reactive.Linq
{
/// <summary>
/// Internal interface describing the LINQ to Events query language.
/// </summary>
internal interface IQueryLanguageEx
{
IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, IEnumerable<IObservable<object>>> iteratorMethod);
IObservable<Unit> Create(Func<IEnumerable<IObservable<object>>> iteratorMethod);
IObservable<TSource> Expand<TSource>(IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector);
IObservable<TSource> Expand<TSource>(IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler);
IObservable<TResult> ForkJoin<TFirst, TSecond, TResult>(IObservable<TFirst> first, IObservable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector);
IObservable<TSource[]> ForkJoin<TSource>(params IObservable<TSource>[] sources);
IObservable<TSource[]> ForkJoin<TSource>(IEnumerable<IObservable<TSource>> sources);
IObservable<TResult> Let<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, IObservable<TResult>> function);
IObservable<TResult> ManySelect<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector);
IObservable<TResult> ManySelect<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector, IScheduler scheduler);
ListObservable<TSource> ToListObservable<TSource>(IObservable<TSource> source);
}
}

View File

@@ -0,0 +1,234 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reactive.Concurrency;
namespace System.Reactive.Linq
{
/// <summary>
/// Provides a set of static methods for writing in-memory queries over observable sequences.
/// </summary>
public static class ObservableEx
{
private static IQueryLanguageEx s_impl = QueryServices.GetQueryImpl<IQueryLanguageEx>(new QueryLanguageEx());
#region Create
/// <summary>
/// Subscribes to each observable sequence returned by the iteratorMethod in sequence and returns the observable sequence of values sent to the observer given to the iteratorMethod.
/// </summary>
/// <typeparam name="TResult">The type of the elements in the produced sequence.</typeparam>
/// <param name="iteratorMethod">Iterator method that produces elements in the resulting sequence by calling the given observer.</param>
/// <returns>An observable sequence obtained by running the iterator and returning the elements that were sent to the observer.</returns>
/// <exception cref="ArgumentNullException"><paramref name="iteratorMethod"/> is null.</exception>
[Experimental]
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, IEnumerable<IObservable<object>>> iteratorMethod)
{
if (iteratorMethod == null)
throw new ArgumentNullException("iteratorMethod");
return s_impl.Create<TResult>(iteratorMethod);
}
/// <summary>
/// Subscribes to each observable sequence returned by the iteratorMethod in sequence and produces a Unit value on the resulting sequence for each step of the iteration.
/// </summary>
/// <param name="iteratorMethod">Iterator method that drives the resulting observable sequence.</param>
/// <returns>An observable sequence obtained by running the iterator and returning Unit values for each iteration step.</returns>
/// <exception cref="ArgumentNullException"><paramref name="iteratorMethod"/> is null.</exception>
[Experimental]
public static IObservable<Unit> Create(Func<IEnumerable<IObservable<object>>> iteratorMethod)
{
if (iteratorMethod == null)
throw new ArgumentNullException("iteratorMethod");
return s_impl.Create(iteratorMethod);
}
#endregion
#region Expand
/// <summary>
/// Expands an observable sequence by recursively invoking selector, using the specified scheduler to enumerate the queue of obtained sequences.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <param name="scheduler">Scheduler on which to perform the expansion by enumerating the internal queue of obtained sequences.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> or <paramref name="scheduler"/> is null.</exception>
[Experimental]
public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.Expand<TSource>(source, selector, scheduler);
}
/// <summary>
/// Expands an observable sequence by recursively invoking selector.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
[Experimental]
public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return s_impl.Expand<TSource>(source, selector);
}
#endregion
#region ForkJoin
/// <summary>
/// Runs two observable sequences in parallel and combines their last elemenets.
/// </summary>
/// <typeparam name="TSource1">The type of the elements in the first source sequence.</typeparam>
/// <typeparam name="TSource2">The type of the elements in the second source sequence.</typeparam>
/// <typeparam name="TResult">The type of the elements in the result sequence, returned by the selector function.</typeparam>
/// <param name="first">First observable sequence.</param>
/// <param name="second">Second observable sequence.</param>
/// <param name="resultSelector">Result selector function to invoke with the last elements of both sequences.</param>
/// <returns>An observable sequence with the result of calling the selector function with the last elements of both input sequences.</returns>
/// <exception cref="ArgumentNullException"><paramref name="first"/> or <paramref name="second"/> or <paramref name="resultSelector"/> is null.</exception>
[Experimental]
public static IObservable<TResult> ForkJoin<TSource1, TSource2, TResult>(this IObservable<TSource1> first, IObservable<TSource2> second, Func<TSource1, TSource2, TResult> resultSelector)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
if (resultSelector == null)
throw new ArgumentNullException("resultSelector");
return s_impl.ForkJoin<TSource1, TSource2, TResult>(first, second, resultSelector);
}
/// <summary>
/// Runs all specified observable sequences in parallel and collects their last elements.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Observable sequence to collect the last elements for.</param>
/// <returns>An observable sequence with an array collecting the last elements of all the input sequences.</returns>
/// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
[Experimental]
public static IObservable<TSource[]> ForkJoin<TSource>(params IObservable<TSource>[] sources)
{
if (sources == null)
throw new ArgumentNullException("sources");
return s_impl.ForkJoin<TSource>(sources);
}
/// <summary>
/// Runs all observable sequences in the enumerable sources sequence in parallel and collect their last elements.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Observable sequence to collect the last elements for.</param>
/// <returns>An observable sequence with an array collecting the last elements of all the input sequences.</returns>
/// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
[Experimental]
public static IObservable<TSource[]> ForkJoin<TSource>(this IEnumerable<IObservable<TSource>> sources)
{
if (sources == null)
throw new ArgumentNullException("sources");
return s_impl.ForkJoin<TSource>(sources);
}
#endregion
#region Let
/// <summary>
/// Returns an observable sequence that is the result of invoking the selector on the source sequence, without sharing subscriptions.
/// This operator allows for a fluent style of writing queries that use the same sequence multiple times.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <typeparam name="TResult">The type of the elements in the result sequence.</typeparam>
/// <param name="source">Source sequence that will be shared in the selector function.</param>
/// <param name="selector">Selector function which can use the source sequence as many times as needed, without sharing subscriptions to the source sequence.</param>
/// <returns>An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
[Experimental]
public static IObservable<TResult> Let<TSource, TResult>(this IObservable<TSource> source, Func<IObservable<TSource>, IObservable<TResult>> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return s_impl.Let<TSource, TResult>(source, selector);
}
#endregion
#region ManySelect
/// <summary>
/// Comonadic bind operator.
/// </summary>
[Experimental]
public static IObservable<TResult> ManySelect<TSource, TResult>(this IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector, IScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return s_impl.ManySelect<TSource, TResult>(source, selector, scheduler);
}
/// <summary>
/// Comonadic bind operator.
/// </summary>
[Experimental]
public static IObservable<TResult> ManySelect<TSource, TResult>(this IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return s_impl.ManySelect<TSource, TResult>(source, selector);
}
#endregion
#region ToListObservable
/// <summary>
/// Immediately subscribes to source and retains the elements in the observable sequence.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <param name="source">Source sequence.</param>
/// <returns>Object that's both an observable sequence and a list which can be used to access the source sequence's elements.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
[Experimental]
public static ListObservable<TSource> ToListObservable<TSource>(this IObservable<TSource> source)
{
if (source == null)
throw new ArgumentNullException("source");
return s_impl.ToListObservable<TSource>(source);
}
#endregion
}
}

View File

@@ -0,0 +1,369 @@
/*
* WARNING: Auto-generated file (11/21/2013 11:07:25 AM)
* Run Rx's auto-homoiconizer tool to generate this file (in the HomoIcon directory).
*/
#pragma warning disable 1591
#if !NO_EXPRESSIONS
using System;
using System.Reactive.Concurrency;
using System.Collections.Generic;
using System.Reactive.Joins;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Reactive;
using System.Reactive.Subjects;
#if !NO_TPL
using System.Threading.Tasks;
#endif
#if !NO_REMOTING
using System.Runtime.Remoting.Lifetime;
#endif
namespace System.Reactive.Linq
{
public static partial class QbservableEx
{
#if !STABLE
/// <summary>
/// Subscribes to each observable sequence returned by the iteratorMethod in sequence and produces a Unit value on the resulting sequence for each step of the iteration.
/// </summary>
/// <param name="provider">Query provider used to construct the IQbservable&lt;T&gt; data source.</param>
/// <param name="iteratorMethod">Iterator method that drives the resulting observable sequence.</param>
/// <returns>An observable sequence obtained by running the iterator and returning Unit values for each iteration step.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="iteratorMethod" /> is null.</exception>
[Experimental]
public static IQbservable<Unit> Create(this IQbservableProvider provider, Expression<Func<IEnumerable<IObservable<object>>>> iteratorMethod)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (iteratorMethod == null)
throw new ArgumentNullException("iteratorMethod");
return provider.CreateQuery<Unit>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.Create(default(IQbservableProvider), default(Expression<Func<IEnumerable<IObservable<object>>>>))),
#else
(MethodInfo)MethodInfo.GetCurrentMethod(),
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
iteratorMethod
)
);
}
#endif
#if !STABLE
/// <summary>
/// Subscribes to each observable sequence returned by the iteratorMethod in sequence and returns the observable sequence of values sent to the observer given to the iteratorMethod.
/// </summary>
/// <param name="provider">Query provider used to construct the IQbservable&lt;T&gt; data source.</param>
/// <typeparam name="TResult">The type of the elements in the produced sequence.</typeparam>
/// <param name="iteratorMethod">Iterator method that produces elements in the resulting sequence by calling the given observer.</param>
/// <returns>An observable sequence obtained by running the iterator and returning the elements that were sent to the observer.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="iteratorMethod" /> is null.</exception>
[Experimental]
public static IQbservable<TResult> Create<TResult>(this IQbservableProvider provider, Expression<Func<IObserver<TResult>, IEnumerable<IObservable<object>>>> iteratorMethod)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (iteratorMethod == null)
throw new ArgumentNullException("iteratorMethod");
return provider.CreateQuery<TResult>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.Create<TResult>(default(IQbservableProvider), default(Expression<Func<IObserver<TResult>, IEnumerable<IObservable<object>>>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TResult)),
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
iteratorMethod
)
);
}
#endif
#if !STABLE
/// <summary>
/// Expands an observable sequence by recursively invoking selector.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> or <paramref name="selector" /> is null.</exception>
[Experimental]
public static IQbservable<TSource> Expand<TSource>(this IQbservable<TSource> source, Expression<Func<TSource, IObservable<TSource>>> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.Provider.CreateQuery<TSource>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.Expand<TSource>(default(IQbservable<TSource>), default(Expression<Func<TSource, IObservable<TSource>>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)),
#endif
source.Expression,
selector
)
);
}
#endif
#if !STABLE
/// <summary>
/// Expands an observable sequence by recursively invoking selector, using the specified scheduler to enumerate the queue of obtained sequences.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <param name="scheduler">Scheduler on which to perform the expansion by enumerating the internal queue of obtained sequences.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> or <paramref name="selector" /> or <paramref name="scheduler" /> is null.</exception>
[Experimental]
public static IQbservable<TSource> Expand<TSource>(this IQbservable<TSource> source, Expression<Func<TSource, IObservable<TSource>>> selector, IScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return source.Provider.CreateQuery<TSource>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.Expand<TSource>(default(IQbservable<TSource>), default(Expression<Func<TSource, IObservable<TSource>>>), default(IScheduler))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)),
#endif
source.Expression,
selector,
Expression.Constant(scheduler, typeof(IScheduler))
)
);
}
#endif
#if !STABLE
/// <summary>
/// Runs all specified observable sequences in parallel and collects their last elements.
/// </summary>
/// <param name="provider">Query provider used to construct the IQbservable&lt;T&gt; data source.</param>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Observable sequence to collect the last elements for.</param>
/// <returns>An observable sequence with an array collecting the last elements of all the input sequences.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="sources" /> is null.</exception>
[Experimental]
public static IQbservable<TSource[]> ForkJoin<TSource>(this IQbservableProvider provider, params IObservable<TSource>[] sources)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (sources == null)
throw new ArgumentNullException("sources");
return provider.CreateQuery<TSource[]>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.ForkJoin<TSource>(default(IQbservableProvider), default(IObservable<TSource>[]))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)),
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
GetSourceExpression(sources)
)
);
}
#endif
#if !STABLE
/// <summary>
/// Runs all observable sequences in the enumerable sources sequence in parallel and collect their last elements.
/// </summary>
/// <param name="provider">Query provider used to construct the IQbservable&lt;T&gt; data source.</param>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Observable sequence to collect the last elements for.</param>
/// <returns>An observable sequence with an array collecting the last elements of all the input sequences.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="sources" /> is null.</exception>
[Experimental]
public static IQbservable<TSource[]> ForkJoin<TSource>(this IQbservableProvider provider, IEnumerable<IObservable<TSource>> sources)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (sources == null)
throw new ArgumentNullException("sources");
return provider.CreateQuery<TSource[]>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.ForkJoin<TSource>(default(IQbservableProvider), default(IEnumerable<IObservable<TSource>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)),
#endif
Expression.Constant(provider, typeof(IQbservableProvider)),
GetSourceExpression(sources)
)
);
}
#endif
#if !STABLE
/// <summary>
/// Runs two observable sequences in parallel and combines their last elemenets.
/// </summary>
/// <typeparam name="TSource1">The type of the elements in the first source sequence.</typeparam>
/// <typeparam name="TSource2">The type of the elements in the second source sequence.</typeparam>
/// <typeparam name="TResult">The type of the elements in the result sequence, returned by the selector function.</typeparam>
/// <param name="first">First observable sequence.</param>
/// <param name="second">Second observable sequence.</param>
/// <param name="resultSelector">Result selector function to invoke with the last elements of both sequences.</param>
/// <returns>An observable sequence with the result of calling the selector function with the last elements of both input sequences.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="first" /> or <paramref name="second" /> or <paramref name="resultSelector" /> is null.</exception>
[Experimental]
public static IQbservable<TResult> ForkJoin<TSource1, TSource2, TResult>(this IQbservable<TSource1> first, IObservable<TSource2> second, Expression<Func<TSource1, TSource2, TResult>> resultSelector)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
if (resultSelector == null)
throw new ArgumentNullException("resultSelector");
return first.Provider.CreateQuery<TResult>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.ForkJoin<TSource1, TSource2, TResult>(default(IQbservable<TSource1>), default(IObservable<TSource2>), default(Expression<Func<TSource1, TSource2, TResult>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource1), typeof(TSource2), typeof(TResult)),
#endif
first.Expression,
GetSourceExpression(second),
resultSelector
)
);
}
#endif
#if !STABLE
/// <summary>
/// Returns an observable sequence that is the result of invoking the selector on the source sequence, without sharing subscriptions.
/// This operator allows for a fluent style of writing queries that use the same sequence multiple times.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <typeparam name="TResult">The type of the elements in the result sequence.</typeparam>
/// <param name="source">Source sequence that will be shared in the selector function.</param>
/// <param name="selector">Selector function which can use the source sequence as many times as needed, without sharing subscriptions to the source sequence.</param>
/// <returns>An observable sequence that contains the elements of a sequence produced by multicasting the source sequence within a selector function.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> or <paramref name="selector" /> is null.</exception>
[Experimental]
public static IQbservable<TResult> Let<TSource, TResult>(this IQbservable<TSource> source, Expression<Func<IObservable<TSource>, IObservable<TResult>>> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.Provider.CreateQuery<TResult>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.Let<TSource, TResult>(default(IQbservable<TSource>), default(Expression<Func<IObservable<TSource>, IObservable<TResult>>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)),
#endif
source.Expression,
selector
)
);
}
#endif
#if !STABLE
/// <summary>
/// Comonadic bind operator.
/// </summary>
[Experimental]
public static IQbservable<TResult> ManySelect<TSource, TResult>(this IQbservable<TSource> source, Expression<Func<IObservable<TSource>, TResult>> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.Provider.CreateQuery<TResult>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.ManySelect<TSource, TResult>(default(IQbservable<TSource>), default(Expression<Func<IObservable<TSource>, TResult>>))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)),
#endif
source.Expression,
selector
)
);
}
#endif
#if !STABLE
/// <summary>
/// Comonadic bind operator.
/// </summary>
[Experimental]
public static IQbservable<TResult> ManySelect<TSource, TResult>(this IQbservable<TSource> source, Expression<Func<IObservable<TSource>, TResult>> selector, IScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
if (scheduler == null)
throw new ArgumentNullException("scheduler");
return source.Provider.CreateQuery<TResult>(
Expression.Call(
null,
#if CRIPPLED_REFLECTION
InfoOf(() => QbservableEx.ManySelect<TSource, TResult>(default(IQbservable<TSource>), default(Expression<Func<IObservable<TSource>, TResult>>), default(IScheduler))),
#else
((MethodInfo)MethodInfo.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)),
#endif
source.Expression,
selector,
Expression.Constant(scheduler, typeof(IScheduler))
)
);
}
#endif
}
}
#endif
#pragma warning restore 1591

View File

@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_EXPRESSIONS
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace System.Reactive.Linq
{
/// <summary>
/// Provides a set of static methods for writing queries over observable sequences, allowing translation to a target query language.
/// </summary>
[LocalQueryMethodImplementationType(typeof(ObservableEx))]
public static partial class QbservableEx
{
internal static Expression GetSourceExpression<TSource>(IObservable<TSource> source)
{
var q = source as IQbservable<TSource>;
if (q != null)
return q.Expression;
return Expression.Constant(source, typeof(IObservable<TSource>));
}
internal static Expression GetSourceExpression<TSource>(IEnumerable<TSource> source)
{
var q = source as IQueryable<TSource>;
if (q != null)
return q.Expression;
return Expression.Constant(source, typeof(IEnumerable<TSource>));
}
internal static Expression GetSourceExpression<TSource>(IObservable<TSource>[] sources)
{
return Expression.NewArrayInit(
typeof(IObservable<TSource>),
sources.Select(source => GetSourceExpression(source))
);
}
internal static Expression GetSourceExpression<TSource>(IEnumerable<TSource>[] sources)
{
return Expression.NewArrayInit(
typeof(IEnumerable<TSource>),
sources.Select(source => GetSourceExpression(source))
);
}
internal static MethodInfo InfoOf<R>(Expression<Func<R>> f)
{
return ((MethodCallExpression)f.Body).Method;
}
}
}
#endif

View File

@@ -0,0 +1,445 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Subjects;
namespace System.Reactive.Linq
{
internal class QueryLanguageEx : IQueryLanguageEx
{
#region Create
public virtual IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, IEnumerable<IObservable<object>>> iteratorMethod)
{
return new AnonymousObservable<TResult>(observer =>
iteratorMethod(observer).Concat().Subscribe(_ => { }, observer.OnError, observer.OnCompleted));
}
public virtual IObservable<Unit> Create(Func<IEnumerable<IObservable<object>>> iteratorMethod)
{
return new AnonymousObservable<Unit>(observer =>
iteratorMethod().Concat().Subscribe(_ => { }, observer.OnError, observer.OnCompleted));
}
#endregion
#region Expand
public virtual IObservable<TSource> Expand<TSource>(IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler)
{
return new AnonymousObservable<TSource>(observer =>
{
var outGate = new object();
var q = new Queue<IObservable<TSource>>();
var m = new SerialDisposable();
var d = new CompositeDisposable { m };
var activeCount = 0;
var isAcquired = false;
var ensureActive = default(Action);
ensureActive = () =>
{
var isOwner = false;
lock (q)
{
if (q.Count > 0)
{
isOwner = !isAcquired;
isAcquired = true;
}
}
if (isOwner)
{
m.Disposable = scheduler.Schedule(self =>
{
var work = default(IObservable<TSource>);
lock (q)
{
if (q.Count > 0)
work = q.Dequeue();
else
{
isAcquired = false;
return;
}
}
var m1 = new SingleAssignmentDisposable();
d.Add(m1);
m1.Disposable = work.Subscribe(
x =>
{
lock (outGate)
observer.OnNext(x);
var result = default(IObservable<TSource>);
try
{
result = selector(x);
}
catch (Exception exception)
{
lock (outGate)
observer.OnError(exception);
}
lock (q)
{
q.Enqueue(result);
activeCount++;
}
ensureActive();
},
exception =>
{
lock (outGate)
observer.OnError(exception);
},
() =>
{
d.Remove(m1);
var done = false;
lock (q)
{
activeCount--;
if (activeCount == 0)
done = true;
}
if (done)
lock (outGate)
observer.OnCompleted();
});
self();
});
}
};
lock (q)
{
q.Enqueue(source);
activeCount++;
}
ensureActive();
return d;
});
}
public virtual IObservable<TSource> Expand<TSource>(IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector)
{
return source.Expand(selector, SchedulerDefaults.Iteration);
}
#endregion
#region ForkJoin
public virtual IObservable<TResult> ForkJoin<TFirst, TSecond, TResult>(IObservable<TFirst> first, IObservable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
return Combine<TFirst, TSecond, TResult>(first, second, (observer, leftSubscription, rightSubscription) =>
{
var leftStopped = false;
var rightStopped = false;
var hasLeft = false;
var hasRight = false;
var lastLeft = default(TFirst);
var lastRight = default(TSecond);
return new BinaryObserver<TFirst, TSecond>(
left =>
{
switch (left.Kind)
{
case NotificationKind.OnNext:
hasLeft = true;
lastLeft = left.Value;
break;
case NotificationKind.OnError:
rightSubscription.Dispose();
observer.OnError(left.Exception);
break;
case NotificationKind.OnCompleted:
leftStopped = true;
if (rightStopped)
{
if (!hasLeft)
observer.OnCompleted();
else if (!hasRight)
observer.OnCompleted();
else
{
TResult result;
try
{
result = resultSelector(lastLeft, lastRight);
}
catch (Exception exception)
{
observer.OnError(exception);
return;
}
observer.OnNext(result);
observer.OnCompleted();
}
}
break;
}
},
right =>
{
switch (right.Kind)
{
case NotificationKind.OnNext:
hasRight = true;
lastRight = right.Value;
break;
case NotificationKind.OnError:
leftSubscription.Dispose();
observer.OnError(right.Exception);
break;
case NotificationKind.OnCompleted:
rightStopped = true;
if (leftStopped)
{
if (!hasLeft)
observer.OnCompleted();
else if (!hasRight)
observer.OnCompleted();
else
{
TResult result;
try
{
result = resultSelector(lastLeft, lastRight);
}
catch (Exception exception)
{
observer.OnError(exception);
return;
}
observer.OnNext(result);
observer.OnCompleted();
}
}
break;
}
});
});
}
public virtual IObservable<TSource[]> ForkJoin<TSource>(params IObservable<TSource>[] sources)
{
return sources.ForkJoin();
}
public virtual IObservable<TSource[]> ForkJoin<TSource>(IEnumerable<IObservable<TSource>> sources)
{
return new AnonymousObservable<TSource[]>(subscriber =>
{
var allSources = sources.ToArray();
var count = allSources.Length;
if (count == 0)
{
subscriber.OnCompleted();
return Disposable.Empty;
}
var group = new CompositeDisposable(allSources.Length);
var gate = new object();
var finished = false;
var hasResults = new bool[count];
var hasCompleted = new bool[count];
var results = new List<TSource>(count);
lock (gate)
{
for (var index = 0; index < count; index++)
{
var currentIndex = index;
var source = allSources[index];
results.Add(default(TSource));
group.Add(source.Subscribe(
value =>
{
lock (gate)
{
if (!finished)
{
hasResults[currentIndex] = true;
results[currentIndex] = value;
}
}
},
error =>
{
lock (gate)
{
finished = true;
subscriber.OnError(error);
group.Dispose();
}
},
() =>
{
lock (gate)
{
if (!finished)
{
if (!hasResults[currentIndex])
{
subscriber.OnCompleted();
return;
}
hasCompleted[currentIndex] = true;
foreach (var completed in hasCompleted)
{
if (!completed)
return;
}
finished = true;
subscriber.OnNext(results.ToArray());
subscriber.OnCompleted();
}
}
}));
}
}
return group;
});
}
#endregion
#region Let
public virtual IObservable<TResult> Let<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, IObservable<TResult>> function)
{
return function(source);
}
#endregion
#region ManySelect
public virtual IObservable<TResult> ManySelect<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector)
{
return ManySelect(source, selector, DefaultScheduler.Instance);
}
public virtual IObservable<TResult> ManySelect<TSource, TResult>(IObservable<TSource> source, Func<IObservable<TSource>, TResult> selector, IScheduler scheduler)
{
return Observable.Defer<TResult>(() =>
{
var chain = default(ChainObservable<TSource>);
return source
.Select(
x =>
{
var curr = new ChainObservable<TSource>(x);
if (chain != null)
chain.OnNext(curr);
chain = curr;
return (IObservable<TSource>)curr;
})
.Do(
_ => { },
exception =>
{
if (chain != null)
chain.OnError(exception);
},
() =>
{
if (chain != null)
chain.OnCompleted();
})
.ObserveOn(scheduler)
.Select(selector);
});
}
class ChainObservable<T> : ISubject<IObservable<T>, T>
{
T head;
AsyncSubject<IObservable<T>> tail = new AsyncSubject<IObservable<T>>();
public ChainObservable(T head)
{
this.head = head;
}
public IDisposable Subscribe(IObserver<T> observer)
{
var g = new CompositeDisposable();
g.Add(CurrentThreadScheduler.Instance.Schedule(() =>
{
observer.OnNext(head);
g.Add(tail.Merge().Subscribe(observer));
}));
return g;
}
public void OnCompleted()
{
OnNext(Observable.Empty<T>());
}
public void OnError(Exception error)
{
OnNext(Observable.Throw<T>(error));
}
public void OnNext(IObservable<T> value)
{
tail.OnNext(value);
tail.OnCompleted();
}
}
#endregion
#region ToListObservable
public virtual ListObservable<TSource> ToListObservable<TSource>(IObservable<TSource> source)
{
return new ListObservable<TSource>(source);
}
#endregion
#region |> Helpers <|
private static IObservable<TResult> Combine<TLeft, TRight, TResult>(IObservable<TLeft> leftSource, IObservable<TRight> rightSource, Func<IObserver<TResult>, IDisposable, IDisposable, IObserver<Either<Notification<TLeft>, Notification<TRight>>>> combinerSelector)
{
return new AnonymousObservable<TResult>(observer =>
{
var leftSubscription = new SingleAssignmentDisposable();
var rightSubscription = new SingleAssignmentDisposable();
var combiner = combinerSelector(observer, leftSubscription, rightSubscription);
var gate = new object();
leftSubscription.Disposable = leftSource.Materialize().Select(x => Either<Notification<TLeft>, Notification<TRight>>.CreateLeft(x)).Synchronize(gate).Subscribe(combiner);
rightSubscription.Disposable = rightSource.Materialize().Select(x => Either<Notification<TLeft>, Notification<TRight>>.CreateRight(x)).Synchronize(gate).Subscribe(combiner);
return new CompositeDisposable(leftSubscription, rightSubscription);
});
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{41E65B96-733B-41C4-A1BB-7476359B89EB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>System.Reactive.Experimental</RootNamespace>
<AssemblyName>System.Reactive.Experimental</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProductSignAssembly>true</ProductSignAssembly>
<CodeAnalysisRuleSet>..\Rx.ruleset</CodeAnalysisRuleSet>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseXBLV|AnyCPU'">
<OutputPath>bin\ReleaseXBLV\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugXBLV|AnyCPU'">
<OutputPath>bin\DebugXBLV\</OutputPath>
</PropertyGroup>
<Import Project="..\Common.targets" />
<PropertyGroup>
<DocumentationFile>$(OutputPath)\$(AssemblyName).XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" Condition=" '$(BuildPlatform)' == 'SILVERLIGHT' Or '$(BuildPlatform)' == 'XNA' " />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Observable" Condition=" '$(BuildFlavor)' == 'SILVERLIGHTM7' " />
</ItemGroup>
<ItemGroup>
<Compile Include="ExperimentalAttribute.cs" />
<Compile Include="InternalsVisibleTo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reactive\Internal\BinaryObserver.cs" />
<Compile Include="Reactive\Linq\QbservableEx.cs" />
<Compile Include="Reactive\Linq\IQueryLanguageEx.cs" />
<Compile Include="Reactive\Linq\ObservableEx.cs" />
<Compile Include="Reactive\Linq\QbservableEx.Generated.cs" />
<Compile Include="Reactive\Linq\QueryLanguageEx.cs" />
<Compile Include="Reactive\ListObservable.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\System.Reactive.Linq\System.Reactive.Linq.csproj">
<Project>{63252AE9-5186-45CA-BFCD-FA51C6B66A43}</Project>
<Name>System.Reactive.Linq</Name>
</ProjectReference>
<ProjectReference Include="..\System.Reactive.Core\System.Reactive.Core.csproj">
<Project>{4E516F10-DA7A-4D43-963E-A93865ABEA5B}</Project>
<Name>System.Reactive.Core</Name>
</ProjectReference>
<ProjectReference Include="..\System.Reactive.Interfaces\System.Reactive.Interfaces.csproj">
<Project>{9E9B9C60-98B0-40FA-9C2B-1218D417CAA4}</Project>
<Name>System.Reactive.Interfaces</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\Import.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</Project>