1
- using System . Collections . Concurrent ;
1
+ using System . Data ;
2
2
using System . Net ;
3
- using System . Net ;
3
+ using System . Reflection ;
4
4
using System . Text ;
5
- using Tigernet . Hosting . Actions ;
6
- using Tigernet . Hosting . Attributes ;
7
5
using Tigernet . Hosting . Attributes . Commons ;
6
+ using Tigernet . Hosting . Attributes . HttpMethods ;
7
+ using Tigernet . Hosting . Attributes . Resters ;
8
8
using Tigernet . Hosting . Exceptions ;
9
9
10
10
namespace Tigernet . Hosting
@@ -125,86 +125,126 @@ private async Task HandleRequestAsync(HttpListenerContext context)
125
125
response . Close ( ) ;
126
126
}
127
127
}
128
- /// <summary>
129
- /// Maps the REST API endpoint for the given route and ResterBase implementation.
130
- /// The methods decorated with the GetterAttribute are extracted and mapped to their corresponding route URL
131
- /// The response is returned in JSON format.
132
- /// </summary>
133
- /// <typeparam name="T">The type of the ResterBase implementations</typeparam>
134
- /// <param name="route">The base route URL for the REST API endpoints</param>
135
- public void MapRester < T > ( string route = null ) where T : ResterBase
128
+
129
+ /// <summary>
130
+ /// Using middleware
131
+ /// </summary>
132
+ /// <param name="middleware"></param>
133
+ /// <returns></returns>
134
+ public TigernetHostBuilder UseAsync ( Func < HttpListenerContext , Task > middleware )
135
+ {
136
+ _middlewares . Add ( middleware ) ;
137
+
138
+ return this ;
139
+ }
140
+
141
+ public void MapResters ( )
142
+ {
143
+ // get the assembly that is using this library
144
+ var assembly = Assembly . GetCallingAssembly ( ) ;
145
+
146
+ // get all types in the assembly
147
+ var types = assembly . GetTypes ( ) ;
148
+
149
+ // filter for types that have the ApiRester attribute
150
+ var resterTypes = types . Where ( t => t . GetCustomAttribute < ApiResterAttribute > ( ) != null ) ;
151
+
152
+ foreach ( var resterType in resterTypes )
136
153
{
137
- T rester ;
138
- var type = typeof ( T ) ;
139
- var constructor = type . GetConstructors ( ) [ 0 ] ;
140
- var parameters = constructor . GetParameters ( ) ;
141
- if ( parameters . Length == 0 )
154
+ var methods = resterType . GetMethods ( BindingFlags . Public | BindingFlags . Instance )
155
+ . Where ( m => m . GetCustomAttribute < GetterAttribute > ( ) != null || m . GetCustomAttribute < PosterAttribute > ( ) != null ) ;
156
+
157
+ var typeName = resterType . Name ;
158
+
159
+ foreach ( var method in methods )
142
160
{
143
- rester = ( T ) Activator . CreateInstance ( type ) ;
161
+ var getterAttr = method . GetCustomAttribute < GetterAttribute > ( ) ;
162
+ var posterAttr = method . GetCustomAttribute < PosterAttribute > ( ) ;
163
+
164
+ var endpointAttr = getterAttr != null ? getterAttr : ( HttpMethodAttribute ) posterAttr ;
165
+
166
+ var route = Path . Combine ( "/" , typeName . Split ( new [ ] { "Rester" } ,
167
+ StringSplitOptions . None ) . FirstOrDefault ( ) ) ;
168
+
169
+ var routeUrl = ( route + endpointAttr . route ) . ToLower ( ) ;
170
+
171
+ var handler = CreateHandlerFunc ( resterType , method ) ;
172
+
173
+ MapRoute ( routeUrl , handler ) ;
144
174
}
175
+ }
176
+ }
145
177
146
- else
178
+ private Func < HttpListenerContext , Task > CreateHandlerFunc ( Type resterType , MethodInfo method )
179
+ {
180
+ return async context =>
181
+ {
182
+ object rester ;
183
+ var constructor = resterType . GetConstructors ( ) . FirstOrDefault ( ) ;
184
+
185
+ if ( constructor != null )
147
186
{
187
+ var parameters = constructor . GetParameters ( ) ;
148
188
var parameterInstances = new object [ parameters . Length ] ;
189
+
149
190
for ( var i = 0 ; i < parameters . Length ; i ++ )
150
191
{
151
- parameterInstances [ i ] = GetService ( parameters [ i ] . ParameterType ) ;
192
+ var parameterType = parameters [ i ] . ParameterType ;
193
+ var service = GetService ( parameterType ) ;
194
+ if ( service != null )
195
+ {
196
+ parameterInstances [ i ] = service ;
197
+ }
198
+ else
199
+ {
200
+ throw new Exception ( $ "Unable to resolve service of type { parameterType } for constructor of { resterType } .") ;
201
+ }
152
202
}
153
203
154
- rester = ( T ) constructor . Invoke ( parameterInstances ) ;
204
+ rester = constructor . Invoke ( parameterInstances ) ;
155
205
}
156
- var typeName = type . Name ;
157
- var methods = type . GetMethods ( ) ;
158
- foreach ( var method in methods )
206
+ else
159
207
{
160
- var attributes = method . GetCustomAttributes ( typeof ( HttpMethodAttribute ) , false ) ;
161
- if ( attributes . Length > 0 )
162
- {
163
- var attribute = attributes [ 0 ] as HttpMethodAttribute ;
208
+ rester = Activator . CreateInstance ( resterType ) ;
209
+ }
164
210
165
- // if route is null, use the route from the class name
166
- if ( string . IsNullOrEmpty ( route ) )
167
- {
168
- route = Path . Combine ( "/" , typeName . Split ( new [ ] { "Rester" } ,
169
- StringSplitOptions . None ) . FirstOrDefault ( ) ) ;
170
- }
211
+ var args = GetArguments ( method , context ) ;
212
+ var result = method . Invoke ( rester , args ) ;
171
213
172
- var routeUrl = ( route + attribute . route ) . ToLower ( ) ;
173
- MapRoute ( routeUrl , async context =>
174
- {
175
- var response = context . Response ;
176
- response . ContentType = "application/json" ;
177
-
178
- if ( context . Request . HttpMethod == attribute . HttpMethodName )
179
- {
180
- var result = method . Invoke ( rester , null ) ;
181
- var content = Encoding . UTF8 . GetBytes ( result . ToString ( ) ) ;
182
- response . ContentLength64 = content . Length ;
183
- using ( var output = response . OutputStream )
184
- {
185
- await output . WriteAsync ( content , 0 , content . Length ) ;
186
- }
187
- }
188
- else
189
- {
190
- response . StatusCode = ( int ) HttpStatusCode . NotFound ;
191
- response . Close ( ) ;
192
- }
193
- } ) ;
194
- }
214
+ if ( result is Task task )
215
+ {
216
+ await task ;
195
217
}
196
- }
197
218
198
- /// <summary>
199
- /// Using middleware
200
- /// </summary>
201
- /// <param name="middleware"></param>
202
- /// <returns></returns>
203
- public TigernetHostBuilder UseAsync ( Func < HttpListenerContext , Task > middleware )
204
- {
205
- _middlewares . Add ( middleware ) ;
219
+ var response = context . Response ;
220
+ var content = Encoding . UTF8 . GetBytes ( result . ToString ( ) ) ;
221
+ response . ContentLength64 = content . Length ;
222
+ using ( var output = response . OutputStream )
223
+ {
224
+ await output . WriteAsync ( content , 0 , content . Length ) ;
225
+ }
226
+ } ;
227
+ }
206
228
207
- return this ;
229
+ private object [ ] GetArguments ( MethodInfo method , HttpListenerContext context )
230
+ {
231
+ var parameters = method . GetParameters ( ) ;
232
+ var args = new object [ parameters . Length ] ;
233
+
234
+ for ( int i = 0 ; i < parameters . Length ; i ++ )
235
+ {
236
+ var parameterType = parameters [ i ] . ParameterType ;
237
+ if ( parameterType == typeof ( HttpListenerContext ) )
238
+ {
239
+ args [ i ] = context ;
240
+ }
241
+ else
242
+ {
243
+ args [ i ] = null ;
244
+ }
208
245
}
246
+
247
+ return args ;
209
248
}
249
+ }
210
250
}
0 commit comments