BOB/Common/Tool/ExpressionEvaluator.cs
2025-11-11 13:29:56 +08:00

104 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NCalc;
namespace Common.Tools
{
public class ExpressionEvaluator
{
public static bool EvaluateExpression(string expression, Dictionary<string, object>? variables = null)
{
try
{
// 预处理:替换中文变量名为英文别名
var (processedExpression, processedVariables) = PreprocessExpression(expression, variables);
var expr = new Expression(processedExpression, EvaluateOptions.IgnoreCase);
if (processedVariables != null)
{
foreach (var kvp in processedVariables)
{
expr.Parameters[kvp.Key] = kvp.Value;
}
}
if (expr.HasErrors())
{
throw new ArgumentException($"条件表达式格式错误: {expr.Error}");
}
var result = expr.Evaluate();
return Convert.ToBoolean(result);
}
catch (Exception ex)
{
throw new ArgumentException($"条件表达式异常: {ex.Message}");
}
}
private static (string, Dictionary<string, object>) PreprocessExpression(
string expression,
Dictionary<string, object>? variables)
{
if (variables == null || variables.Count == 0)
return (expression, variables ?? new Dictionary<string, object>());
// 生成变量名映射 (中文 -> 英文别名)
var chineseToAlias = new Dictionary<string, string>();
var aliasToValue = new Dictionary<string, object>();
int counter = 1;
foreach (var key in variables.Keys)
{
if (ContainsChinese(key))
{
string alias = $"var_{counter}";
counter++;
chineseToAlias[key] = alias;
aliasToValue[alias] = variables[key];
}
}
// 如果没有中文变量名,直接返回原始数据
if (chineseToAlias.Count == 0)
return (expression, variables);
// 替换表达式中的中文变量名
string processedExpression = expression;
foreach (var pair in chineseToAlias)
{
// 使用正则确保完整匹配变量名
string pattern = $@"\b{Regex.Escape(pair.Key)}\b";
processedExpression = Regex.Replace(
processedExpression,
pattern,
pair.Value,
RegexOptions.Compiled
);
}
// 创建新变量字典(英文别名 + 原始英文变量)
var newVariables = new Dictionary<string, object>(aliasToValue);
foreach (var key in variables.Keys)
{
if (!ContainsChinese(key))
{
newVariables[key] = variables[key];
}
}
return (processedExpression, newVariables);
}
// 检查字符串是否包含中文字符
private static bool ContainsChinese(string text)
{
return text.Any(c => c >= 0x4E00 && c <= 0x9FFF);
}
}
}