using Apewer.Network; using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace Apewer.AspNetBridge { [Serializable] internal class RouteItem : IToJson { public string Path; public string Lower; public Type Controller; public MethodInfo Method; public string MethodName; public bool Connect; public bool Delete; public bool Get; public bool Head; public bool Options; public bool Patch; public bool Post; public bool Put; public bool Trace; public ParameterInfo[] Parameters; public Type Return; public Json ToJson() { var ps = Json.NewObject(); foreach (var parameter in Parameters) ps.SetProperty(parameter.Name, parameter.ParameterType.FullName); var methods = Json.NewArray(); if (Connect) methods.AddItem("connect"); if (Delete) methods.AddItem("delete"); if (Get) methods.AddItem("get"); if (Head) methods.AddItem("head"); if (Options) methods.AddItem("options"); if (Patch) methods.AddItem("patch"); if (Post) methods.AddItem("post"); if (Put) methods.AddItem("put"); if (Trace) methods.AddItem("trace"); var json = Json.NewObject(); json.SetProperty("path", Path); json.SetProperty("controller", Controller.FullName); json.SetProperty("function", Method.Name); json.SetProperty("return", Return.FullName); json.SetProperty("parameters", ps); json.SetProperty("methods", methods); return json; } #region Enumerate internal static RouteItem[] Parse(IEnumerable assemblies, bool withVoid) { if (assemblies.IsEmpty()) assemblies = AppDomain.CurrentDomain.GetAssemblies(); var baseType = typeof(ApiController); var items = new ArrayBuilder(); foreach (var assembly in assemblies) { var types = assembly.GetExportedTypes(); foreach (var type in types) { if (type.IsNotPublic) continue; if (!type.IsClass) continue; if (!RuntimeUtility.IsInherits(type, baseType)) continue; if (type.Name == "AccountController") { } var pa = RuntimeUtility.GetAttribute(type, false); var prefix = (pa == null || pa.Path.IsEmpty()) ? null : pa.Path.Split('/'); var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var method in methods) { if (method.IsConstructor) continue; if (method.IsGenericMethod) continue; if (!withVoid) { var returnType = method.ReturnType; if (returnType == null || returnType.Equals(typeof(void))) continue; } var route = RuntimeUtility.GetAttribute(method); if (route == null) continue; var path = route.Path; if (path.IsEmpty()) path = method.Name; if (path.IsEmpty()) continue; path = Concat(prefix, path.Split('/')); var item = new RouteItem(); item.Controller = type; item.Method = method; item.MethodName = method.Name; item.Parameters = method.GetParameters(); item.Return = method.ReturnType; item.Path = path; item.Lower = path.Lower(); item.Get = RuntimeUtility.Contains(method); item.Post = RuntimeUtility.Contains(method); item.Connect = RuntimeUtility.Contains(method); item.Delete = RuntimeUtility.Contains(method); item.Head = RuntimeUtility.Contains(method); item.Options = RuntimeUtility.Contains(method); item.Patch = RuntimeUtility.Contains(method); item.Put = RuntimeUtility.Contains(method); item.Trace = RuntimeUtility.Contains(method); items.Add(item); } } } return items.Export(); } internal static RouteItem Match(RouteItem[] routes, string path, HttpMethod method) { if (routes == null) return null; if (path.IsEmpty()) path = "/"; var length = routes.Length; for (var i = 0; i < length; i++) { var route = routes[i]; if (route == null) continue; if (route.Path != path) continue; if (method == HttpMethod.GET && route.Get) return route; if (method == HttpMethod.POST && route.Post) return route; if (method == HttpMethod.CONNECT && route.Connect) return route; if (method == HttpMethod.DELETE && route.Delete) return route; if (method == HttpMethod.HEAD && route.Head) return route; if (method == HttpMethod.OPTIONS && route.Options) return route; if (method == HttpMethod.PATCH && route.Patch) return route; if (method == HttpMethod.PUT && route.Put) return route; if (method == HttpMethod.TRACE && route.Trace) return route; } var lower = path.Lower(); for (var i = 0; i < length; i++) { var route = routes[i]; if (route == null) continue; if (route.Lower != lower) continue; if (method == HttpMethod.GET && route.Get) return route; if (method == HttpMethod.POST && route.Post) return route; if (method == HttpMethod.CONNECT && route.Connect) return route; if (method == HttpMethod.DELETE && route.Delete) return route; if (method == HttpMethod.HEAD && route.Head) return route; if (method == HttpMethod.OPTIONS && route.Options) return route; if (method == HttpMethod.PATCH && route.Patch) return route; if (method == HttpMethod.PUT && route.Put) return route; if (method == HttpMethod.TRACE && route.Trace) return route; } return null; } static string Concat(string[] prefix, string[] path) { var all = new List(16); if (prefix != null) all.AddRange(prefix); if (path != null) all.AddRange(path); var segs = new List(all.Count); foreach (var seg in all) { if (seg.IsEmpty()) continue; segs.Add(seg); } if (segs.Count < 1) return "/"; return "/" + TextUtility.Join("/", segs.ToArray()); } #endregion } }