// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reactive.Concurrency; using System.Reflection; namespace System.Reactive.Linq { /// /// Provides a set of static methods for writing queries over observable sequences, allowing translation to a target query language. /// public static partial class Qbservable { /// /// Returns the input typed as an . /// This operator is used to separate the part of the query that's captured as an expression tree from the part that's executed locally. /// /// The type of the elements in the source sequence. /// An sequence to convert to an sequence. /// The original source object, but typed as an . /// is null. public static IObservable AsObservable(this IQbservable source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return source; } /// /// Converts an enumerable sequence to an observable sequence. /// /// The type of the elements in the source sequence. /// Enumerable sequence to convert to an observable sequence. /// The observable sequence whose elements are pulled from the given enumerable sequence. /// is null. /// This operator requires the source's object (see ) to implement . public static IQbservable ToQbservable(this IQueryable source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return ((IQbservableProvider)source.Provider).CreateQuery( Expression.Call( null, #pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed ((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TSource)), #pragma warning restore IL2060 source.Expression ) ); } /// /// Converts an enumerable sequence to an observable sequence, using the specified scheduler to run the enumeration loop. /// /// The type of the elements in the source sequence. /// Enumerable sequence to convert to an observable sequence. /// Scheduler to run the enumeration of the input sequence on. /// The observable sequence whose elements are pulled from the given enumerable sequence. /// or is null. /// This operator requires the source's object (see ) to implement . public static IQbservable ToQbservable(this IQueryable source, IScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return ((IQbservableProvider)source.Provider).CreateQuery( Expression.Call( null, #pragma warning disable IL2060 // ('System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.) This gets the MethodInfo for the method running right now, so it can't have been trimmed ((MethodInfo)MethodBase.GetCurrentMethod()!).MakeGenericMethod(typeof(TSource)), #pragma warning restore IL2060 source.Expression, Expression.Constant(scheduler) ) ); } internal static Expression GetSourceExpression(IObservable source) { if (source is IQbservable q) { return q.Expression; } return Expression.Constant(source, typeof(IObservable)); } internal static Expression GetSourceExpression(IEnumerable source) { if (source is IQueryable q) { return q.Expression; } return Expression.Constant(source, typeof(IEnumerable)); } internal static Expression GetSourceExpression(IObservable[] sources) { return Expression.NewArrayInit( typeof(IObservable), sources.Select(source => GetSourceExpression(source)) ); } internal static Expression GetSourceExpression(IEnumerable[] sources) { return Expression.NewArrayInit( typeof(IEnumerable), sources.Select(source => GetSourceExpression(source)) ); } internal static MethodInfo InfoOf(Expression> f) { return ((MethodCallExpression)f.Body).Method; } } }