Переглянути джерело

Moving some Create methods to AsyncEnumerator.

Bart De Smet 8 роки тому
батько
коміт
b479229682

+ 82 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/AsyncEnumerator.cs

@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
 
+using System.Diagnostics;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -12,6 +14,30 @@ namespace System.Collections.Generic
     /// </summary>
     public static class AsyncEnumerator
     {
+        public static IAsyncEnumerator<T> Create<T>(Func<Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
+        {
+            if (moveNext == null)
+                throw new ArgumentNullException(nameof(moveNext));
+
+            // Note: Many methods pass null in for the second two params. We're assuming
+            // That the caller is responsible and knows what they're doing
+            return new AnonymousAsyncIterator<T>(moveNext, current, dispose);
+        }
+
+        internal static IAsyncEnumerator<T> Create<T>(Func<TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
+        {
+            return new AnonymousAsyncIterator<T>(
+                async () =>
+                {
+                    var tcs = new TaskCompletionSource<bool>();
+
+                    return await moveNext(tcs).ConfigureAwait(false);
+                },
+                current,
+                dispose
+            );
+        }
+
         /// <summary>
         /// Advances the enumerator to the next element in the sequence, returning the result asynchronously.
         /// </summary>
@@ -30,5 +56,61 @@ namespace System.Collections.Generic
 
             return source.MoveNextAsync();
         }
+
+        private sealed class AnonymousAsyncIterator<T> : AsyncIterator<T>
+        {
+            private readonly Func<T> currentFunc;
+            private readonly Func<Task> dispose;
+            private readonly Func<Task<bool>> moveNext;
+
+            public AnonymousAsyncIterator(Func<Task<bool>> moveNext, Func<T> currentFunc, Func<Task> dispose)
+            {
+                Debug.Assert(moveNext != null);
+
+                this.moveNext = moveNext;
+                this.currentFunc = currentFunc;
+                this.dispose = dispose;
+
+                // Explicit call to initialize enumerator mode
+                GetAsyncEnumerator();
+            }
+
+            public override AsyncIterator<T> Clone()
+            {
+                throw new NotSupportedException("AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.");
+            }
+
+            public override async Task DisposeAsync()
+            {
+                if (dispose != null)
+                {
+                    await dispose().ConfigureAwait(false);
+                }
+
+                await base.DisposeAsync().ConfigureAwait(false);
+            }
+
+            protected override async Task<bool> MoveNextCore()
+            {
+                switch (state)
+                {
+                    case AsyncIteratorState.Allocated:
+                        state = AsyncIteratorState.Iterating;
+                        goto case AsyncIteratorState.Iterating;
+
+                    case AsyncIteratorState.Iterating:
+                        if (await moveNext().ConfigureAwait(false))
+                        {
+                            current = currentFunc();
+                            return true;
+                        }
+
+                        await DisposeAsync().ConfigureAwait(false);
+                        break;
+                }
+
+                return false;
+            }
+        }
     }
 }

+ 2 - 74
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Create.cs

@@ -29,28 +29,12 @@ namespace System.Linq
 
         public static IAsyncEnumerator<T> CreateEnumerator<T>(Func<Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
         {
-            if (moveNext == null)
-                throw new ArgumentNullException(nameof(moveNext));
-
-            // Note: Many methods pass null in for the second two params. We're assuming
-            // That the caller is responsible and knows what they're doing
-            return new AnonymousAsyncIterator<T>(moveNext, current, dispose);
+            return AsyncEnumerator.Create(moveNext, current, dispose);
         }
 
         private static IAsyncEnumerator<T> CreateEnumerator<T>(Func<TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
         {
-            var self = new AnonymousAsyncIterator<T>(
-                async () =>
-                {
-                    var tcs = new TaskCompletionSource<bool>();
-
-                    return await moveNext(tcs).ConfigureAwait(false);
-                },
-                current,
-                dispose
-            );
-
-            return self;
+            return AsyncEnumerator.Create(moveNext, current, dispose);
         }
 
         private sealed class AnonymousAsyncEnumerable<T> : IAsyncEnumerable<T>
@@ -154,61 +138,5 @@ namespace System.Linq
                 }
             }
         }
-
-        private sealed class AnonymousAsyncIterator<T> : AsyncIterator<T>
-        {
-            private readonly Func<T> currentFunc;
-            private readonly Func<Task> dispose;
-            private readonly Func<Task<bool>> moveNext;
-
-            public AnonymousAsyncIterator(Func<Task<bool>> moveNext, Func<T> currentFunc, Func<Task> dispose)
-            {
-                Debug.Assert(moveNext != null);
-
-                this.moveNext = moveNext;
-                this.currentFunc = currentFunc;
-                this.dispose = dispose;
-
-                // Explicit call to initialize enumerator mode
-                GetAsyncEnumerator();
-            }
-
-            public override AsyncIterator<T> Clone()
-            {
-                throw new NotSupportedException("AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.");
-            }
-
-            public override async Task DisposeAsync()
-            {
-                if (dispose != null)
-                {
-                    await dispose().ConfigureAwait(false);
-                }
-
-                await base.DisposeAsync().ConfigureAwait(false);
-            }
-
-            protected override async Task<bool> MoveNextCore()
-            {
-                switch (state)
-                {
-                    case AsyncIteratorState.Allocated:
-                        state = AsyncIteratorState.Iterating;
-                        goto case AsyncIteratorState.Iterating;
-
-                    case AsyncIteratorState.Iterating:
-                        if (await moveNext().ConfigureAwait(false))
-                        {
-                            current = currentFunc();
-                            return true;
-                        }
-
-                        await DisposeAsync().ConfigureAwait(false);
-                        break;
-                }
-
-                return false;
-            }
-        }
     }
 }