using Apewer.Network; using Apewer.Source; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.Reflection; using System.Text; namespace Apewer.Web { /// public static class ApiUtility { #region Text /// 修剪 IP 地址,去除无效的部分。 public static string TrimIP(string text) { var trimmed = TextUtility.Trim(text); if (string.IsNullOrEmpty(trimmed)) return ""; var ip = TextUtility.Trim(trimmed.Split(':')[0]); return NetworkUtility.IsIP(ip) ? ip : ""; } /// 按 & 拆分多个参数。 public static StringPairs Parameters(string query, bool decode = true) { var input = query; var list = new StringPairs(); if (!string.IsNullOrEmpty(input)) { if (input[0] == '?') input = input.Substring(1); var args = input.Split('&'); foreach (var arg in args) { var equals = arg.IndexOf("="); var left = equals < 0 ? arg : arg.Substring(0, equals); var right = equals < 0 ? "" : arg.Substring(equals + 1); if (decode) { left = TextUtility.DecodeUrl(left); right = TextUtility.DecodeUrl(right); } list.Add(left, right); } } return list; } /// 获取参数并解码,可要求修剪参数值。 public static string Parameter(string encoded, bool trim, params string[] names) { if (string.IsNullOrEmpty(encoded)) return null; if (names == null || names.Length < 1) return null; // Names 转为小写,加强适配。 var lowerNames = new List(names.Length); foreach (var name in names) { var lower = TextUtility.Lower(name); if (string.IsNullOrEmpty(lower)) continue; lowerNames.Add(lower); } if (lowerNames.Count < 1) return null; // 分参数对比。 var parameters = Parameters(encoded); var matched = false; foreach (var parameter in parameters) { var left = parameter.Key; var right = parameter.Value; if (trim) right = TextUtility.Lower(right); var lowerLeft = TextUtility.Lower(left); if (lowerNames.Contains(right)) { matched = true; if (!string.IsNullOrEmpty(right)) return right; } } return matched ? "" : null; } /// 获取参数,可要求修剪参数值。 public static string Parameter(StringPairs parameters, bool trim, params string[] names) { if (parameters == null || parameters.Count < 1) return null; if (names == null || names.Length < 1) return null; var lowerNames = new List(names.Length); foreach (var name in names) { var lower = TextUtility.Lower(name); if (string.IsNullOrEmpty(lower)) continue; lowerNames.Add(lower); } foreach (var parameter in parameters) { var lowerKey = TextUtility.Lower(parameter.Key); if (lowerNames.Contains(lowerKey)) { var value = parameter.Value; if (trim) value = TextUtility.Trim(value); if (!string.IsNullOrEmpty(value)) return value; } } return null; } /// 获取 User Agent。 public static string UserAgent(HttpHeaders headers) => headers == null ? null : headers.GetValue("user-agent"); // 从 Uri 对象中解析路径片段。 private static string[] Segmentals(Uri url) { if (url == null) return null; if (string.IsNullOrEmpty(url.AbsolutePath)) return null; var segmentals = url.AbsolutePath.Split('/'); return segmentals; } // 获取已经解析的路径片段。 private static string Segmental(string[] segmentals, int index = 3, bool decode = false) { if (segmentals == null || segmentals.Length < 1) return null; if (index < 1 || index >= segmentals.Length) return null; var segmental = segmentals[index]; if (decode) segmental = TextUtility.DecodeUrl(segmental); return segmental; } #endregion #region Headers /// public static HttpMethod Method(string method) { if (!string.IsNullOrEmpty(method)) { var upper = TextUtility.Upper(method); if (upper.Contains("OPTIONS")) return HttpMethod.OPTIONS; else if (upper.Contains("POST")) return HttpMethod.POST; else if (upper.Contains("GET")) return HttpMethod.GET; else if (upper.Contains("CONNECT")) return HttpMethod.CONNECT; else if (upper.Contains("DELETE")) return HttpMethod.DELETE; else if (upper.Contains("HEAD")) return HttpMethod.HEAD; else if (upper.Contains("PATCH")) return HttpMethod.PATCH; else if (upper.Contains("PUT")) return HttpMethod.PUT; else if (upper.Contains("TRACE")) return HttpMethod.TRACE; } return HttpMethod.NULL; } /// 获取 X-Forwarded-For,不存在时返回 NULL 值。 public static string[] GetForwardedIP(HttpHeaders headers) { if (headers != null) { var value = headers.GetValue("x-forwarded-for"); if (!string.IsNullOrEmpty(value)) { var fips = new List(); var split = value.Split(',', ' '); foreach (var para in split) { var fip = TrimIP(para); if (!string.IsNullOrEmpty(fip)) fips.Add(fip); } return fips.ToArray(); } } return new string[0]; } #endregion #region Cookies // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie // 可以是除了控制字符 (CTLs)、空格 (spaces) 或制表符 (tab)之外的任何 US-ASCII 字符。 // 同时不能包含以下分隔字符: ( ) < > @ , ; : \ " / [ ] ? = { }. // 是可选的,如果存在的话,那么需要包含在双引号里面。 // 支持除了控制字符(CTLs)、空格(whitespace)、双引号(double quotes)、逗号(comma)、分号(semicolon)以及反斜线(backslash)之外的任意 US-ASCII 字符。 // 关于编码:许多应用会对 cookie 值按照URL编码(URL encoding)规则进行编码,但是按照 RFC 规范,这不是必须的。 // 不过满足规范中对于 所允许使用的字符的要求是有用的。 const string CookieChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&*+-<>^_`|~"; /// 修剪 Cookie 的 Name 文本。 public static string CookieName(string name) { if (name.IsEmpty()) return null; var t = TextUtility.Restrict(name, CookieChars); while (t.StartsWith("$")) t = t.Substring(1); return t; } /// 修剪 Cookie 的 Value 文本。 public static string CookieValue(string value) { if (value.IsEmpty()) return value; var t = TextUtility.Restrict(value, CookieChars); if (t != value) { t = TextUtility.EncodeUrl(value); t = TextUtility.Restrict(t, CookieChars); } return t; } static string CookieExpires(DateTime dt) { // Expires=Wed, 21 Oct 2015 07:28:00 GMT; var utc = dt.ToUniversalTime(); var sb = new StringBuilder(); var week = utc.DayOfWeek.ToString().Substring(0, 3); sb.Append(week); sb.Append(", "); var day = utc.Day; if (day < 10) sb.Append("0"); sb.Append(day); sb.Append(" "); var month = null as string; switch (utc.Month) { case 1: month = "Jan"; break; case 2: month = "Feb"; break; case 3: month = "Mar"; break; case 4: month = "Apr"; break; case 5: month = "May"; break; case 6: month = "Jun"; break; case 7: month = "Jul"; break; case 8: month = "Aug"; break; case 9: month = "Sep"; break; case 10: month = "Oct"; break; case 11: month = "Nov"; break; case 12: month = "Dec"; break; } sb.Append(month); sb.Append(" "); var year = utc.Year; if (year < 1000) sb.Append("0"); if (year < 100) sb.Append("0"); if (year < 10) sb.Append("0"); sb.Append(year); sb.Append(" "); var time = ClockUtility.Lucid(utc, false, true, true, false); sb.Append(time); sb.Append(" GMT"); return sb.ToString(); } /// 获取 Cookies 中第一个匹配到的值。 public static string GetValue(this CookieCollection cookies, string name) { if (cookies == null || name.IsEmpty()) return null; var count = cookies.Count; for (var i = 0; i < count; i++) { var cookie = cookies[i]; var n = cookie.Name; if (name == n) return cookie.Value; } var lower = TextUtility.Lower(name); for (var i = 0; i < count; i++) { var cookie = cookies[i]; var n = TextUtility.Lower(cookie.Name); if (lower == n) return cookie.Value; } return null; } /// 添加 Cookie 到集合。 /// Cookie 集合。 /// 名称。 /// 值。 /// 应用的路径。 /// public static void Add(this CookieCollection cookies, string name, string value, string path = "/") => Add(cookies, name, value, path, null); /// 添加 Cookie 到集合。 /// Cookie 集合。 /// 名称。 /// 值。 /// 应用的路径。 /// 过期时间。 /// public static void Add(this CookieCollection cookies, string name, string value, DateTime expires, string path = "/") => Add(cookies, name, value, path, new Class(expires)); /// 添加 Cookie 到集合。 /// Cookie 集合。 /// 名称。 /// 值。 /// 应用的路径。 /// 过期时间。 /// public static void Add(this CookieCollection cookies, string name, string value, string path, DateTime expires) => Add(cookies, name, value, path, new Class(expires)); static void Add(this CookieCollection cookies, string name, string value, string path, Class expires) { if (cookies == null) return; name = CookieName(name); value = CookieName(value) ?? ""; if (string.IsNullOrEmpty(name)) return; var cookie = new Cookie(name, value); cookie.Path = string.IsNullOrEmpty(path) ? "/" : path; if (expires != null) cookie.Expires = expires.Value; cookies.Add(cookie); } /// 遍历 Cookie 集合。 public static void ForEach(this CookieCollection cookies, Action action) { if (cookies == null || action == null) return; var count = cookies.Count; for (var i = 0; i < count; i++) { var cookie = cookies[i]; if (cookie == null) continue; action.Invoke(cookie); } } internal static CookieCollection ParseCookies(HttpHeaders headers) { var cookies = new CookieCollection(); if (headers == null) return cookies; var hvs = headers.GetValues("Cookie"); foreach (var hv in hvs) { if (string.IsNullOrEmpty(hv)) continue; var lines = hv.Split(';'); foreach (var line in lines) { var e = line.IndexOf("="); if (e < 0) continue; var name = TextUtility.Left(line, e, true); var value = TextUtility.Right(line, line.Length - e - 1, true); if (string.IsNullOrEmpty(name)) continue; if (string.IsNullOrEmpty(value)) continue; cookies.Add(name, value); } } return cookies; } /// 生成 Set-Cookie 的值。 public static string SetCookie(Cookie cookie) { if (cookie == null) return null; var n = CookieName(cookie.Name); if (n.IsEmpty()) return null; var v = CookieValue(cookie.Value); if (v == null) v = ""; var sb = new StringBuilder(); sb.Append(n); sb.Append("="); sb.Append(v); var expires = cookie.Expires; if (expires > DateTime.MinValue) { sb.Append("; Expires="); sb.Append(CookieExpires(expires)); } var domain = cookie.Domain; if (!string.IsNullOrEmpty(domain)) { sb.Append("; Domain="); sb.Append(domain); } var path = cookie.Path; sb.Append("; Path="); sb.Append(string.IsNullOrEmpty(path) ? "/" : path); var secure = cookie.Secure; if (secure) { sb.Append("; Secure"); } return sb.ToString(); } /// 生成 Set-Cookie 的值。 public static string[] SetCookie(CookieCollection cookies) { if (cookies == null) return null; var count = cookies.Count; var lines = new List(count); for (var i = 0; i < count; i++) { var cookie = cookies[i]; var value = SetCookie(cookie); if (value.IsEmpty()) continue; lines.Add(value); } return lines.ToArray(); } #endregion #region ApiController /// 设置控制器属性。 public static void SetProperties(ApiController controller, ApiRequest request, ApiResponse response, ApiOptions options) { if (controller == null) return; controller.Request = request; controller.Response = response; controller._options = options; } /// 获取由控制器构造函数指定的初始化程序。 public static Func GetInitialier(this ApiController controller) => controller == null ? null : controller._func; /// 获取由控制器构造函数指定的默认程序。 public static Action GetDefault(this ApiController controller) => controller == null ? null : controller._default; /// 获取选项。 public static ApiOptions GetOptions(this ApiController controller) => controller == null ? null : controller._options; /// 以 POST 转移请求到其它 URL。 private static string Transfer(ApiController controller, string url, string application = null, string function = null) { if (controller == null || controller.Request == null || controller.Response == null) return "ApiControllser 无效。"; if (url.IsEmpty()) return "ApiController 无效。"; var s = Json.NewObject(); s.SetProperty("random", TextUtility.Key()); s.SetProperty("application", application.IsEmpty() ? controller.Request.Application : application); s.SetProperty("function", function.IsEmpty() ? controller.Request.Function : function); s.SetProperty("data", controller.Request.Data); s.SetProperty("session", controller.Request.Session); s.SetProperty("ticket", controller.Request.Ticket); s.SetProperty("page", controller.Request.Page); var c = new HttpClient(); c.Url = url; c.Method = HttpMethod.POST; // TODO 设置 Request 的 Cookies。 c.RequestData = s.ToString().Bytes(); var e = c.Send(); if (e != null) return e.Message; // TODO 解析 Response 的 Cookies。 var r = Json.From(c.ResponseData.Text()); if (r == null || !r.Available) { controller.Response.Error("请求失败。"); return "请求失败。"; } if (r["status"] != "ok") { controller.Response.Error(r["message"]); return r["message"]; } controller.Response.Data.Reset(r.GetProperty("data")); return null; } /// 创建指定类型的控制器,并引用当前控制器的 Request 和 Response。 public static T Create(this ApiController current) where T : ApiController, new() { var controller = new T(); if (current != null) { controller.Request = current.Request; controller.Response = current.Response; } return controller; } /// 使用默认控制器处理请求。 public static void UseDefault(this ApiController current) { if (current == null) return; var options = GetOptions(current); if (options == null) return; var type = options.Default; if (type == null) return; var controller = null as ApiController; try { controller = (ApiController)Activator.CreateInstance(type); SetProperties(controller, current.Request, current.Response, options); } catch { return; } controller.GetInitialier()?.Invoke(controller); } #endregion #region ApiContext /// 作为纯文本输出。 /// Content-Type: text/plain public static void Text(ApiContext context, string text) { if (context == null) return; Model(context.Response, new ApiTextModel(text, "text/plain")); } /// 设置 status 为 error,并设置 message 的内容。 public static void Error(ApiContext context, string text) { if (context == null) return; Error(context.Response, text); } #endregion #region ApiRequest /// 获取 URL 路径段,不存在的段为 NULL 值。可要求解码。 public static string Segmental(this ApiRequest request, int index = 3, bool decode = false) { if (request == null) return null; if (request._segmentals == null) request._segmentals = Segmentals(request.Url); return Segmental(request._segmentals, index, decode); } /// 获取参数,指定可能的参数名,默认将修剪参数值。 /// 当从 URL 中获取参数时将解码。 public static string Parameter(this ApiRequest request, params string[] names) => Parameter(request, true, names); /// 获取参数,指定可能的参数名,可要求修剪参数值。 /// 当从 URL 中获取参数时将解码。 public static string Parameter(ApiRequest request, bool trim, params string[] names) { if (request == null) return null; if (names == null || names.Length < 1) return null; var dedupNames = new List(names.Length); var lowerNames = new List(names.Length); foreach (var name in names) { if (string.IsNullOrEmpty(name)) continue; if (dedupNames.Contains(name)) continue; else dedupNames.Add(name); var lower = TextUtility.Lower(name); if (lowerNames.Contains(lower)) continue; else lowerNames.Add(lower); } var matched = false; // POST 优先。 var data = request.Data; if (data != null && data.IsObject) { var properties = data.GetProperties(); if (properties != null) { // Json 区分大小写,先全字匹配。 foreach (var property in properties) { if (!property.IsProperty) continue; var name = property.Name; if (!dedupNames.Contains(name)) continue; var value = property.Value; if (value == null) continue; matched = true; var text = value.ToString(); if (trim) text = TextUtility.Trim(text); if (!string.IsNullOrEmpty(text)) return text; } // 以小写模糊匹配。 foreach (var property in properties) { if (!property.IsProperty) continue; var name = TextUtility.Lower(property.Name); if (!lowerNames.Contains(name)) continue; var value = property.Value; if (value == null) continue; matched = true; var text = value.ToString(); if (trim) text = TextUtility.Trim(text); if (!string.IsNullOrEmpty(text)) return text; } } } // 从已解析的 Get 参数中搜索。 if (request.Parameters != null) { var value = Parameter(request.Parameters, trim, names); if (!string.IsNullOrEmpty(value)) return value; if (value != null) matched = true; } return matched ? "" : null; } #endregion #region ApiResponse internal static ApiModel Model(ApiResponse response, ApiModel model) { if (response == null && model == null) return null; response.Model = model; return model; } /// 设置响应。 public static string Respond(ApiResponse response, Json data, bool lower = true) { if (response == null) return "Response 对象无效。"; if (data != null) { if (lower) data = Json.Lower(data); response.Data = data; } return null; } /// 设置响应,当发生错误时设置响应。返回错误信息。 public static string Respond(ApiResponse response, IList list, bool lower = true, int depth = -1, bool force = false) { if (response == null) return "Response 对象无效。"; if (list == null) { var error = "列表对象无效。"; response.Error(error); return error; } var json = Json.From(list, lower, depth, force); if (json == null || !json.Available) { var error = "列表无法序列化。"; response.Error(error); return error; } if (response.Data == null) response.Data = Json.NewObject(); response.Data.SetProperty("count", list.Count); response.Data.SetProperty("list", Json.From(list, lower, depth, force)); return null; } /// 设置响应,当发生错误时设置响应。返回错误信息。 public static string Respond(ApiResponse response, IRecord record, bool lower = true) { if (response == null) return "Response 对象无效。"; if (record == null) { var error = "记录无效。"; response.Error(error); return error; } var json = Json.From(record, lower); if (json == null || !json.Available) { var error = "记录无法序列化。"; response.Error(error); return error; } if (response.Data == null) response.Data = Json.NewObject(); response.Data.Reset(json); return null; } /// 设置 status 为 error,并设置 message 的内容。 public static void Error(ApiResponse response, string message = "未知错误。") { if (response == null) return; response.Model = null; response.Status = "error"; response.Message = message ?? TextUtility.Empty; } /// 设置 status 为 exception,并设置 message 的内容。 public static void Exception(ApiResponse response, Exception exception, bool setData = true) { if (response == null) return; response.Model = null; response.Status = "exception"; if (exception != null) { try { if (setData) { var json = ToJson(exception); response.Message = json["message"]; response.Data = json; } else { response.Message = exception.Message(); } } catch { } } } private static Json ToJson(Exception exception, bool withInner = true) { if (exception == null) return ToJson(new NullReferenceException()); var json = Json.NewObject(); json.SetProperty("type", exception.GetType().FullName); json.SetProperty("message", exception.Message); var st = exception.StackTrace; if (!string.IsNullOrEmpty(st)) { var stack = Json.NewArray(); var split = st.Split('\r', '\n'); foreach (var line in split) { var trim = TextUtility.Trim(line); if (string.IsNullOrEmpty(trim)) continue; stack.AddItem(trim); } json.SetProperty("stack", stack); } if (withInner) { var iex = exception.InnerException; if (iex != null) json.SetProperty("inner", ToJson(exception, false)); } return json; } /// 停止 Invoker 对返回值的处理。 public static void StopReturn(ApiResponse response) { if (response == null) return; response.StopReturn = true; } /// 生成 Response 的 Json 实例。 public static string ToJson(this ApiResponse response, ApiOptions options = null) { if (response == null) return "{}"; if (string.IsNullOrEmpty(response.Status)) response.Status = "ok"; var json = Json.NewObject(); if (options == null) options = new ApiOptions(); // 执行时间。 if (options.WithClock) { json.SetProperty("clock", ClockUtility.Lucid(DateTime.Now)); } // 持续时间。 if (options.WithDuration) { if (response.Duration.NotEmpty()) json.SetProperty("duration", response.Duration); } // 随机值。 var random = response.Random; if (!string.IsNullOrEmpty(random)) json.SetProperty("random", random); // 调用。 if (options.WithTarget) { json.SetProperty("application", response.Application); json.SetProperty("function", response.Function); } // 状态。 json.SetProperty("status", (TextUtility.IsBlank(response.Status) ? TextUtility.Empty : response.Status.ToLower())); if (!string.IsNullOrEmpty(response.Message)) json.SetProperty("message", response.Message); // 用户数据。 if (response.Message == "exception" && !options.WithException) json.SetProperty("data"); else json.SetProperty("data", response.Data); var indented = response.Indented || options.JsonIndent; var text = json.ToString(indented); return text; } #endregion #region ApiResult /// 对 HTTP 结果设置文件名。 /// 结果。 /// 文件名(未编码)。 public static void SetAttachemnt(this HeadResult result, string name) { if (result == null) throw new ArgumentNullException(nameof(result)); if (name.IsEmpty()) throw new ArgumentNullException(nameof(name)); var encoded = TextUtility.EncodeUrl(name); result.Headers.Add("Content-Disposition", $"attachment; filename={encoded}"); } #endregion #region ApiFunction Parameters internal static object[] ReadParameters(ApiRequest request, ApiFunction function) { if (request == null || function == null) return null; return ReadParameters(request, function.Parameters); } /// 为带有形参的 Function 准备实参。 /// API 请求模型。 /// Function 的参数信息。 /// 实参。 public static object[] ReadParameters(ApiRequest request, ParameterInfo[] parameters) { if (request == null || parameters == null || parameters.Length < 1) return null; var apiParameters = parameters.Map(x => ApiParameter.Parse(x) ?? throw new Exception($"参数【{x.Name}】无效。")); return ReadParameters(request, apiParameters); } /// 为带有形参的 Function 准备实参。 /// API 请求模型。 /// Function 的参数信息。 /// 实参。 public static object[] ReadParameters(ApiRequest request, ApiParameter[] parameters) { if (request == null || parameters == null || parameters.Length < 1) return null; if (parameters == null) return null; var count = parameters.Length; if (count < 1) return null; // 当 Function 仅有一个参数时,尝试生成模型。 if (count == 1 && parameters[0] != null) { var parameterName = parameters[0].Name; var parameterType = parameters[0].Type; // POST if (request.Method == HttpMethod.POST) { // string if (parameterType.Equals(typeof(string))) return new object[] { request.Parameters.GetValue(parameterName, true) }; // json if (parameterType.Equals(typeof(Json))) return new object[] { request.PostJson }; #if !NET20 // dynamic if (parameterType.Equals(typeof(object))) { try { // var expando = new System.Dynamic.ExpandoObject(); // var dict = expando as IDictionary; var expando = new ObjectSet(false, true); var dict = expando.Origin(); if (request.Form != null) { foreach (var kvp in request.Form) { if (dict.ContainsKey(kvp.Key)) continue; dict.Add(kvp.Key, kvp.Value); } } else if (request.PostJson) { var jprops = request.PostJson.GetProperties(); foreach (var jprop in jprops) { var name = jprop.Name; if (dict.ContainsKey(name)) continue; var value = jprop.Value; if (value != null) { } dict.Add(name, value); } } return new object[] { expando }; } catch { } } #endif // class if (parameterType.IsClass) { try { var entity = ReadParameter(request.Data, parameterType); if (entity == null) entity = ReadParameter(request.PostJson, parameterType); if (entity != null) return new object[] { entity.Value }; } catch { } } if (request.PostJson) return new object[] { request.PostJson }; if (request.Form != null) return new object[] { request.Form }; if (request.PostText.NotEmpty()) return new object[] { request.PostText }; return new object[] { request.PostData }; } else { // string if (parameterType.Equals(typeof(string))) return new object[] { request.Parameters.GetValue(parameterName, true) }; // json if (parameterType.Equals(typeof(Json))) return new object[] { Json.From(request.Parameters.GetValue(parameterName, true)) }; } } var values = new object[count]; for (var i = 0; i < count; i++) { if (parameters[i] != null) { var name = parameters[i].Name; var type = parameters[i].Type; var text = Parameter(request, name); values[i] = ReadParameter(text, type); } } return values; } static Class ReadParameter(Json json, Type type) { if (json) { if (json.IsObject) { var properties = json.GetProperties(); if (properties.Length > 0) { var entity = Json.Object(type, json, true, null, true); return new Class(entity); } } if (json.IsArray) { var items = json.GetItems(); if (items.Length > 0) { var entity = Json.Object(type, json, true, null, true); return new Class(entity); } } } return null; } static object ReadParameter(string text, Type type) { if (type.Equals(typeof(object)) || type.Equals(typeof(string))) return text; if (type.Equals(typeof(bool))) return NumberUtility.Boolean(text); if (type.Equals(typeof(float))) return NumberUtility.Single(text); if (type.Equals(typeof(double))) return NumberUtility.Double(text); if (type.Equals(typeof(decimal))) return NumberUtility.Decimal(text); if (type.Equals(typeof(byte))) return NumberUtility.Byte(text); if (type.Equals(typeof(sbyte))) return NumberUtility.SByte(text); if (type.Equals(typeof(short))) return NumberUtility.Int16(text); if (type.Equals(typeof(ushort))) return NumberUtility.UInt16(text); if (type.Equals(typeof(int))) return NumberUtility.Int32(text); if (type.Equals(typeof(uint))) return NumberUtility.UInt32(text); if (type.Equals(typeof(long))) return NumberUtility.Int64(text); if (type.Equals(typeof(ulong))) return NumberUtility.UInt64(text); if (type.Equals(typeof(byte[]))) return TextUtility.FromBase64(text); if (type.Equals(typeof(Json))) return Json.From(text); return type.IsValueType ? Activator.CreateInstance(type) : null; } #endregion #region Enumerate Entries internal static Json Enumerate(IEnumerable applications, ApiOptions options) { var list = Json.NewArray(); var count = 0; if (applications != null) { foreach (var app in applications) { if (app == null) continue; if (app.Hidden) continue; list.AddItem(app.ToJson(options)); count = count + 1; } } var json = Json.NewObject(); json.SetProperty("count", count); json.SetProperty("applications", list); return json; } internal static Json Enumerate(IEnumerable functions, ApiOptions options) { var count = 0; var list = Json.NewArray(); if (functions != null) { foreach (var func in functions) { if (func == null) continue; if (func.Hidden) continue; list.AddItem(func.ToJson(options)); count = count + 1; } } var json = Json.NewObject(); json.SetProperty("count", count); json.SetProperty("functions", list); return json; } #endregion } }