You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
7.5 KiB

3 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Text;
  5. namespace Apewer.Web
  6. {
  7. /// <summary>API 入口。</summary>
  8. [Serializable]
  9. public sealed class ApiEntry : IToJson
  10. {
  11. #region Reflection
  12. internal Assembly _assembly = null;
  13. internal Module _module = null;
  14. internal Type _type = null;
  15. internal MethodInfo _method = null;
  16. /// <summary>定义当前入口的程序集。</summary>
  17. public Assembly Assembly { get => _assembly; }
  18. /// <summary>定义当前入口的模块。</summary>
  19. public Module Module { get => _module; }
  20. /// <summary>定义当前入口的类型。</summary>
  21. public Type Type { get => _type; }
  22. /// <summary>定义当前入口的方法。</summary>
  23. public MethodInfo Method { get => _method; }
  24. #endregion
  25. #region Define
  26. internal CaptionAttribute _caption = null;
  27. internal HiddenAttribute _hidden = null;
  28. internal RoutePrefixAttribute _prefix = null;
  29. internal RouteAttribute _route = null;
  30. internal string _path = null;
  31. internal string _lower = null;
  32. /// <summary>当前入口的路由前缀。</summary>
  33. public RoutePrefixAttribute RoutePrefix { get => _prefix; }
  34. /// <summary>当前入口的路由。</summary>
  35. public RouteAttribute Route { get => _route; }
  36. /// <summary>当前入口的标题。</summary>
  37. public CaptionAttribute Caption { get => _caption; }
  38. /// <summary>当前入口的路由路径。</summary>
  39. public string Path { get => _path; }
  40. #endregion
  41. #region HTTP Method
  42. internal bool _restricted = false;
  43. internal HttpConnectAttribute _connect = null;
  44. internal HttpDeleteAttribute _delete = null;
  45. internal HttpGetAttribute _get = null;
  46. internal HttpHeadAttribute _head = null;
  47. internal HttpOptionsAttribute _options = null;
  48. internal HttpPatchAttribute _patch = null;
  49. internal HttpPostAttribute _post = null;
  50. internal HttpPutAttribute _put = null;
  51. internal HttpTraceAttribute _trace = null;
  52. /// <summary>当前入口拥有 <see cref="HttpConnectAttribute"/> 特性。</summary>
  53. public HttpConnectAttribute Connect { get => _connect; }
  54. /// <summary>当前入口拥有 <see cref="HttpDeleteAttribute"/> 特性。</summary>
  55. public HttpDeleteAttribute Delete { get => _delete; }
  56. /// <summary>当前入口拥有 <see cref="HttpGetAttribute"/> 特性。</summary>
  57. public HttpGetAttribute Get { get => _get; }
  58. /// <summary>当前入口拥有 <see cref="HttpHeadAttribute"/> 特性。</summary>
  59. public HttpHeadAttribute Head { get => _head; }
  60. /// <summary>当前入口拥有 <see cref="HttpOptionsAttribute"/> 特性。</summary>
  61. public HttpOptionsAttribute Options { get => _options; }
  62. /// <summary>当前入口拥有 <see cref="HttpPatchAttribute"/> 特性。</summary>
  63. public HttpPatchAttribute Patch { get => _patch; }
  64. /// <summary>当前入口拥有 <see cref="HttpPostAttribute"/> 特性。</summary>
  65. public HttpPostAttribute Post { get => _post; }
  66. /// <summary>当前入口拥有 <see cref="HttpPutAttribute"/> 特性。</summary>
  67. public HttpPutAttribute Put { get => _put; }
  68. /// <summary>当前入口拥有 <see cref="HttpTraceAttribute"/> 特性。</summary>
  69. public HttpTraceAttribute Trace { get => _trace; }
  70. #endregion
  71. private ApiEntry() { }
  72. internal static ApiEntry[] Parse(Type type)
  73. {
  74. return null;
  75. }
  76. internal static ApiEntry Parse(Type type, MethodInfo method, RoutePrefixAttribute prefix, bool typeIndependent)
  77. {
  78. if (type == null) return null;
  79. if (method == null) return null;
  80. if (!method.IsPublic) return null;
  81. if (method.IsGenericMethod) return null;
  82. if (method.IsStatic) return null;
  83. var route = RuntimeUtility.GetAttribute<RouteAttribute>(method, false);
  84. var path = route == null ? null : Concat(prefix, route);
  85. var lower = path == null ? null : path.ToLower();
  86. var entry = new ApiEntry();
  87. entry._assembly = type.Assembly;
  88. entry._module = type.Module;
  89. entry._type = type;
  90. entry._method = method;
  91. entry._caption = RuntimeUtility.GetAttribute<CaptionAttribute>(method, true);
  92. entry._hidden = RuntimeUtility.GetAttribute<HiddenAttribute>(method, true);
  93. entry._prefix = prefix;
  94. entry._route = route;
  95. entry._path = path;
  96. entry._lower = lower;
  97. // 允许的 HTTP 方法,指定任何方法即表示需要限定方法。
  98. entry._connect = RuntimeUtility.GetAttribute<HttpConnectAttribute>(method, false);
  99. entry._delete = RuntimeUtility.GetAttribute<HttpDeleteAttribute>(method, false);
  100. entry._get = RuntimeUtility.GetAttribute<HttpGetAttribute>(method, false);
  101. entry._head = RuntimeUtility.GetAttribute<HttpHeadAttribute>(method, false);
  102. entry._options = RuntimeUtility.GetAttribute<HttpOptionsAttribute>(method, false);
  103. entry._patch = RuntimeUtility.GetAttribute<HttpPatchAttribute>(method, false);
  104. entry._post = RuntimeUtility.GetAttribute<HttpPostAttribute>(method, false);
  105. entry._put = RuntimeUtility.GetAttribute<HttpPutAttribute>(method, false);
  106. entry._trace = RuntimeUtility.GetAttribute<HttpTraceAttribute>(method, false);
  107. if (entry._get != null) entry._restricted = true;
  108. else if (entry._post != null) entry._restricted = true;
  109. else if (entry._options != null) entry._restricted = true;
  110. else if (entry._connect != null) entry._restricted = true;
  111. else if (entry._delete != null) entry._restricted = true;
  112. else if (entry._head != null) entry._restricted = true;
  113. else if (entry._patch != null) entry._restricted = true;
  114. else if (entry._put != null) entry._restricted = true;
  115. else if (entry._trace != null) entry._restricted = true;
  116. return entry;
  117. }
  118. static string Concat(RoutePrefixAttribute prefix, RouteAttribute route)
  119. {
  120. var segs = new List<string>(16);
  121. if (prefix != null && !string.IsNullOrEmpty(prefix.Path))
  122. {
  123. var split = prefix.Path.Split('/');
  124. var count = split.Length;
  125. for (var i = 0; i < count; i++)
  126. {
  127. var seg = split[i];
  128. if (string.IsNullOrEmpty(seg)) continue;
  129. segs.Add(seg);
  130. }
  131. }
  132. if (route != null && !string.IsNullOrEmpty(route.Path))
  133. {
  134. var split = route.Path.Split('/');
  135. var count = split.Length;
  136. for (var i = 0; i < count; i++)
  137. {
  138. var seg = split[i];
  139. if (string.IsNullOrEmpty(seg)) continue;
  140. segs.Add(seg);
  141. }
  142. }
  143. if (segs.Count < 1) return "/";
  144. return "/" + TextUtility.Join("/", segs.ToArray());
  145. }
  146. /// <summary>生成包含当前实例属性的 Json 对象。</summary>
  147. /// <returns>Json 对象。</returns>
  148. public Json ToJson()
  149. {
  150. var json = Json.NewObject();
  151. return json;
  152. }
  153. }
  154. }