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.

189 lines
5.8 KiB

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Apewer.Web
{
/// <summary>入口集合。</summary>
public sealed class ApiEntries : IToJson
{
#region instance
object locker = new object();
SortedDictionary<string, ApiApplication> _apps = new SortedDictionary<string, ApiApplication>();
SortedDictionary<string, ApiAction> _actions = new SortedDictionary<string, ApiAction>();
internal ApiApplication GetApplication(string name)
{
if (string.IsNullOrEmpty(name)) return null;
var key = name.ToLower();
lock (locker)
{
if (_apps.TryGetValue(key, out var value)) return value;
}
return null;
}
internal ApiAction GetAction(string path)
{
if (string.IsNullOrEmpty(path)) return null;
var key = path.ToLower();
lock (locker)
{
if (_actions.TryGetValue(key, out var value)) return value;
}
return null;
}
/// <summary></summary>
public ApiApplication[] Applications { get => _apps.Values.Map(x => x); }
/// <summary></summary>
public ApiAction[] Actions { get => _actions.Values.Map(x => x); }
/// <summary></summary>
public ApiEntries() { }
/// <summary></summary>
public ApiEntries(IEnumerable<ApiApplication> applications, IEnumerable<ApiAction> actions, bool replace = false) : this()
{
Add(applications, replace);
Add(actions, replace);
}
/// <summary></summary>
public ApiEntries(IEnumerable<ApiApplication> applications, bool replace = false) : this(applications, null, replace) { }
/// <summary></summary>
public ApiEntries(ApiAction[] actions, bool replace = false) : this(null, actions, replace) { }
/// <summary>添加入口。</summary>
public void Add(IEnumerable<ApiApplication> applications, bool replace = false)
{
if (applications == null) return;
lock (locker)
{
foreach (var app in applications)
{
if (app == null) continue;
var appKey = app.Name.Lower();
if (appKey.IsEmpty()) continue;
if (_apps.ContainsKey(appKey))
{
if (replace) _apps[appKey] = app;
}
else
{
_apps.Add(appKey, app);
}
}
}
}
/// <summary>添加入口。</summary>
public void Add(IEnumerable<ApiAction> actions, bool replace = false)
{
if (actions == null) return;
lock (locker)
{
foreach (var action in actions)
{
if (action == null) continue;
var actionKey = action.Path.Lower();
if (actionKey.IsEmpty()) continue;
if (_actions.ContainsKey(actionKey))
{
if (replace) _actions[actionKey] = action;
}
else
{
_actions.Add(actionKey, action);
}
}
}
}
/// <summary>追加指定的集合,指定 replace 参数将替换当前实例中的同名的入口。</summary>
public void Add(ApiEntries entries, bool replace = false)
{
if (entries == null) return;
Add(entries.Applications, replace);
Add(entries.Actions, replace);
}
/// <summary>清空当前实例。</summary>
public void Clear()
{
lock (locker)
{
_apps.Clear();
_actions.Clear();
}
}
/// <summary>生成 Json 实例。</summary>
public Json ToJson()
{
lock (locker)
{
var obj = new
{
applications = Applications,
actions = Actions
};
return Json.From(obj);
}
}
#endregion
#region static
/// <summary>从指定的程序集获取入口。</summary>
public static ApiEntries From(Assembly assembly, bool replace = false)
{
if (assembly == null) return null;
var apps = new List<ApiApplication>();
var actions = new List<ApiAction>();
var types = assembly.GetExportedTypes();
foreach (var type in types)
{
apps.Add(ApiApplication.Parse(type, true));
actions.AddRange(ApiAction.Parse(type));
}
var entries = new ApiEntries(apps, actions, replace);
return entries;
}
/// <summary>从多个程序集中获取入口。</summary>
public static ApiEntries From(IEnumerable<Assembly> assemblies, bool replace = false)
{
if (assemblies == null) return null;
var entries = new ApiEntries();
foreach (var assembly in assemblies) entries.Add(From(assembly), replace);
return entries;
}
/// <summary>从当前程序中获取入口。 </summary>
public static ApiEntries Calling(bool replace = false) => From(Assembly.GetCallingAssembly(), replace);
/// <summary>从当前 AppDomain 中获取入口。</summary>
public static ApiEntries AppDomain(bool replace = false) => From(System.AppDomain.CurrentDomain.GetAssemblies(), replace);
#endregion
}
}