using DynamicExpresso; using System; using System.Collections.Generic; using System.Globalization; namespace MesWork { /// /// 重量标定公式计算工具。 /// public static class WeightCalibrationHelper { private class CalibrationCache { public string ToolName; public string Formula; public string Description; public DateTime LoadedAt; } private static readonly object CacheLock = new object(); private static readonly Dictionary Cache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly TimeSpan CacheLife = TimeSpan.FromSeconds(3); public static bool Apply(string opName, decimal rawWeight, out decimal calibratedWeight, out string formula, out string message) { calibratedWeight = rawWeight; formula = "x"; message = ""; if (!TryGetConfig(opName, rawWeight, out CalibrationCache config, out string queryMsg)) { if (!string.IsNullOrWhiteSpace(queryMsg)) { message = queryMsg; return false; } formula = "x"; calibratedWeight = rawWeight; return true; } formula = NormalizeFormula(config.Formula); return TryEvaluateFormula(formula, rawWeight, out calibratedWeight, out message); } public static void ClearCache() { lock (CacheLock) { Cache.Clear(); } } public static bool ValidateFormula(string formula, out string message) { decimal _; return TryEvaluateFormula(NormalizeFormula(formula), 1M, out _, out message); } private static string NormalizeFormula(string formula) { return string.IsNullOrWhiteSpace(formula) ? "" : formula.Trim(); } private static bool TryEvaluateFormula(string formula, decimal xValue, out decimal result, out string message) { result = xValue; message = ""; if (string.IsNullOrWhiteSpace(formula)) { message = "计算公式不能为空,至少填写 x"; return false; } try { var interpreter = new Interpreter(); interpreter.Reference(typeof(Math)); double x = Convert.ToDouble(xValue); interpreter.SetVariable("x", x); interpreter.SetVariable("X", x); object value = interpreter.Eval(formula); if (value == null) { message = "计算公式未返回数值"; return false; } result = Convert.ToDecimal(value, CultureInfo.InvariantCulture); return true; } catch (Exception err) { message = $"计算公式错误:{err.Message}"; return false; } } private static bool TryGetConfig(string opName, decimal rawWeight, out CalibrationCache config, out string message) { config = null; message = ""; string station = string.IsNullOrWhiteSpace(opName) ? "" : opName.Trim(); string key = station + "|" + rawWeight.ToString("F3", CultureInfo.InvariantCulture); lock (CacheLock) { if (Cache.TryGetValue(key, out config) && DateTime.Now - config.LoadedAt < CacheLife) { return true; } } if (!B_DB_Opera.QueryToolCalibration(station, rawWeight, out string toolName, out string formula, out string description, out message)) { return false; } config = new CalibrationCache { ToolName = toolName, Formula = formula, Description = description, LoadedAt = DateTime.Now }; lock (CacheLock) { Cache[key] = config; } return true; } } }