1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Diagnostics ;
4
5
using System . Diagnostics . CodeAnalysis ;
5
6
using System . Linq . Expressions ;
6
7
using System . Reflection ;
8
+ using System . Runtime . CompilerServices ;
7
9
using Microsoft . AspNetCore . Http ;
8
10
using Microsoft . AspNetCore . Http . Abstractions ;
9
11
using Microsoft . Extensions . Internal ;
@@ -107,7 +109,9 @@ public static IApplicationBuilder UseMiddleware(
107
109
return ( RequestDelegate ) invokeMethod . CreateDelegate ( typeof ( RequestDelegate ) , instance ) ;
108
110
}
109
111
110
- var factory = Compile < object > ( invokeMethod , parameters ) ;
112
+ var factory = RuntimeFeature . IsDynamicCodeSupported
113
+ ? CompileExpression < object > ( invokeMethod , parameters )
114
+ : ReflectionFallback < object > ( invokeMethod , parameters ) ;
111
115
112
116
return context =>
113
117
{
@@ -156,8 +160,36 @@ private static IApplicationBuilder UseMiddlewareInterface(
156
160
} ) ;
157
161
}
158
162
159
- private static Func < T , HttpContext , IServiceProvider , Task > Compile < T > ( MethodInfo methodInfo , ParameterInfo [ ] parameters )
163
+ private static Func < T , HttpContext , IServiceProvider , Task > ReflectionFallback < T > ( MethodInfo methodInfo , ParameterInfo [ ] parameters )
160
164
{
165
+ Debug . Assert ( ! RuntimeFeature . IsDynamicCodeSupported , "Use reflection fallback when dynamic code is not supported." ) ;
166
+
167
+ for ( var i = 1 ; i < parameters . Length ; i ++ )
168
+ {
169
+ var parameterType = parameters [ i ] . ParameterType ;
170
+ if ( parameterType . IsByRef )
171
+ {
172
+ throw new NotSupportedException ( Resources . FormatException_InvokeDoesNotSupportRefOrOutParams ( InvokeMethodName ) ) ;
173
+ }
174
+ }
175
+
176
+ return ( middleware , context , serviceProvider ) =>
177
+ {
178
+ var methodArguments = new object [ parameters . Length ] ;
179
+ methodArguments [ 0 ] = context ;
180
+ for ( var i = 1 ; i < parameters . Length ; i ++ )
181
+ {
182
+ methodArguments [ i ] = GetService ( serviceProvider , parameters [ i ] . ParameterType , methodInfo . DeclaringType ! ) ;
183
+ }
184
+
185
+ return ( Task ) methodInfo . Invoke ( middleware , BindingFlags . DoNotWrapExceptions , binder : null , methodArguments , culture : null ) ! ;
186
+ } ;
187
+ }
188
+
189
+ private static Func < T , HttpContext , IServiceProvider , Task > CompileExpression < T > ( MethodInfo methodInfo , ParameterInfo [ ] parameters )
190
+ {
191
+ Debug . Assert ( RuntimeFeature . IsDynamicCodeSupported , "Use compiled expression when dynamic code is supported." ) ;
192
+
161
193
// If we call something like
162
194
//
163
195
// public class Middleware
@@ -192,7 +224,7 @@ private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInf
192
224
193
225
var methodArguments = new Expression [ parameters . Length ] ;
194
226
methodArguments [ 0 ] = httpContextArg ;
195
- for ( int i = 1 ; i < parameters . Length ; i ++ )
227
+ for ( var i = 1 ; i < parameters . Length ; i ++ )
196
228
{
197
229
var parameterType = parameters [ i ] . ParameterType ;
198
230
if ( parameterType . IsByRef )
@@ -202,9 +234,9 @@ private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInf
202
234
203
235
var parameterTypeExpression = new Expression [ ]
204
236
{
205
- providerArg ,
206
- Expression . Constant ( parameterType , typeof ( Type ) ) ,
207
- Expression . Constant ( methodInfo . DeclaringType , typeof ( Type ) )
237
+ providerArg ,
238
+ Expression . Constant ( parameterType , typeof ( Type ) ) ,
239
+ Expression . Constant ( methodInfo . DeclaringType , typeof ( Type ) )
208
240
} ;
209
241
210
242
var getServiceCall = Expression . Call ( GetServiceInfo , parameterTypeExpression ) ;
0 commit comments