using System; using System.Collections.Generic; using System.Reflection; namespace Apewer.Web { /// public sealed class ApiApplication : IToJson { #region fields Type _type = null; string _module = null; // ApiAttribute string _name = null; string _caption = null; string _description = null; // invoke & enumerate bool _independent = false; bool _hidden = false; // functions Dictionary _dict = new Dictionary(); List _list = new List(); #endregion #region properties /// public Type Type { get => _type; } /// public string Module { get => _module; } /// public string Name { get => _name; } /// public string Caption { get => _caption; } /// public string Description { get => _description; } /// public bool Independent { get => _independent; } /// public bool Hidden { get => _hidden; } /// public ApiFunction[] Functions { get => _list.ToArray(); } #endregion /// public ApiApplication(Type type, ApiAttribute api) { // type _type = type; // api if (api == null) { _name = type?.Name; } else { _name = string.IsNullOrEmpty(api.Name) ? type?.Name : api.Name; _caption = api.Caption; _description = api.Description; } if (type != null) { // caption if (string.IsNullOrEmpty(_caption)) { var captions = type.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 (type.Contains(false)) _hidden = true; // independent if (type.Contains(false)) _independent = true; // Module var assemblyName = type.Assembly.GetName(); _module = TextUtility.Join("-", assemblyName.Name, assemblyName.Version.ToString()); // functions var funcs = new Dictionary(); var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (var method in methods) { var func = ApiFunction.Parse(this, method); if (func == null) continue; var funcKey = func.Name.Lower(); if (funcs.ContainsKey(funcKey)) continue; funcs.Add(funcKey, func); } _dict = funcs; _list.AddRange(funcs.Values); _list.Sort(new Comparison((a, b) => a.Name.CompareTo(b.Name))); } } internal ApiFunction GetFunction(string name) { if (string.IsNullOrEmpty(name)) return null; if (_dict.TryGetValue(name.ToLower(), out var func)) return func; return null; } /// public Json ToJson() => ToJson(new ApiOptions()); internal Json ToJson(ApiOptions options) { 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 (options != null) { if (options.WithTypeName) json.SetProperty("type", _type.FullName); if (options.WithModuleName) json.SetProperty("mudule", _module); if (options.AllowEnumerate) json.SetProperty("functions", Json.From(_list)); } return json; } /// 解析类型,获取 实例。 /// 要解析的类型。 /// 要求此类型拥有 Api 特性。 /// 解析成功返回实例,解析失败返回 NULL 值。 public static ApiApplication Parse(Type type, bool requireAttribute) { if (type == null) return null; // 检查类型的属性。 if (!type.IsClass) return null; if (type.IsAbstract) return null; if (type.IsGenericType) return null; if (type.GetGenericArguments().NotEmpty()) return null; if (!RuntimeUtility.CanNew(type)) return null; // 判断基类。 if (!typeof(ApiController).IsAssignableFrom(type)) return null; // 检查类型的特性。 var apis = type.GetCustomAttributes(typeof(ApiAttribute), false); var api = apis.Length > 0 ? (ApiAttribute)apis[0] : null; if (requireAttribute && api == null) return null; return new ApiApplication(type, api); } } }