5
5
using System . Collections ;
6
6
using System . Collections . Concurrent ;
7
7
using System . Collections . Generic ;
8
- using System . Diagnostics ;
9
8
using System . Reflection ;
10
9
using System . Threading . Tasks ;
11
10
using Microsoft . AspNetCore . Mvc . Core ;
@@ -17,8 +16,6 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
17
16
namespace Microsoft . AspNetCore . Mvc . Infrastructure
18
17
#endif
19
18
{
20
- using ReaderFunc = Func < IAsyncEnumerable < object > , Task < ICollection > > ;
21
-
22
19
/// <summary>
23
20
/// Type that reads an <see cref="IAsyncEnumerable{T}"/> instance into a
24
21
/// generic collection instance.
@@ -34,8 +31,8 @@ internal sealed class AsyncEnumerableReader
34
31
nameof ( ReadInternal ) ,
35
32
BindingFlags . NonPublic | BindingFlags . Instance ) ;
36
33
37
- private readonly ConcurrentDictionary < Type , ReaderFunc > _asyncEnumerableConverters =
38
- new ConcurrentDictionary < Type , ReaderFunc > ( ) ;
34
+ private readonly ConcurrentDictionary < Type , Func < object , Task < ICollection > > > _asyncEnumerableConverters =
35
+ new ConcurrentDictionary < Type , Func < object , Task < ICollection > > > ( ) ;
39
36
private readonly MvcOptions _mvcOptions ;
40
37
41
38
/// <summary>
@@ -48,37 +45,39 @@ public AsyncEnumerableReader(MvcOptions mvcOptions)
48
45
}
49
46
50
47
/// <summary>
51
- /// Reads a <see cref="IAsyncEnumerable{T}"/> into an <see cref="ICollection{T}"/>.
48
+ /// Attempts to produces a delagate that reads a <see cref="IAsyncEnumerable{T}"/> into an <see cref="ICollection{T}"/>.
52
49
/// </summary>
53
- /// <param name="value">The <see cref="IAsyncEnumerable{T}"/> to read.</param>
54
- /// <returns>The <see cref="ICollection"/>.</returns>
55
- public Task < ICollection > ReadAsync ( IAsyncEnumerable < object > value )
50
+ /// <param name="type">The type to read.</param>
51
+ /// <param name="reader">A delegate that when awaited reads the <see cref="IAsyncEnumerable{T}"/>.</param>
52
+ /// <returns><see langword="true" /> when <paramref name="type"/> is an instance of <see cref="IAsyncEnumerable{T}"/>, othwerise <see langword="false"/>.</returns>
53
+ public bool TryGetReader ( Type type , out Func < object , Task < ICollection > > reader )
56
54
{
57
- if ( value == null )
58
- {
59
- throw new ArgumentNullException ( nameof ( value ) ) ;
60
- }
61
-
62
- var type = value . GetType ( ) ;
63
- if ( ! _asyncEnumerableConverters . TryGetValue ( type , out var result ) )
55
+ if ( ! _asyncEnumerableConverters . TryGetValue ( type , out reader ) )
64
56
{
65
57
var enumerableType = ClosedGenericMatcher . ExtractGenericInterface ( type , typeof ( IAsyncEnumerable < > ) ) ;
66
- Debug . Assert ( enumerableType != null ) ;
67
-
68
- var enumeratedObjectType = enumerableType . GetGenericArguments ( ) [ 0 ] ;
58
+ if ( enumerableType is null )
59
+ {
60
+ // Not an IAsyncEnumerable<T>. Cache this result so we avoid reflection the next time we see this type.
61
+ reader = null ;
62
+ _asyncEnumerableConverters . TryAdd ( type , reader ) ;
63
+ }
64
+ else
65
+ {
66
+ var enumeratedObjectType = enumerableType . GetGenericArguments ( ) [ 0 ] ;
69
67
70
- var converter = ( ReaderFunc ) Converter
71
- . MakeGenericMethod ( enumeratedObjectType )
72
- . CreateDelegate ( typeof ( ReaderFunc ) , this ) ;
68
+ var converter = ( Func < object , Task < ICollection > > ) Converter
69
+ . MakeGenericMethod ( enumeratedObjectType )
70
+ . CreateDelegate ( typeof ( Func < object , Task < ICollection > > ) , this ) ;
73
71
74
- _asyncEnumerableConverters . TryAdd ( type , converter ) ;
75
- result = converter ;
72
+ reader = converter ;
73
+ _asyncEnumerableConverters . TryAdd ( type , reader ) ;
74
+ }
76
75
}
77
76
78
- return result ( value ) ;
77
+ return reader != null ;
79
78
}
80
79
81
- private async Task < ICollection > ReadInternal < T > ( IAsyncEnumerable < object > value )
80
+ private async Task < ICollection > ReadInternal < T > ( object value )
82
81
{
83
82
var asyncEnumerable = ( IAsyncEnumerable < T > ) value ;
84
83
var result = new List < T > ( ) ;
0 commit comments