WebApiEngine.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Reflection;
  7. using System.Text.Json;
  8. using System.Text.Json.Serialization;
  9. using Vinno.FIS.Sonopost.Helpers;
  10. using Vinno.FIS.Sonopost.WebApi.Models;
  11. using Vinno.IUS.Common.Log;
  12. namespace Vinno.FIS.Sonopost.WebApi
  13. {
  14. internal class WebApiEngine
  15. {
  16. private static readonly int CONTROLLER_STR_LEN = "Controller".Length;
  17. private readonly ConcurrentDictionary<string, Type> _controllerReference;
  18. public const string ROUTE_PREFIX = "/api/";
  19. internal WebApiEngine()
  20. {
  21. _controllerReference = new ConcurrentDictionary<string, Type>();
  22. Register();
  23. }
  24. private void Register()
  25. {
  26. Assembly assembly = GetType().Assembly;
  27. Type baseControllerType = typeof(BaseController);
  28. Type[] types = assembly.GetTypes()
  29. .Where(x => baseControllerType.IsAssignableFrom(x) && x != baseControllerType)
  30. .ToArray();
  31. foreach (Type type in types)
  32. {
  33. object[] attrs = type.GetCustomAttributes(typeof(WebApiControllerAttribute), false);
  34. if (attrs.Length == 0) continue;
  35. WebApiControllerAttribute attr = (WebApiControllerAttribute)attrs[0];
  36. string controllerName = attr.Name;
  37. if (string.IsNullOrWhiteSpace(controllerName))
  38. {
  39. controllerName = type.Name.Substring(0, type.Name.Length - CONTROLLER_STR_LEN);
  40. }
  41. string key = controllerName.ToLower();
  42. if (!_controllerReference.ContainsKey(key))
  43. {
  44. _controllerReference.TryAdd(key, type);
  45. }
  46. }
  47. }
  48. /// <summary>
  49. /// Handle Api Request
  50. /// </summary>
  51. /// <param name="route"></param>
  52. /// <param name="requestJson"></param>
  53. /// <returns>Response Json String</returns>
  54. public string Handle(string route, string requestJson, HttpListenerContext context)
  55. {
  56. string[] routeSplits = route.Split('/');
  57. string controllerName = routeSplits[0];
  58. string actionName = routeSplits[1];
  59. if (!_controllerReference.ContainsKey(controllerName))
  60. {
  61. return null;
  62. }
  63. Assembly assembly = GetType().Assembly;
  64. Type classType = _controllerReference[controllerName];
  65. BaseController instance = (BaseController)assembly.CreateInstance(classType.FullName);
  66. IEnumerable<FieldInfo> baseFieldInfos = classType.BaseType.GetRuntimeFields();
  67. foreach (FieldInfo fieldInfo in baseFieldInfos)
  68. {
  69. if (fieldInfo.FieldType.Equals(context.GetType()))
  70. {
  71. fieldInfo.SetValue(instance, context);
  72. }
  73. }
  74. MethodInfo[] methodInfos = classType.GetMethods();
  75. foreach (MethodInfo methodInfo in methodInfos)
  76. {
  77. if (!methodInfo.IsPublic) continue;
  78. if (methodInfo.IsConstructor || methodInfo.IsStatic || methodInfo.IsVirtual || methodInfo.IsAbstract) continue;
  79. object[] attrs = methodInfo.GetCustomAttributes(typeof(WebApiActionAttribute), false);
  80. if (attrs.Length == 0) continue;
  81. WebApiActionAttribute attr = (WebApiActionAttribute)attrs[0];
  82. string attrActionName = string.IsNullOrWhiteSpace(attr.Name) ? methodInfo.Name : attr.Name;
  83. if (!actionName.Equals(attrActionName.ToLowerInvariant())) continue;
  84. object[] parameters = null;
  85. try
  86. {
  87. ParameterInfo[] parameterInfos = methodInfo.GetParameters();
  88. if (parameterInfos.Length > 0)
  89. {
  90. var parameter = JsonHelper.JsonToObj(requestJson, parameterInfos[0].ParameterType, new JsonSerializerOptions
  91. {
  92. NumberHandling = JsonNumberHandling.AllowReadingFromString
  93. });
  94. parameters = new object[] { parameter };
  95. }
  96. object result = methodInfo.Invoke(instance, parameters);
  97. return JsonHelper.ToJson(result, new JsonSerializerOptions
  98. {
  99. NumberHandling = JsonNumberHandling.WriteAsString,
  100. DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
  101. });
  102. }
  103. catch (Exception ex)
  104. {
  105. Logger.WriteLineError($"[{nameof(WebApiEngine)}]{nameof(Handle)} error: {ex}");
  106. return Result.Fail("RequestError").ToJson();
  107. }
  108. }
  109. return null;
  110. }
  111. }
  112. }