ExpressionResolver.cs
4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Data;
using System.Text.RegularExpressions;
using Rcs.Domain.Entities;
using Rcs.Domain.Enums;
using Rcs.Domain.Models;
using Rcs.Domain.Services;
using Rcs.Shared.Utils;
namespace Rcs.Infrastructure.Services.ParameterResolvers
{
/// <summary>
/// 表达式解析器 - 支持变量替换和算术运算
/// 语法示例:
/// - 简单变量:${Node.LayerHeight}
/// - 算术运算:${Node.LayerHeight} * ${Node.LayerCount} + 50
/// - 字符串拼接:${Task.TaskCode}_${Robot.RobotCode}
/// @author zzy
/// </summary>
public class ExpressionResolver : IParameterValueResolver
{
public ParameterSourceType SourceType => ParameterSourceType.Context;
/// <summary>
/// 变量占位符正则表达式:匹配 ${Source.Path} 格式
/// </summary>
private static readonly Regex PlaceholderRegex = new(
@"\$\{(\w+)\.([^}]+)\}",
RegexOptions.Compiled);
/// <summary>
/// 算术运算符检测
/// </summary>
private static readonly char[] ArithmeticOperators = { '+', '-', '*', '/', '%', '(', ')' };
public object? Resolve(ActionParameterDefinition definition, ParameterContext context)
{
var expression = definition.ParameterSourcePath;
if (string.IsNullOrEmpty(expression))
return definition.DefaultValue;
// 1. 替换所有变量占位符为实际值
var resolvedExpr = PlaceholderRegex.Replace(expression, match =>
{
var sourceName = match.Groups[1].Value; // Task, Robot, Node, Edge, Extra
var path = match.Groups[2].Value; // 属性路径
var source = GetSourceObject(context, sourceName);
var value = PropertyPathResolver.GetValue(source, path);
// 数值类型返回数字字符串,其他类型返回原始字符串
return value?.ToString() ?? "0";
});
// 2. 判断是否包含算术运算符
if (ContainsArithmeticOperator(resolvedExpr))
{
return EvaluateArithmeticExpression(resolvedExpr);
}
// 3. 非算术表达式,直接返回替换后的字符串
return resolvedExpr;
}
/// <summary>
/// 根据来源名称获取上下文中的对象
/// </summary>
private static object? GetSourceObject(ParameterContext context, string sourceName)
{
return sourceName.ToUpperInvariant() switch
{
"TASK" => context.Task,
"ROBOT" => context.Robot,
"NODE" => context.Node,
"EDGE" => context.Edge,
"EXTRA" => context.Extra,
_ => null
};
}
/// <summary>
/// 检测表达式是否包含算术运算符
/// </summary>
private static bool ContainsArithmeticOperator(string expression)
{
return expression.IndexOfAny(ArithmeticOperators) >= 0;
}
/// <summary>
/// 计算算术表达式
/// 使用 DataTable.Compute 方法,支持 +, -, *, /, %, 括号
/// </summary>
private static object? EvaluateArithmeticExpression(string expression)
{
try
{
// 清理表达式中的空格
var cleanExpr = expression.Trim();
// 使用 DataTable.Compute 计算表达式
var table = new DataTable();
var result = table.Compute(cleanExpr, string.Empty);
// 转换为 double 类型
if (result != null && result != DBNull.Value)
{
return Convert.ToDouble(result);
}
return null;
}
catch (Exception)
{
// 计算失败,返回原始表达式
return expression;
}
}
}
}