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

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;
}
}
}