@@ -52,6 +52,80 @@ public static class RequestDelegateBuilder
52
52
/// <param name="action">A request handler with any number of custom parameters that often produces a response with its return value.</param>
53
53
/// <returns>The <see cref="RequestDelegate"/></returns>
54
54
public static RequestDelegate BuildRequestDelegate ( Delegate action )
55
+ {
56
+ if ( action is null )
57
+ {
58
+ throw new ArgumentNullException ( nameof ( action ) ) ;
59
+ }
60
+
61
+ var targetExpression = action . Target switch
62
+ {
63
+ { } => Expression . Convert ( TargetArg , action . Target . GetType ( ) ) ,
64
+ null => null ,
65
+ } ;
66
+
67
+ var untargetedRequestDelegate = BuildRequestDelegate ( action . Method , targetExpression ) ;
68
+
69
+ return httpContext =>
70
+ {
71
+ return untargetedRequestDelegate ( action . Target , httpContext ) ;
72
+ } ;
73
+ }
74
+
75
+ /// <summary>
76
+ /// Builds a <see cref="RequestDelegate"/> implementation for <paramref name="methodInfo"/>.
77
+ /// </summary>
78
+ /// <param name="methodInfo">A static request handler with any number of custom parameters that often produces a response with its return value.</param>
79
+ /// <returns>The <see cref="RequestDelegate"/></returns>
80
+ public static RequestDelegate BuildRequestDelegate ( MethodInfo methodInfo )
81
+ {
82
+ if ( methodInfo is null )
83
+ {
84
+ throw new ArgumentNullException ( nameof ( methodInfo ) ) ;
85
+ }
86
+
87
+ var untargetedRequestDelegate = BuildRequestDelegate ( methodInfo , targetExpression : null ) ;
88
+
89
+ return httpContext =>
90
+ {
91
+ return untargetedRequestDelegate ( null , httpContext ) ;
92
+ } ;
93
+ }
94
+
95
+
96
+ /// <summary>
97
+ /// Builds a <see cref="RequestDelegate"/> implementation for <paramref name="methodInfo"/>.
98
+ /// </summary>
99
+ /// <param name="methodInfo">A request handler with any number of custom parameters that often produces a response with its return value.</param>
100
+ /// <param name="targetFactory">Creates the <see langword="this"/> for the non-static method. If the </param>
101
+ /// <returns>The <see cref="RequestDelegate"/></returns>
102
+ public static RequestDelegate BuildRequestDelegate ( MethodInfo methodInfo , Func < HttpContext , object > targetFactory )
103
+ {
104
+ if ( methodInfo is null )
105
+ {
106
+ throw new ArgumentNullException ( nameof ( methodInfo ) ) ;
107
+ }
108
+
109
+ if ( targetFactory is null )
110
+ {
111
+ throw new ArgumentNullException ( nameof ( targetFactory ) ) ;
112
+ }
113
+
114
+ if ( methodInfo . DeclaringType is null )
115
+ {
116
+ throw new ArgumentException ( $ "A { nameof ( targetFactory ) } was provided, but { nameof ( methodInfo ) } does not have a Declaring type.") ;
117
+ }
118
+
119
+ var targetExpression = Expression . Convert ( TargetArg , methodInfo . DeclaringType ) ;
120
+ var untargetedRequestDelegate = BuildRequestDelegate ( methodInfo , targetExpression ) ;
121
+
122
+ return httpContext =>
123
+ {
124
+ return untargetedRequestDelegate ( targetFactory ( httpContext ) , httpContext ) ;
125
+ } ;
126
+ }
127
+
128
+ private static Func < object ? , HttpContext , Task > BuildRequestDelegate ( MethodInfo methodInfo , Expression ? targetExpression )
55
129
{
56
130
// Non void return type
57
131
@@ -69,8 +143,6 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
69
143
// return default;
70
144
// }
71
145
72
- var method = action . Method ;
73
-
74
146
var consumeBodyDirectly = false ;
75
147
var consumeBodyAsForm = false ;
76
148
Type ? bodyType = null ;
@@ -79,7 +151,7 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
79
151
// This argument represents the deserialized body returned from IHttpRequestReader
80
152
// when the method has a FromBody attribute declared
81
153
82
- var methodParameters = method . GetParameters ( ) ;
154
+ var methodParameters = methodInfo . GetParameters ( ) ;
83
155
var args = new List < Expression > ( methodParameters . Length ) ;
84
156
85
157
foreach ( var parameter in methodParameters )
@@ -163,18 +235,17 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
163
235
164
236
MethodCallExpression methodCall ;
165
237
166
- if ( action . Target is null )
238
+ if ( targetExpression is null )
167
239
{
168
- methodCall = Expression . Call ( method , args ) ;
240
+ methodCall = Expression . Call ( methodInfo , args ) ;
169
241
}
170
242
else
171
243
{
172
- var castedTarget = Expression . Convert ( TargetArg , action . Target . GetType ( ) ) ;
173
- methodCall = Expression . Call ( castedTarget , method , args ) ;
244
+ methodCall = Expression . Call ( targetExpression , methodInfo , args ) ;
174
245
}
175
246
176
247
// Exact request delegate match
177
- if ( method . ReturnType == typeof ( void ) )
248
+ if ( methodInfo . ReturnType == typeof ( void ) )
178
249
{
179
250
var bodyExpressions = new List < Expression >
180
251
{
@@ -184,22 +255,22 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
184
255
185
256
body = Expression . Block ( bodyExpressions ) ;
186
257
}
187
- else if ( AwaitableInfo . IsTypeAwaitable ( method . ReturnType , out var info ) )
258
+ else if ( AwaitableInfo . IsTypeAwaitable ( methodInfo . ReturnType , out var info ) )
188
259
{
189
- if ( method . ReturnType == typeof ( Task ) )
260
+ if ( methodInfo . ReturnType == typeof ( Task ) )
190
261
{
191
262
body = methodCall ;
192
263
}
193
- else if ( method . ReturnType == typeof ( ValueTask ) )
264
+ else if ( methodInfo . ReturnType == typeof ( ValueTask ) )
194
265
{
195
266
body = Expression . Call (
196
267
ExecuteValueTaskMethodInfo ,
197
268
methodCall ) ;
198
269
}
199
- else if ( method . ReturnType . IsGenericType &&
200
- method . ReturnType . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
270
+ else if ( methodInfo . ReturnType . IsGenericType &&
271
+ methodInfo . ReturnType . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
201
272
{
202
- var typeArg = method . ReturnType . GetGenericArguments ( ) [ 0 ] ;
273
+ var typeArg = methodInfo . ReturnType . GetGenericArguments ( ) [ 0 ] ;
203
274
204
275
if ( typeof ( IResult ) . IsAssignableFrom ( typeArg ) )
205
276
{
@@ -227,10 +298,10 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
227
298
}
228
299
}
229
300
}
230
- else if ( method . ReturnType . IsGenericType &&
231
- method . ReturnType . GetGenericTypeDefinition ( ) == typeof ( ValueTask < > ) )
301
+ else if ( methodInfo . ReturnType . IsGenericType &&
302
+ methodInfo . ReturnType . GetGenericTypeDefinition ( ) == typeof ( ValueTask < > ) )
232
303
{
233
- var typeArg = method . ReturnType . GetGenericArguments ( ) [ 0 ] ;
304
+ var typeArg = methodInfo . ReturnType . GetGenericArguments ( ) [ 0 ] ;
234
305
235
306
if ( typeof ( IResult ) . IsAssignableFrom ( typeArg ) )
236
307
{
@@ -261,18 +332,18 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
261
332
else
262
333
{
263
334
// TODO: Handle custom awaitables
264
- throw new NotSupportedException ( $ "Unsupported return type: { method . ReturnType } ") ;
335
+ throw new NotSupportedException ( $ "Unsupported return type: { methodInfo . ReturnType } ") ;
265
336
}
266
337
}
267
- else if ( typeof ( IResult ) . IsAssignableFrom ( method . ReturnType ) )
338
+ else if ( typeof ( IResult ) . IsAssignableFrom ( methodInfo . ReturnType ) )
268
339
{
269
340
body = Expression . Call ( methodCall , ResultWriteResponseAsync , HttpContextParameter ) ;
270
341
}
271
- else if ( method . ReturnType == typeof ( string ) )
342
+ else if ( methodInfo . ReturnType == typeof ( string ) )
272
343
{
273
344
body = Expression . Call ( StringResultWriteResponseAsync , HttpResponseExpr , methodCall , Expression . Constant ( CancellationToken . None ) ) ;
274
345
}
275
- else if ( method . ReturnType . IsValueType )
346
+ else if ( methodInfo . ReturnType . IsValueType )
276
347
{
277
348
var box = Expression . TypeAs ( methodCall , typeof ( object ) ) ;
278
349
body = Expression . Call ( JsonResultWriteResponseAsync , HttpResponseExpr , box , Expression . Constant ( CancellationToken . None ) ) ;
@@ -364,10 +435,7 @@ public static RequestDelegate BuildRequestDelegate(Delegate action)
364
435
requestDelegate = invoker ;
365
436
}
366
437
367
- return httpContext =>
368
- {
369
- return requestDelegate ( action . Target , httpContext ) ;
370
- } ;
438
+ return requestDelegate ;
371
439
}
372
440
373
441
private static ILogger GetLogger ( HttpContext httpContext )
0 commit comments