/// <summary>
        /// Creates a new <see cref="ObjectResultExecutor"/>.
        /// </summary>
        /// <param name="formatterSelector">The <see cref="OutputFormatterSelector"/>.</param>
        /// <param name="writerFactory">The <see cref="IHttpResponseStreamWriterFactory"/>.</param>
        /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
        /// <param name="mvcOptions">Accessor to <see cref="MvcOptions"/>.</param>
        public ObjectResultExecutor(
            OutputFormatterSelector formatterSelector,
            IHttpResponseStreamWriterFactory writerFactory,
            ILoggerFactory loggerFactory,
            IOptions <MvcOptions> mvcOptions)
        {
            if (formatterSelector == null)
            {
                throw new ArgumentNullException(nameof(formatterSelector));
            }

            if (writerFactory == null)
            {
                throw new ArgumentNullException(nameof(writerFactory));
            }

            if (loggerFactory == null)
            {
                throw new ArgumentNullException(nameof(loggerFactory));
            }

            FormatterSelector = formatterSelector;
            WriterFactory     = writerFactory.CreateWriter;
            Logger            = loggerFactory.CreateLogger <ObjectResultExecutor>();
            var options = mvcOptions?.Value ?? throw new ArgumentNullException(nameof(mvcOptions));

            _asyncEnumerableReaderFactory = new AsyncEnumerableReader(options);
        }
 public SystemTextJsonResultExecutor(
     IOptions <JsonOptions> options,
     ILogger <SystemTextJsonResultExecutor> logger,
     IOptions <MvcOptions> mvcOptions)
 {
     _options = options.Value;
     _logger  = logger;
     _asyncEnumerableReader = new AsyncEnumerableReader(mvcOptions.Value);
 }
        public async Task Reader_ThrowsIfIAsyncEnumerableThrows()
        {
            // Arrange
            var enumerable    = ThrowingAsyncEnumerable();
            var options       = new MvcOptions();
            var readerFactory = new AsyncEnumerableReader(options);

            // Act & Assert
            Assert.True(readerFactory.TryGetReader(enumerable.GetType(), out var reader));
            await Assert.ThrowsAsync <TimeZoneNotFoundException>(() => reader(enumerable, default));
        }
        public void TryGetReader_ReturnsFalse_IfTypeIsNotIAsyncEnumerable(Type type)
        {
            // Arrange
            var options         = new MvcOptions();
            var readerFactory   = new AsyncEnumerableReader(options);
            var asyncEnumerable = TestEnumerable();

            // Act
            var result = readerFactory.TryGetReader(type, out var reader);

            // Assert
            Assert.False(result);
        }
示例#5
0
        public async Task ReadAsync_ReadsIAsyncEnumerable()
        {
            // Arrange
            var options = new MvcOptions();
            var reader  = new AsyncEnumerableReader(options);

            // Act
            var result = await reader.ReadAsync(TestEnumerable());

            // Assert
            var collection = Assert.IsAssignableFrom <ICollection <string> >(result);

            Assert.Equal(new[] { "0", "1", "2", }, collection);
        }
        public void TryGetReader_ReturnsCachedDelegate_WhenTypeImplementsMultipleIAsyncEnumerableContracts()
        {
            // Arrange
            var options          = new MvcOptions();
            var readerFactory    = new AsyncEnumerableReader(options);
            var asyncEnumerable1 = new MultiAsyncEnumerable();
            var asyncEnumerable2 = new MultiAsyncEnumerable();

            // Act
            Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader1));
            Assert.True(readerFactory.TryGetReader(asyncEnumerable2.GetType(), out var reader2));

            // Assert
            Assert.Same(reader1, reader2);
        }
        public void TryGetReader_ReturnsCachedDelegate()
        {
            // Arrange
            var options          = new MvcOptions();
            var readerFactory    = new AsyncEnumerableReader(options);
            var asyncEnumerable1 = TestEnumerable();
            var asyncEnumerable2 = TestEnumerable();

            // Act
            Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader1));
            Assert.True(readerFactory.TryGetReader(asyncEnumerable2.GetType(), out var reader2));

            // Assert
            Assert.Same(reader1, reader2);
        }
        public void TryGetReader_ReturnsDifferentInstancesForDifferentEnumerables()
        {
            // Arrange
            var options       = new MvcOptions();
            var readerFactory = new AsyncEnumerableReader(options);
            var enumerable1   = TestEnumerable();
            var enumerable2   = TestEnumerable2();

            // Act
            Assert.True(readerFactory.TryGetReader(enumerable1.GetType(), out var reader1));
            Assert.True(readerFactory.TryGetReader(enumerable2.GetType(), out var reader2));

            // Assert
            Assert.NotSame(reader1, reader2);
        }
        public async Task CachedDelegate_CanReadEnumerableInstanceMultipleTimes_ThatProduceDifferentResults()
        {
            // Arrange
            var options          = new MvcOptions();
            var readerFactory    = new AsyncEnumerableReader(options);
            var asyncEnumerable1 = TestEnumerable();
            var asyncEnumerable2 = TestEnumerable(4);

            // Act
            Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader));

            // Assert
            Assert.Equal(new[] { "0", "1", "2" }, await reader(asyncEnumerable1, default));
            Assert.Equal(new[] { "0", "1", "2", "3" }, await reader(asyncEnumerable2, default));
        }
示例#10
0
        public async Task ReadAsync_ReadsIAsyncEnumerable_ImplementingMultipleAsyncEnumerableInterfaces()
        {
            // This test ensures the reader does not fail if you have a type that implements IAsyncEnumerable for multiple Ts
            // Arrange
            var options = new MvcOptions();
            var reader  = new AsyncEnumerableReader(options);

            // Act
            var result = await reader.ReadAsync(new MultiAsyncEnumerable());

            // Assert
            var collection = Assert.IsAssignableFrom <ICollection <object> >(result);

            Assert.Equal(new[] { "0", "1", "2", }, collection);
        }
示例#11
0
        public async Task CachedDelegate_CanReadEnumerableInstanceMultipleTimes()
        {
            // Arrange
            var options          = new MvcOptions();
            var readerFactory    = new AsyncEnumerableReader(options);
            var asyncEnumerable1 = TestEnumerable();
            var asyncEnumerable2 = TestEnumerable();
            var expected         = new[] { "0", "1", "2" };

            // Act
            Assert.True(readerFactory.TryGetReader(asyncEnumerable1.GetType(), out var reader));

            // Assert
            Assert.Equal(expected, await reader(asyncEnumerable1));
            Assert.Equal(expected, await reader(asyncEnumerable2));
        }
        public async Task Reader_PassesCancellationTokenToIAsyncEnumerable()
        {
            // Arrange
            var enumerable          = AsyncEnumerable();
            var options             = new MvcOptions();
            CancellationToken token = default;
            var readerFactory       = new AsyncEnumerableReader(options);
            var cts = new CancellationTokenSource();

            // Act & Assert
            Assert.True(readerFactory.TryGetReader(enumerable.GetType(), out var reader));
            await reader(enumerable, cts.Token);

            cts.Cancel();
            Assert.Equal(cts.Token, token);

            async IAsyncEnumerable <string> AsyncEnumerable([EnumeratorCancellation] CancellationToken cancellationToken = default)
        public async Task TryGetReader_ReturnsReaderForIAsyncEnumerableOfValueType()
        {
            // Arrange
            var options         = new MvcOptions();
            var readerFactory   = new AsyncEnumerableReader(options);
            var asyncEnumerable = PrimitiveEnumerable();

            // Act
            var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader);

            // Assert
            Assert.True(result);
            var readCollection = await reader(asyncEnumerable, default);

            var collection = Assert.IsAssignableFrom <ICollection <int> >(readCollection);

            Assert.Equal(new[] { 0, 1, 2, }, collection);
        }
        public async Task TryGetReader_ReturnsReaderForIAsyncEnumerable()
        {
            // Arrange
            var options         = new MvcOptions();
            var readerFactory   = new AsyncEnumerableReader(options);
            var asyncEnumerable = TestEnumerable();

            // Act
            var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader);

            // Assert
            Assert.True(result);
            var readCollection = await reader(asyncEnumerable, default);

            var collection = Assert.IsAssignableFrom <ICollection <string> >(readCollection);

            Assert.Equal(new[] { "0", "1", "2", }, collection);
        }
示例#15
0
        public async Task ReadAsync_ThrowsIfBufferimitIsReached()
        {
            // Arrange
            var enumerable = TestEnumerable(11);
            var expected   = $"'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type '{enumerable.GetType()}'. " +
                             "This limit is in place to prevent infinite streams of 'IAsyncEnumerable<>' from continuing indefinitely. If this is not a programming mistake, " +
                             $"consider ways to reduce the collection size, or consider manually converting '{enumerable.GetType()}' into a list rather than increasing the limit.";
            var options = new MvcOptions {
                MaxIAsyncEnumerableBufferLimit = 10
            };
            var reader = new AsyncEnumerableReader(options);

            // Act
            var ex = await Assert.ThrowsAsync <InvalidOperationException>(() => reader.ReadAsync(enumerable));

            // Assert
            Assert.Equal(expected, ex.Message);
        }
        public async Task Reader_ReadsIAsyncEnumerable_ImplementingMultipleAsyncEnumerableInterfaces()
        {
            // This test ensures the reader does not fail if you have a type that implements IAsyncEnumerable for multiple Ts
            // Arrange
            var options         = new MvcOptions();
            var readerFactory   = new AsyncEnumerableReader(options);
            var asyncEnumerable = new MultiAsyncEnumerable();

            // Act
            var result = readerFactory.TryGetReader(asyncEnumerable.GetType(), out var reader);

            // Assert
            Assert.True(result);
            var readCollection = await reader(asyncEnumerable, default);

            var collection = Assert.IsAssignableFrom <ICollection <object> >(readCollection);

            Assert.Equal(new[] { "0", "1", "2", }, collection);
        }