123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection.Emit;
- using MiniWebApi.Network;
- namespace MiniWebApi.Handler
- {
- public class BaseHandler
- {
- private readonly Dictionary<string, CallingMethod> _callingMethods = new Dictionary<string, CallingMethod>();
- public BaseHandler()
- {
- RegisterCallingMethods();
- }
- private void RegisterCallingMethods()
- {
-
- var methods = GetType().GetMethods();
- foreach (var method in methods.Where(x => x.IsVirtual == false && x.IsStatic == false && x.ReturnType == typeof(void)))
- {
-
- var methodWebApiAttrs = method.GetCustomAttributes(typeof(WebApiMethodAttribute), true);
- if (methodWebApiAttrs.Length == 0)
- {
-
- continue;
- }
- if (methodWebApiAttrs.Length >1)
- {
-
- throw new InvalidOperationException($"Method {method.Name} defined more than one WebApi method attributes.");
- }
- if (!method.IsPublic)
- {
-
- throw new InvalidOperationException($"Method {method.Name} should be public for WebApi method.");
- }
- var webApiMethodAttribute = (WebApiMethodAttribute)methodWebApiAttrs[0];
- var methodWebApiType = webApiMethodAttribute.ToWebApiType();
- var methodName = string.IsNullOrWhiteSpace(webApiMethodAttribute.Name)
- ? method.Name
- : webApiMethodAttribute.Name;
-
- var parameters = method.GetParameters();
-
- if (parameters[0].ParameterType != typeof(WebApiHttpContext))
- {
- throw new InvalidDataException($"The first argument of method {method.Name} must be WebApiHttpContext");
- }
-
- var paramInfos = new List<CallingParameter>();
- foreach (var parameterInfo in parameters)
- {
- if (parameterInfo.ParameterType == typeof(WebApiHttpContext))
- {
- continue;
- }
- var fromType = FromType.None;
-
- var paramWebApiAttrs = parameterInfo.GetCustomAttributes(typeof(WebApiParameterAttribute), true);
- if (paramWebApiAttrs.Length > 0)
- {
- if (paramWebApiAttrs[0] is FromUrlAttribute)
- {
- fromType = FromType.FromUrl;
- }
- else if (paramWebApiAttrs[0] is FromBodyAttribute)
- {
- fromType = FromType.FromBody;
- }
- }
- paramInfos.Add(new CallingParameter(parameterInfo.Name, parameterInfo.ParameterType, fromType));
- }
-
- if (paramInfos.Count(x => x.FromType == FromType.FromUrl) > 1)
- {
- throw new InvalidOperationException($"Method {method.Name} defined more than one [FromUrl] parameters.");
- }
-
- if (paramInfos.Count(x => x.FromType == FromType.FromBody) > 1)
- {
- throw new InvalidOperationException($"Method {method.Name} defined more than one [FromBody] parameters.");
- }
-
- if (paramInfos.Any(x => x.FromType == FromType.FromUrl) && paramInfos.Any(x=>x.FromType == FromType.None))
- {
- throw new InvalidOperationException($"Only one [FromUrl] parameter can be define in Method {method.Name} without any other parameters.");
- }
-
- if (methodWebApiType == WebApiType.Get && paramInfos.Any(x => x.FromType == FromType.FromBody))
- {
- throw new InvalidOperationException($"Get method {method.Name} can not contains [FromBody] parameter.");
- }
-
- var dynamicMethod = new DynamicMethod("", null, new[] { typeof(object), typeof(object[]) }, GetType().Module);
- var il = dynamicMethod.GetILGenerator();
-
- il.Emit(OpCodes.Ldarg_S, 0);
-
- il.Emit(OpCodes.Castclass, GetType());
-
- il.Emit(OpCodes.Ldarg_S, 1);
-
- il.Emit(OpCodes.Ldc_I4_S, 0);
-
- il.Emit(OpCodes.Ldelem_Ref);
-
- il.Emit(OpCodes.Castclass, typeof(WebApiHttpContext));
-
- for (var i = 0; i < paramInfos.Count; i++)
- {
- var parameterInfo = paramInfos[i];
-
- il.Emit(OpCodes.Ldarg_S, 1);
-
- il.Emit(OpCodes.Ldc_I4_S, i+1);
-
- il.Emit(OpCodes.Ldelem_Ref);
-
- il.Emit(parameterInfo.ParameterType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, parameterInfo.ParameterType);
- }
-
- il.Emit(OpCodes.Call, method);
-
- il.Emit(OpCodes.Ret);
-
- var action = (Action<object, object[]>)dynamicMethod.CreateDelegate(typeof(Action<object, object[]>));
- var callingMethod = new CallingMethod(methodName.ToLower(), methodWebApiType, paramInfos, this, new WebApiMethod(action));
- _callingMethods.Add(callingMethod.Name, callingMethod);
- }
- }
-
-
-
-
-
- public CallingMethod GetCallingMethod(string name)
- {
- return !_callingMethods.ContainsKey(name) ? null : _callingMethods[name];
- }
-
-
-
-
- public CallingMethod[] GetCallingMethods()
- {
- return _callingMethods.Values.ToArray();
- }
- }
- }
|