11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4+ using System . Diagnostics ;
45using System . Diagnostics . CodeAnalysis ;
56using System . Linq . Expressions ;
67using System . Reflection ;
8+ using System . Runtime . CompilerServices ;
79using Microsoft . AspNetCore . Http ;
810using Microsoft . AspNetCore . Http . Abstractions ;
911using Microsoft . Extensions . Internal ;
@@ -107,7 +109,9 @@ public static IApplicationBuilder UseMiddleware(
107109 return ( RequestDelegate ) invokeMethod . CreateDelegate ( typeof ( RequestDelegate ) , instance ) ;
108110 }
109111
110- var factory = Compile < object > ( invokeMethod , parameters ) ;
112+ var factory = RuntimeFeature . IsDynamicCodeSupported
113+ ? CompileExpression < object > ( invokeMethod , parameters )
114+ : ReflectionFallback < object > ( invokeMethod , parameters ) ;
111115
112116 return context =>
113117 {
@@ -156,8 +160,36 @@ private static IApplicationBuilder UseMiddlewareInterface(
156160 } ) ;
157161 }
158162
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 )
160164 {
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+
161193 // If we call something like
162194 //
163195 // public class Middleware
@@ -192,7 +224,7 @@ private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInf
192224
193225 var methodArguments = new Expression [ parameters . Length ] ;
194226 methodArguments [ 0 ] = httpContextArg ;
195- for ( int i = 1 ; i < parameters . Length ; i ++ )
227+ for ( var i = 1 ; i < parameters . Length ; i ++ )
196228 {
197229 var parameterType = parameters [ i ] . ParameterType ;
198230 if ( parameterType . IsByRef )
@@ -202,9 +234,9 @@ private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInf
202234
203235 var parameterTypeExpression = new Expression [ ]
204236 {
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 ) )
208240 } ;
209241
210242 var getServiceCall = Expression . Call ( GetServiceInfo , parameterTypeExpression ) ;
0 commit comments