AsyncEnumerableQuery.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. namespace System.Linq
  7. {
  8. /// <summary>
  9. /// Representation of an asynchronous enumerable sequence using an expression tree.
  10. /// </summary>
  11. internal abstract class AsyncEnumerableQuery
  12. {
  13. /// <summary>
  14. /// Gets the enumerable sequence obtained from evaluating the expression tree.
  15. /// </summary>
  16. internal abstract object Enumerable { get; }
  17. /// <summary>
  18. /// Gets the expression tree representing the asynchronous enumerable sequence.
  19. /// </summary>
  20. internal abstract Expression Expression { get; }
  21. }
  22. /// <summary>
  23. /// Representation of an asynchronous enumerable sequence using an expression tree.
  24. /// </summary>
  25. /// <typeparam name="T">The type of the elements in the sequence.</typeparam>
  26. internal class AsyncEnumerableQuery<T> : AsyncEnumerableQuery, IOrderedAsyncQueryable<T>, IAsyncQueryProvider
  27. {
  28. private readonly Expression _expression;
  29. private IAsyncEnumerable<T> _enumerable;
  30. /// <summary>
  31. /// Creates a new asynchronous enumerable sequence represented by the specified expression tree.
  32. /// </summary>
  33. /// <param name="expression">The expression tree representing the asynchronous enumerable sequence.</param>
  34. public AsyncEnumerableQuery(Expression expression)
  35. {
  36. _expression = expression;
  37. }
  38. /// <summary>
  39. /// Creates a new asynchronous enumerable sequence by wrapping the specified sequence in an expression tree representation.
  40. /// </summary>
  41. /// <param name="enumerable">The asynchronous enumerable sequence to represent using an expression tree.</param>
  42. public AsyncEnumerableQuery(IAsyncEnumerable<T> enumerable)
  43. {
  44. _enumerable = enumerable;
  45. _expression = Expression.Constant(this);
  46. }
  47. /// <summary>
  48. /// Gets the type of the elements in the sequence.
  49. /// </summary>
  50. Type IAsyncQueryable.ElementType
  51. {
  52. get
  53. {
  54. return typeof(T);
  55. }
  56. }
  57. /// <summary>
  58. /// Gets the expression representing the sequence.
  59. /// </summary>
  60. Expression IAsyncQueryable.Expression
  61. {
  62. get
  63. {
  64. return _expression;
  65. }
  66. }
  67. /// <summary>
  68. /// Gets the query provider used to execute the sequence.
  69. /// </summary>
  70. IAsyncQueryProvider IAsyncQueryable.Provider
  71. {
  72. get
  73. {
  74. return this;
  75. }
  76. }
  77. /// <summary>
  78. /// Gets the enumerable sequence obtained from evaluating the expression tree.
  79. /// </summary>
  80. internal override object Enumerable
  81. {
  82. get
  83. {
  84. return _enumerable;
  85. }
  86. }
  87. /// <summary>
  88. /// Gets the expression tree representing the asynchronous enumerable sequence.
  89. /// </summary>
  90. internal override Expression Expression
  91. {
  92. get
  93. {
  94. return _expression;
  95. }
  96. }
  97. /// <summary>
  98. /// Creates a new asynchronous enumerable sequence represented by an expression tree.
  99. /// </summary>
  100. /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
  101. /// <param name="expression">The expression tree representing the asynchronous enumerable sequence.</param>
  102. /// <returns>Asynchronous enumerable sequence represented by the specified expression tree.</returns>
  103. IAsyncQueryable<TElement> IAsyncQueryProvider.CreateQuery<TElement>(Expression expression)
  104. {
  105. return new AsyncEnumerableQuery<TElement>(expression);
  106. }
  107. /// <summary>
  108. /// Executes an expression tree representing a computation over asynchronous enumerable sequences.
  109. /// </summary>
  110. /// <typeparam name="TResult">The type of the result of evaluating the expression tree.</typeparam>
  111. /// <param name="expression">The expression tree to evaluate.</param>
  112. /// <param name="token">Cancellation token used to cancel the evaluation.</param>
  113. /// <returns>Task representing the result of evaluating the specified expression tree.</returns>
  114. Task<TResult> IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, CancellationToken token)
  115. {
  116. if (expression == null)
  117. {
  118. throw new ArgumentNullException("expression");
  119. }
  120. if (!typeof(Task<TResult>).IsAssignableFrom(expression.Type))
  121. {
  122. throw new ArgumentException("The specified expression is not assignable to the result type.", "expression");
  123. }
  124. return new AsyncEnumerableExecutor<TResult>(expression).ExecuteAsync(token);
  125. }
  126. /// <summary>
  127. /// Gets an enumerator to enumerate the elements in the sequence.
  128. /// </summary>
  129. /// <returns>A new enumerator instance used to enumerate the elements in the sequence.</returns>
  130. public IAsyncEnumerator<T> GetEnumerator()
  131. {
  132. if (_enumerable == null)
  133. {
  134. var expression = Expression.Lambda<Func<IAsyncEnumerable<T>>>(new AsyncEnumerableRewriter().Visit(_expression), null);
  135. _enumerable = expression.Compile()();
  136. }
  137. return _enumerable.GetEnumerator();
  138. }
  139. /// <summary>
  140. /// Gets a string representation of the enumerable sequence.
  141. /// </summary>
  142. /// <returns>String representation of the enumerable sequence.</returns>
  143. public override string ToString()
  144. {
  145. var ce = _expression as ConstantExpression;
  146. if (ce == null || ce.Value != this)
  147. {
  148. return _expression.ToString();
  149. }
  150. if (_enumerable != null)
  151. {
  152. return _enumerable.ToString();
  153. }
  154. return "null";
  155. }
  156. }
  157. }