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
200 lines
7.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
|
|
namespace Apewer.Web
|
|
{
|
|
|
|
/// <summary>API 入口。</summary>
|
|
[Serializable]
|
|
public sealed class ApiEntry : IToJson
|
|
{
|
|
|
|
#region Reflection
|
|
|
|
internal Assembly _assembly = null;
|
|
internal Module _module = null;
|
|
internal Type _type = null;
|
|
internal MethodInfo _method = null;
|
|
|
|
/// <summary>定义当前入口的程序集。</summary>
|
|
public Assembly Assembly { get => _assembly; }
|
|
|
|
/// <summary>定义当前入口的模块。</summary>
|
|
public Module Module { get => _module; }
|
|
|
|
/// <summary>定义当前入口的类型。</summary>
|
|
public Type Type { get => _type; }
|
|
|
|
/// <summary>定义当前入口的方法。</summary>
|
|
public MethodInfo Method { get => _method; }
|
|
|
|
#endregion
|
|
|
|
#region Define
|
|
|
|
internal CaptionAttribute _caption = null;
|
|
internal HiddenAttribute _hidden = null;
|
|
|
|
internal RoutePrefixAttribute _prefix = null;
|
|
internal RouteAttribute _route = null;
|
|
internal string _path = null;
|
|
internal string _lower = null;
|
|
|
|
/// <summary>当前入口的路由前缀。</summary>
|
|
public RoutePrefixAttribute RoutePrefix { get => _prefix; }
|
|
|
|
/// <summary>当前入口的路由。</summary>
|
|
public RouteAttribute Route { get => _route; }
|
|
|
|
/// <summary>当前入口的标题。</summary>
|
|
public CaptionAttribute Caption { get => _caption; }
|
|
|
|
/// <summary>当前入口的路由路径。</summary>
|
|
public string Path { get => _path; }
|
|
|
|
#endregion
|
|
|
|
#region HTTP Method
|
|
|
|
internal bool _restricted = false;
|
|
internal HttpConnectAttribute _connect = null;
|
|
internal HttpDeleteAttribute _delete = null;
|
|
internal HttpGetAttribute _get = null;
|
|
internal HttpHeadAttribute _head = null;
|
|
internal HttpOptionsAttribute _options = null;
|
|
internal HttpPatchAttribute _patch = null;
|
|
internal HttpPostAttribute _post = null;
|
|
internal HttpPutAttribute _put = null;
|
|
internal HttpTraceAttribute _trace = null;
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpConnectAttribute"/> 特性。</summary>
|
|
public HttpConnectAttribute Connect { get => _connect; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpDeleteAttribute"/> 特性。</summary>
|
|
public HttpDeleteAttribute Delete { get => _delete; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpGetAttribute"/> 特性。</summary>
|
|
public HttpGetAttribute Get { get => _get; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpHeadAttribute"/> 特性。</summary>
|
|
public HttpHeadAttribute Head { get => _head; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpOptionsAttribute"/> 特性。</summary>
|
|
public HttpOptionsAttribute Options { get => _options; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpPatchAttribute"/> 特性。</summary>
|
|
public HttpPatchAttribute Patch { get => _patch; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpPostAttribute"/> 特性。</summary>
|
|
public HttpPostAttribute Post { get => _post; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpPutAttribute"/> 特性。</summary>
|
|
public HttpPutAttribute Put { get => _put; }
|
|
|
|
/// <summary>当前入口拥有 <see cref="HttpTraceAttribute"/> 特性。</summary>
|
|
public HttpTraceAttribute Trace { get => _trace; }
|
|
|
|
#endregion
|
|
|
|
private ApiEntry() { }
|
|
|
|
internal static ApiEntry[] Parse(Type type)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
internal static ApiEntry Parse(Type type, MethodInfo method, RoutePrefixAttribute prefix, bool typeIndependent)
|
|
{
|
|
if (type == null) return null;
|
|
if (method == null) return null;
|
|
if (!method.IsPublic) return null;
|
|
if (method.IsGenericMethod) return null;
|
|
if (method.IsStatic) return null;
|
|
|
|
var route = RuntimeUtility.GetAttribute<RouteAttribute>(method, false);
|
|
var path = route == null ? null : Concat(prefix, route);
|
|
var lower = path == null ? null : path.ToLower();
|
|
|
|
var entry = new ApiEntry();
|
|
|
|
entry._assembly = type.Assembly;
|
|
entry._module = type.Module;
|
|
entry._type = type;
|
|
entry._method = method;
|
|
|
|
entry._caption = RuntimeUtility.GetAttribute<CaptionAttribute>(method, true);
|
|
entry._hidden = RuntimeUtility.GetAttribute<HiddenAttribute>(method, true);
|
|
|
|
entry._prefix = prefix;
|
|
entry._route = route;
|
|
entry._path = path;
|
|
entry._lower = lower;
|
|
|
|
// 允许的 HTTP 方法,指定任何方法即表示需要限定方法。
|
|
entry._connect = RuntimeUtility.GetAttribute<HttpConnectAttribute>(method, false);
|
|
entry._delete = RuntimeUtility.GetAttribute<HttpDeleteAttribute>(method, false);
|
|
entry._get = RuntimeUtility.GetAttribute<HttpGetAttribute>(method, false);
|
|
entry._head = RuntimeUtility.GetAttribute<HttpHeadAttribute>(method, false);
|
|
entry._options = RuntimeUtility.GetAttribute<HttpOptionsAttribute>(method, false);
|
|
entry._patch = RuntimeUtility.GetAttribute<HttpPatchAttribute>(method, false);
|
|
entry._post = RuntimeUtility.GetAttribute<HttpPostAttribute>(method, false);
|
|
entry._put = RuntimeUtility.GetAttribute<HttpPutAttribute>(method, false);
|
|
entry._trace = RuntimeUtility.GetAttribute<HttpTraceAttribute>(method, false);
|
|
if (entry._get != null) entry._restricted = true;
|
|
else if (entry._post != null) entry._restricted = true;
|
|
else if (entry._options != null) entry._restricted = true;
|
|
else if (entry._connect != null) entry._restricted = true;
|
|
else if (entry._delete != null) entry._restricted = true;
|
|
else if (entry._head != null) entry._restricted = true;
|
|
else if (entry._patch != null) entry._restricted = true;
|
|
else if (entry._put != null) entry._restricted = true;
|
|
else if (entry._trace != null) entry._restricted = true;
|
|
|
|
return entry;
|
|
}
|
|
|
|
static string Concat(RoutePrefixAttribute prefix, RouteAttribute route)
|
|
{
|
|
var segs = new List<string>(16);
|
|
|
|
if (prefix != null && !string.IsNullOrEmpty(prefix.Path))
|
|
{
|
|
var split = prefix.Path.Split('/');
|
|
var count = split.Length;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var seg = split[i];
|
|
if (string.IsNullOrEmpty(seg)) continue;
|
|
segs.Add(seg);
|
|
}
|
|
}
|
|
|
|
if (route != null && !string.IsNullOrEmpty(route.Path))
|
|
{
|
|
var split = route.Path.Split('/');
|
|
var count = split.Length;
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var seg = split[i];
|
|
if (string.IsNullOrEmpty(seg)) continue;
|
|
segs.Add(seg);
|
|
}
|
|
}
|
|
|
|
if (segs.Count < 1) return "/";
|
|
return "/" + TextUtility.Join("/", segs.ToArray());
|
|
}
|
|
|
|
/// <summary>生成包含当前实例属性的 Json 对象。</summary>
|
|
/// <returns>Json 对象。</returns>
|
|
public Json ToJson()
|
|
{
|
|
var json = Json.NewObject();
|
|
return json;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|