using NCC.ClayObject.Extensions; using NCC.Dependency; using NCC.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace NCC.Templates.Extensions { /// /// 字符串渲染模板拓展类 /// [SuppressSniffer] public static class StringRenderExtensions { /// /// 模板正则表达式 /// private const string commonTemplatePattern = @"\{(?

.+?)\}"; ///

/// 读取配置模板正则表达式 /// private const string configTemplatePattern = @"\#\((?

.*?)\)"; ///

/// 渲染模板 /// /// /// /// public static void Render(this string template, object templateData, bool encode = false) { if (template == null) return; template.Render(templateData == null ? default : templateData.ToDictionary(), encode); } /// /// 渲染模板 /// /// /// /// /// public static string Render(this string template, IDictionary templateData, bool encode = false) { if (template == null) return default; // 如果模板为空,则跳过 if (templateData == null || templateData.Count == 0) return template; // 判断字符串是否包含模板 if (!Regex.IsMatch(template, commonTemplatePattern)) return template; // 获取所有匹配的模板 var templateValues = Regex.Matches(template, commonTemplatePattern) .Select(u => new { Template = u.Groups["p"].Value, Value = MatchTemplateValue(u.Groups["p"].Value, templateData) }); // 循环替换模板 foreach (var item in templateValues) { template = template.Replace($"{{{item.Template}}}", encode ? Uri.EscapeDataString(item.Value?.ToString() ?? string.Empty) : item.Value?.ToString()); } return template; } /// /// 从配置中渲染字符串模板 /// /// /// /// public static string Render(this string template, bool encode = false) { if (template == null) return default; // 判断字符串是否包含模板 if (!Regex.IsMatch(template, configTemplatePattern)) return template; // 获取所有匹配的模板 var templateValues = Regex.Matches(template, configTemplatePattern) .Select(u => new { Template = u.Groups["p"].Value, Value = App.Configuration[u.Groups["p"].Value] }); // 循环替换模板 foreach (var item in templateValues) { template = template.Replace($"#({item.Template})", encode ? Uri.EscapeDataString(item.Value?.ToString() ?? string.Empty) : item.Value?.ToString()); } return template; } /// /// 匹配模板值 /// /// /// /// private static object MatchTemplateValue(string template, IDictionary templateData) { string tmpl; if (!template.Contains('.', StringComparison.CurrentCulture)) tmpl = template; else tmpl = template.Split('.', StringSplitOptions.RemoveEmptyEntries).First(); var templateValue = templateData.ContainsKey(tmpl) ? templateData[tmpl] : default; return ResolveTemplateValue(template, templateValue); } /// /// 解析模板的值 /// /// /// /// private static object ResolveTemplateValue(string template, object data) { // 根据 . 分割模板 var propertyCrumbs = template.Split('.', StringSplitOptions.RemoveEmptyEntries); return GetValue(propertyCrumbs, data); // 静态本地函数 static object GetValue(string[] propertyCrumbs, object data) { if (data == null || propertyCrumbs == null || propertyCrumbs.Length <= 1) return data; var dataType = data.GetType(); // 如果是基元类型则直接返回 if (dataType.IsRichPrimitive()) return data; object value = null; // 递归获取下一级模板值 for (var i = 1; i < propertyCrumbs.Length; i++) { var propery = dataType.GetProperty(propertyCrumbs[i]); if (propery == null) break; value = propery.GetValue(data); if (i + 1 < propertyCrumbs.Length) { value = GetValue(propertyCrumbs.Skip(i).ToArray(), value); } else break; } return value; } } } }