逻辑规则和CAN结合的更改

This commit is contained in:
2025-04-23 20:57:54 +08:00
parent a7fc676b82
commit 0aee140e3f
10 changed files with 194 additions and 166 deletions

View File

@@ -42,7 +42,7 @@ namespace CapMachine.Wpf.Services
/// Key: 规则名称, Value: 已编译的Lambda表达式
///private readonly ConcurrentDictionary<string, Func<double, double>> _expressionCache;
/// </summary>
private readonly ConcurrentDictionary<string, Lambda> _expressionCache;
private readonly ConcurrentDictionary<string, Func<double, double>> _expressionCache;
///// <summary>
///// 创建包含指定值的参数数组
@@ -60,7 +60,7 @@ namespace CapMachine.Wpf.Services
/// </summary>
private Parameter CreateParameters(double value)
{
return new Parameter("value", typeof(double),value);
return new Parameter("value", typeof(double), value);
}
@@ -76,13 +76,10 @@ namespace CapMachine.Wpf.Services
// 初始化集合
LogicRuleDtos = new ObservableCollection<LogicRuleDto>();
_expressionCache = new ConcurrentDictionary<string, Lambda>();
_expressionCache = new ConcurrentDictionary<string, Func<double, double>>();
// 初始化DynamicExpresso解释器
CurInterpreter = new Interpreter();
//.Reference(typeof(Math)) // 引用Math类
// //.SetVariable("Math", typeof(Math))
//.SetVariable("value", 0.2);
try
{
@@ -228,7 +225,7 @@ namespace CapMachine.Wpf.Services
/// 更新规则
/// </summary>
/// <param name="rule">规则对象</param>
public void UpdateRule(LogicRule rule)
public void UpdateRule(LogicRule ruleOld,LogicRule rule)
{
if (string.IsNullOrWhiteSpace(rule.Name))
{
@@ -269,8 +266,8 @@ namespace CapMachine.Wpf.Services
LogicRuleDtos.Insert(insertIndex - 1, Mapper.Map<LogicRuleDto>(rule));
}
_expressionCache.TryRemove(updatedDto.Name, out _);
//有可能更改的是名称那么新名称的话在_expressionCache中肯定是找不到的,可以用之前的ruleOld
_expressionCache.TryRemove(ruleOld.Name!, out _);
CacheExpression(updatedDto);
}
}
@@ -412,39 +409,6 @@ namespace CapMachine.Wpf.Services
return rule;
}
/// <summary>
/// 应用逻辑转换 - 主要使用方法
/// </summary>
/// <param name="value">输入值</param>
/// <param name="ruleName">规则名称</param>
/// <returns>转换后的输出值</returns>
public double ApplyLogic(double value, string ruleName)
{
var rule = GetRuleByName(ruleName);
return ApplyExpression(value, rule);
}
/// <summary>
/// 应用逻辑转换(基于参数类型自动选择规则)
/// </summary>
/// <param name="value">输入值</param>
/// <param name="parameterType">参数类型</param>
/// <returns>转换后的输出值</returns>
public double ApplyLogicByType(double value, string parameterType)
{
var rules = GetRulesByParameterType(parameterType).ToList();
if (rules.Count == 0)
{
LogService.Warn($"未找到适用于 {parameterType} 的转换规则,将返回原始值");
return value;
}
// 如果存在多个规则,取第一个
var rule = rules.First();
return ApplyExpression(value, rule);
}
/// <summary>
/// 将规则表达式预编译并缓存到字典中
@@ -459,13 +423,17 @@ namespace CapMachine.Wpf.Services
try
{
// ****如下步骤很重要,尝试了很多次才正常运行****
// 使用已有的CreateParameters方法创建参数声明
var parameter = CreateParameters(0); // 值不重要,只是为了获取参数声明
// 只解析一次,得到 Lambda 对象
var lambda = CurInterpreter.Parse(rule.Expression, parameter); // 只定义参数类型,不传值
// 编译为强类型委托
var compiledFunc = lambda.Compile<Func<double, double>>();
// 存入缓存
_expressionCache[rule.Name] = lambda;
_expressionCache[rule.Name] = compiledFunc;
}
catch (Exception ex)
{
@@ -557,114 +525,54 @@ namespace CapMachine.Wpf.Services
/// <summary>
/// 临时测试用
/// 快速的执行数据
/// </summary>
/// <param name="value"></param>
/// <param name="rule"></param>
/// <returns></returns>
public double ApplyExpressionNoCache(double value, LogicRuleDto rule)
public double ApplyExpressionFast(double value, LogicRuleDto rule)
{
try
{
if (!_expressionCache.TryGetValue(rule.Name, out var CurActiveFunc))
{
CacheExpression(rule);
if (!_expressionCache.TryGetValue(rule.Name, out CurActiveFunc))
return value;
}
CurInterpreter.SetVariable("value", value);
var lambda = CurInterpreter.Parse(rule.Expression);
return (double)lambda.Invoke();
//// 创建全新的解释器实例
//var localInterpreter = new Interpreter()
// .Reference(typeof(Math))
// .SetVariable("Math", typeof(Math));
//// 直接设置变量值而不是使用参数
//localInterpreter.SetVariable("value", value);
//// 解析并执行
//var result = localInterpreter.Eval<double>(rule.Expression);
//Console.WriteLine($"直接执行: 输入={value}, 表达式={rule.Expression}, 结果={result}");
//return result;
// 直接调用委托,无反射开销
return CurActiveFunc(value);
}
catch (Exception ex)
catch
{
LogService.Error($"直接执行表达式失败: {ex.Message}");
return value;
}
}
/// <summary>
/// 批量应用逻辑转换 (高性能版本)
/// 如果需要对多个数据应用相同规则,考虑实现批处理版本
/// </summary>
/// <param name="values">原始值字典(键为参数名称,值为原始值)</param>
/// <returns>转换后的值字典</returns>
public Dictionary<string, double> ApplyBatchLogic(Dictionary<string, double> values)
/// <param name="values"></param>
/// <param name="rule"></param>
/// <returns></returns>
public IEnumerable<double> ApplyExpressionBatch(IEnumerable<double> values, LogicRuleDto rule)
{
// 为了性能,预分配容量
var result = new Dictionary<string, double>(values.Count);
// 缓存参数类型到规则的映射,避免重复查询
var cachedRulesByType = new Dictionary<string, LogicRuleDto>();
foreach (var entry in values)
if (!_expressionCache.TryGetValue(rule.Name, out var func))
{
var paramName = entry.Key;
var origValue = entry.Value;
try
{
// 获取参数类型
var paramType = DetermineParameterType(paramName);
// 尝试从缓存获取规则
if (!cachedRulesByType.TryGetValue(paramType, out var rule))
{
var rules = GetRulesByParameterType(paramType).ToList();
if (rules.Count > 0)
{
rule = rules.First();
cachedRulesByType[paramType] = rule; // 添加到缓存
}
}
// 如果找到规则,应用转换
if (rule != null)
{
var convertedValue = ApplyExpression(origValue, rule);
result.Add(paramName, convertedValue);
}
else
{
result.Add(paramName, origValue); // 没有规则时使用原始值
}
}
catch (Exception ex)
{
LogService.Error($"处理参数 {paramName} 失败: {ex.Message}");
result.Add(paramName, origValue); // 出错时使用原始值
}
CacheExpression(rule);
if (!_expressionCache.TryGetValue(rule.Name, out func))
return values;
}
return result;
// 使用并行处理大量数据
return values.AsParallel().Select(v =>
{
try { return func(v); }
catch { return v; }
});
}
/// <summary>
/// 从参数名称确定参数类型
/// </summary>
/// <param name="paramName">参数名称</param>
/// <returns>参数类型</returns>
private string DetermineParameterType(string paramName)
{
// 根据参数名称确定类型的逻辑
// 这里使用简单的名称匹配,实际项目中可能需要更复杂的映射
if (paramName.Contains("速度") || paramName.Contains("转速"))
return "转速";
else if (paramName.Contains("功率") || paramName.Contains("pw") || paramName.Contains("power"))
return "功率";
else if (paramName.Contains("温度") || paramName.Contains("temp"))
return "温度";
else if (paramName.Contains("压力") || paramName.Contains("press"))
return "压力";
// 默认类型
return "通用";
}
}
}