using System.Text.RegularExpressions; using NCalc; public class Utils { public static Dictionary FeignUrl = new Dictionary(); #region 打控制台日志 public static void WriteLog(string msg, string filename = "message") { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "--" + filename + "--" + msg); } #endregion /// /// 解析布尔表达式,返回 true/false /// 支持的表达式示例:"10 > 5", "a == b", "(1+2) < 10 && 3 != 4", "true || false" /// /// 布尔表达式字符串 /// 可选:表达式中的变量参数(如 a=10, b=5) /// 表达式的布尔结果 public static bool EvaluateBoolean(string booleanExpression, Dictionary parameters = null) { try { // 创建表达式对象 var expr = new Expression(booleanExpression); // 2. 【强制绑定】直接绑定函数事件(不抽离,避免绑定失效) expr.EvaluateFunction += OnEvaluateFunction; // 注入变量参数(如果有) if (parameters != null && parameters.Count > 0) { foreach (var param in parameters) { expr.Parameters[param.Key] = param.Value; } } // 执行表达式并转换为布尔值 var result = expr.Evaluate(); return Convert.ToBoolean(result); } catch (Exception ex) { throw new ArgumentException($"布尔表达式解析失败:{booleanExpression},错误:{ex.Message}", ex); } } /// /// 核心函数处理逻辑(直接写,避免任何匹配误差) /// private static void OnEvaluateFunction(string funcName, FunctionArgs args) { // 注册 Contains 函数(核心新增) if (funcName == "Contains") { if (args.Parameters.Length != 2) { throw new ArgumentException("Contains 必须传入 2 个参数:字符串、子串"); } // 安全获取参数(避免 null/空字符串解析问题) var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty; var subStr = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty; args.Result = str.Contains(subStr); return; } // 方案1:精准匹配(表达式写 StartsWith 就匹配 StartsWith) if (funcName == "StartsWith") { // 严格校验参数数量 if (args.Parameters.Length != 2) { throw new ArgumentException("StartsWith 必须传入 2 个参数:字符串、前缀"); } // 安全获取参数值(避免 null) var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty; var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty; // 执行原生 StartsWith args.Result = str.StartsWith(prefix); return; } if (funcName == "EndsWith") { // 严格校验参数数量 if (args.Parameters.Length != 2) { throw new ArgumentException("EndsWith 必须传入 2 个参数:字符串、前缀"); } // 安全获取参数值(避免 null) var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty; var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty; // 执行原生 EndsWith args.Result = str.EndsWith(prefix); return; } if (funcName == "In") { // 严格校验参数数量 if (args.Parameters.Length != 2) { throw new ArgumentException("In 必须传入 2 个参数:字符串、前缀"); } // 安全获取参数值(避免 null) var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty; var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty; // 执行原生 EndsWith args.Result = str.Replace("[", "").Replace("]", "").Split(',').Contains(prefix); return; } // 方案1:精准匹配 IsNullOrEmpty if (funcName == "IsNullOrEmpty") { if (args.Parameters.Length != 1) { throw new ArgumentException("IsNullOrEmpty 必须传入 1 个参数:字符串"); } var value = args.Parameters[0].Evaluate()?.ToString(); args.Result = string.IsNullOrEmpty(value); return; } if (funcName == "ArrayLen") { if (args.Parameters.Length != 1) { throw new ArgumentException("ArrayLen 必须传入 1 个参数:数组"); } var value = args.Parameters[0].Evaluate()?.ToString(); args.Result = value?.Replace("[", "").Replace("]", "").Split(',').Length ?? 0; return; } if (funcName == "Match") { // 严格校验参数数量 if (args.Parameters.Length != 2) { throw new ArgumentException("Match 必须传入 2 个参数:字符串、正则表达式"); } // 安全获取参数值(避免 null) var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty; var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty; // 执行原生 StartsWith args.Result = Regex.IsMatch(str, prefix); return; } // 未找到函数时明确报错 throw new ArgumentException($"未定义函数:{funcName}"); } }