Utils.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System.Text.RegularExpressions;
  2. using NCalc;
  3. public class Utils
  4. {
  5. public static Dictionary<string, string> FeignUrl = new Dictionary<string, string>();
  6. #region 打控制台日志
  7. public static void WriteLog(string msg, string filename = "message")
  8. {
  9. Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "--" + filename + "--" + msg);
  10. }
  11. #endregion
  12. /// <summary>
  13. /// 解析布尔表达式,返回 true/false
  14. /// 支持的表达式示例:"10 > 5", "a == b", "(1+2) < 10 && 3 != 4", "true || false"
  15. /// </summary>
  16. /// <param name="booleanExpression">布尔表达式字符串</param>
  17. /// <param name="parameters">可选:表达式中的变量参数(如 a=10, b=5)</param>
  18. /// <returns>表达式的布尔结果</returns>
  19. public static bool EvaluateBoolean(string booleanExpression, Dictionary<string, object> parameters = null)
  20. {
  21. if(string.IsNullOrEmpty(booleanExpression)) return false;
  22. try
  23. {
  24. // 创建表达式对象
  25. var expr = new Expression(booleanExpression);
  26. // 2. 【强制绑定】直接绑定函数事件(不抽离,避免绑定失效)
  27. expr.EvaluateFunction += OnEvaluateFunction;
  28. // 注入变量参数(如果有)
  29. if (parameters != null && parameters.Count > 0)
  30. {
  31. foreach (var param in parameters)
  32. {
  33. expr.Parameters[param.Key] = param.Value;
  34. }
  35. }
  36. // 执行表达式并转换为布尔值
  37. var result = expr.Evaluate();
  38. return Convert.ToBoolean(result);
  39. }
  40. catch (Exception ex)
  41. {
  42. // throw new ArgumentException($"布尔表达式解析失败:{booleanExpression},错误:{ex.Message}", ex);
  43. Utils.WriteLog($"布尔表达式解析失败:{booleanExpression},错误:{ex.Message}", "error");
  44. return false;
  45. }
  46. }
  47. /// <summary>
  48. /// 核心函数处理逻辑(直接写,避免任何匹配误差)
  49. /// </summary>
  50. private static void OnEvaluateFunction(string funcName, FunctionArgs args)
  51. {
  52. // 注册 Contains 函数(核心新增)
  53. if (funcName == "Contains")
  54. {
  55. if (args.Parameters.Length != 2)
  56. {
  57. throw new ArgumentException("Contains 必须传入 2 个参数:字符串、子串");
  58. }
  59. // 安全获取参数(避免 null/空字符串解析问题)
  60. var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty;
  61. var subStr = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty;
  62. args.Result = str.Contains(subStr);
  63. return;
  64. }
  65. // 方案1:精准匹配(表达式写 StartsWith 就匹配 StartsWith)
  66. if (funcName == "StartsWith")
  67. {
  68. // 严格校验参数数量
  69. if (args.Parameters.Length != 2)
  70. {
  71. throw new ArgumentException("StartsWith 必须传入 2 个参数:字符串、前缀");
  72. }
  73. // 安全获取参数值(避免 null)
  74. var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty;
  75. var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty;
  76. // 执行原生 StartsWith
  77. args.Result = str.StartsWith(prefix);
  78. return;
  79. }
  80. if (funcName == "EndsWith")
  81. {
  82. // 严格校验参数数量
  83. if (args.Parameters.Length != 2)
  84. {
  85. throw new ArgumentException("EndsWith 必须传入 2 个参数:字符串、前缀");
  86. }
  87. // 安全获取参数值(避免 null)
  88. var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty;
  89. var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty;
  90. // 执行原生 EndsWith
  91. args.Result = str.EndsWith(prefix);
  92. return;
  93. }
  94. if (funcName == "In")
  95. {
  96. // 严格校验参数数量
  97. if (args.Parameters.Length != 2)
  98. {
  99. throw new ArgumentException("In 必须传入 2 个参数:字符串、前缀");
  100. }
  101. // 安全获取参数值(避免 null)
  102. var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty;
  103. var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty;
  104. // 执行原生 EndsWith
  105. args.Result = str.Replace("[", "").Replace("]", "").Split(',').Contains(prefix);
  106. return;
  107. }
  108. // 方案1:精准匹配 IsNullOrEmpty
  109. if (funcName == "IsNullOrEmpty")
  110. {
  111. if (args.Parameters.Length != 1)
  112. {
  113. throw new ArgumentException("IsNullOrEmpty 必须传入 1 个参数:字符串");
  114. }
  115. var value = args.Parameters[0].Evaluate()?.ToString();
  116. args.Result = string.IsNullOrEmpty(value);
  117. return;
  118. }
  119. if (funcName == "ArrayLen")
  120. {
  121. if (args.Parameters.Length != 1)
  122. {
  123. throw new ArgumentException("ArrayLen 必须传入 1 个参数:数组");
  124. }
  125. var value = args.Parameters[0].Evaluate()?.ToString();
  126. args.Result = value?.Replace("[", "").Replace("]", "").Split(',').Length ?? 0;
  127. return;
  128. }
  129. if (funcName == "Match")
  130. {
  131. // 严格校验参数数量
  132. if (args.Parameters.Length != 2)
  133. {
  134. throw new ArgumentException("Match 必须传入 2 个参数:字符串、正则表达式");
  135. }
  136. // 安全获取参数值(避免 null)
  137. var str = args.Parameters[0].Evaluate()?.ToString() ?? string.Empty;
  138. var prefix = args.Parameters[1].Evaluate()?.ToString() ?? string.Empty;
  139. // 执行原生 StartsWith
  140. args.Result = Regex.IsMatch(str, prefix);
  141. return;
  142. }
  143. // 未找到函数时明确报错
  144. throw new ArgumentException($"未定义函数:{funcName}");
  145. }
  146. }