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.

163 lines
4.9 KiB

using System;
using System.Collections.Generic;
using System.Reflection;
namespace Apewer.Web
{
/// <summary></summary>
public sealed class ApiFunction : IToJson
{
#region fields
ApiApplication _application = null;
MethodInfo _method = null;
Type _return = null;
ApiParameter[] _parameters = null;
string _name = null;
string _lower = null;
string _caption = null;
string _description = null;
bool _hidden = false;
#endregion
#region properties
/// <summary></summary>
public ApiApplication Application { get => _application; }
/// <summary>方法。</summary>
public MethodInfo Method { get => _method; }
/// <summary>参数。</summary>
public ApiParameter[] Parameters { get => _parameters.Map(x => x); }
/// <summary>返回的类型。</summary>
public Type ReturnType { get => _return; }
/// <summary></summary>
public string Name { get => _name; }
/// <summary></summary>
public string Caption { get => _caption; }
/// <summary></summary>
public string Description { get => _description; }
/// <summary></summary>
public bool Hidden { get => _hidden; }
#endregion
/// <summary></summary>
public Json ToJson() => ToJson(true);
/// <summary></summary>
public Json ToJson(ApiOptions options) => ToJson((options ?? new ApiOptions()).WithParameters);
/// <summary></summary>
public Json ToJson(bool withParameters)
{
if (Hidden) return null;
var json = Json.NewObject();
json.SetProperty("name", Name);
if (!string.IsNullOrEmpty(Caption)) json.SetProperty("caption", Caption);
if (!string.IsNullOrEmpty(Description)) json.SetProperty("description", Description);
if (withParameters) json.SetProperty("parameters", Json.From(_parameters));
return json;
}
ApiFunction(MethodInfo method, ApiApplication application, ApiParameter[] parameters)
{
// 检查 ApiAttribute 特性。
var apis = method.GetCustomAttributes(typeof(ApiAttribute), false);
var api = apis.Length > 0 ? (ApiAttribute)apis[0] : null;
// Entry
_application = application;
_method = method;
// 返回值。
_return = method.ReturnType;
if (_return.Equals(typeof(void))) _return = null;
// api
if (api == null)
{
_name = method?.Name;
_lower = _name?.Lower();
}
else
{
_name = string.IsNullOrEmpty(api.Name) ? method?.Name : api.Name;
_lower = _name?.Lower();
_caption = api.Caption;
_description = api.Description;
}
// caption
if (string.IsNullOrEmpty(_caption))
{
var captions = method.GetCustomAttributes(typeof(CaptionAttribute), true);
if (captions.Length > 0)
{
var caption = (CaptionAttribute)captions[0];
_caption = caption.Title;
if (string.IsNullOrEmpty(_description))
{
_description = caption.Description;
}
}
}
// hidden
if (method.Contains<HiddenAttribute>(false)) _hidden = true;
// 参数。
_parameters = parameters;
}
/// <summary></summary>
public static ApiFunction Parse(ApiApplication application, MethodInfo method)
{
if (application == null) return null;
if (method == null) return null;
// 滤除构造函数、抽象方法、泛型和非本类定义方法。
if (method.IsConstructor) return null;
if (method.IsAbstract) return null;
if (method.GetGenericArguments().NotEmpty()) return null;
// 滤除 get 和 set 访问器。
var methodName = method.Name;
if (methodName.StartsWith("get_") || methodName.StartsWith("set_")) return null;
switch (methodName)
{
case "Dispose":
return null;
}
// 定义者。
var declaring = method.DeclaringType;
if (declaring.Equals(typeof(object))) return null;
// 参数,所有参数必须是 In 方向。
var ps = new List<ApiParameter>();
foreach (var pi in method.GetParameters())
{
var p = ApiParameter.Parse(pi);
if (p == null) return null;
ps.Add(p);
}
return new ApiFunction(method, application, ps.ToArray());
}
}
}