using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Text.RegularExpressions; using TeamAAS.Communication; namespace TeamAAS.FlowEditor.Execution { /// /// 执行结果注册中心 - 存储各节点最新执行结果,支持 &{节点名.属性名} 公式解析 /// 内部结构: Dictionary>> /// 保留键 "Gloab" 用于存储全局变量 /// /// 实例化设计:主页面运行流程与产品管理编辑/调试流程使用各自独立的注册表实例, /// 避免 Debug 流程的清理/写入干扰运行中流程的结果缓存(导致内存释放异常)。 /// - :主页面的运行流程(FlowRunner)专用 /// - :产品管理编辑/调试流程专用 /// 产品管理进入监控模式时挂接的是主页面运行态流程,其 Graph.Registry 指向 Main, /// 因此公式解析/结果读取会自动落到主面对象上。 /// public class ResultRegistry { /// 主页面运行流程专用注册表 public static ResultRegistry Main { get; } = new ResultRegistry(); /// 产品管理编辑/调试流程专用注册表 public static ResultRegistry Debug { get; } = new ResultRegistry(); public const string GlobalVariablesKey = "Gloab"; public readonly Dictionary>> _store = new Dictionary>>(); private readonly object _lock = new object(); private bool _initialized; /// /// 初始化所有注册表实例:订阅全局变量变化事件,自动刷新 ResultRegistry /// public static void Initialize() { Main.InitializeInstance(); Debug.InitializeInstance(); } /// /// 刷新所有注册表实例的全局变量区(全局变量为进程级共享数据) /// public static void RefreshGlobals() { Main.RefreshGlobalVariables(); Debug.RefreshGlobalVariables(); } /// /// 初始化:订阅全局变量变化事件,自动刷新本注册表 /// public void InitializeInstance() { if (_initialized) return; _initialized = true; GlobalVariableManager.Instance.VariablesChanged += RefreshGlobalVariables; RefreshGlobalVariables(); } /// /// 设置节点最新执行结果 /// public void SetResult(string graphId, string nodeid, string nodeName, Dictionary results) { if (string.IsNullOrEmpty(graphId) || string.IsNullOrEmpty(nodeName)) return; lock (_lock) { if (!_store.TryGetValue(graphId, out var flowDict)) { flowDict = new Dictionary>(); _store[graphId] = flowDict; } flowDict[nodeName] = results ?? new Dictionary(); } } /// /// 向指定流程的「输入」虚拟节点写入单个变量(供 &{输入.变量名} 2段式解析) /// public void SetInputVariable(string graphId, string varName, object value) { if (string.IsNullOrEmpty(graphId) || string.IsNullOrEmpty(varName)) return; lock (_lock) { if (!_store.TryGetValue(graphId, out var flowDict)) { flowDict = new Dictionary>(); _store[graphId] = flowDict; } if (!flowDict.TryGetValue("输入", out var inputDict)) { inputDict = new Dictionary(); flowDict["输入"] = inputDict; } inputDict[varName] = value; } } /// /// 获取指定流程下所有节点的结果 /// public void GetFlowResults(string graphId, out Dictionary> flowResults) { flowResults = new Dictionary>(); if (string.IsNullOrEmpty(graphId)) return; lock (_lock) { if (_store.TryGetValue(graphId, out var dict)) { foreach (var kvp in dict) flowResults[kvp.Key] = kvp.Value; } } } /// /// 获取节点最新结果字典 /// public Dictionary GetResult(string graphId, string nodeName) { lock (_lock) { if (_store.TryGetValue(graphId, out var flowDict) && flowDict.TryGetValue(nodeName, out var dict)) return dict; } return null; } /// /// 获取节点某个属性值 /// public object GetValue(string graphId, string nodeName, string propertyName) { lock (_lock) { if (_store.TryGetValue(graphId, out var flowDict) && flowDict.TryGetValue(nodeName, out var dict) && dict.TryGetValue(propertyName, out var val)) return val; } return null; } /// /// 刷新全局变量到 _store["Gloab"] /// public void RefreshGlobalVariables() { var vars = GlobalVariableManager.Instance.Variables; lock (_lock) { if (!_store.TryGetValue(GlobalVariablesKey, out var gloabDict)) { gloabDict = new Dictionary>(); _store[GlobalVariablesKey] = gloabDict; } gloabDict.Clear(); foreach (var v in vars) { if (string.IsNullOrWhiteSpace(v.Name)) continue; gloabDict[v.Name] = new Dictionary { ["Value"] = v.Value, ["DataType"] = v.DataType, ["Note"] = v.Note ?? "" }; } } } /// /// 解析公式 &{节点名.属性名}(2段式)或 &{流程名.节点名.属性名}(3段式) /// 特殊支持 &{Gloab.变量名} 直接获取全局变量值(2段式),或 &{Gloab.变量名.Value}(3段式) /// public object ResolveFormula(string FlowId, string formula) { if (string.IsNullOrEmpty(formula)) return formula; var match2 = Regex.Match(formula, @"^&\{(?[^.}]+)\.(?[^.}]+)\}$"); var match3 = Regex.Match(formula, @"^&\{(?[^.}]+)\.(?[^.}]+)\.(?[^.}]+)\}$"); if (match2.Success) { string first = match2.Groups["node"].Value; string second = match2.Groups["prop"].Value; if (first == GlobalVariablesKey) { return GetValue(GlobalVariablesKey, second, "Value"); } var result = GetValue(FlowId, first, second); return result; } else if (match3.Success) { string flow = match3.Groups["flow"].Value; string node = match3.Groups["node"].Value; string prop = match3.Groups["prop"].Value; if (flow == GlobalVariablesKey) { return GetValue(GlobalVariablesKey, node, prop); } return GetValue(flow, node, prop); } else return formula; } /// /// 删除指定流程中某个节点的执行结果 /// public void RemoveNodeResult(string graphId, string nodeName) { if (string.IsNullOrEmpty(graphId) || string.IsNullOrEmpty(nodeName)) return; lock (_lock) { if (_store.TryGetValue(graphId, out var flowDict)) flowDict.Remove(nodeName); } } /// /// 清空指定流程的所有结果 /// public void ClearFlow(string graphId) { if (string.IsNullOrEmpty(graphId)) return; lock (_lock) { _store.Remove(graphId); } } /// /// 完全释放所有流程数据(各流程 GraphId 及其子流程 SubGraphId 条目全部移除),仅保留全局变量区。 /// ClearFlow 只按单个 GraphId 清理,会漏掉组合/循环子流程写入的 SubGraphId 条目; /// 切换/重载产品、进出监控时用本方法彻底清干净,避免上次产品的数据残留堆积。 /// public void ClearAllFlows() { lock (_lock) { var flowKeys = _store.Keys.Where(k => k != GlobalVariablesKey).ToList(); foreach (var key in flowKeys) _store.Remove(key); } } /// /// 清空所有结果 /// public void Clear() { lock (_lock) { _store.Clear(); } } #region 调试监控(供主页“注册表监控”窗口的 PropertyGrid 直接绑定 Main / Debug 显示) /// 【监控】当前缓存的流程数(不含全局变量区)。若 Debug 持续增长而不回落,通常意味着清理没做好。 [Category("注册表监控")] [DisplayName("流程数")] [ReadOnly(true)] public int FlowCount { get { lock (_lock) return _store.Keys.Count(k => k != GlobalVariablesKey); } } /// 【监控】缓存的流程 GraphId 列表(逗号分隔)。 [Category("注册表监控")] [DisplayName("流程ID列表")] [ReadOnly(true)] public string FlowIds { get { lock (_lock) return string.Join(", ", _store.Keys.Where(k => k != GlobalVariablesKey)); } } /// 【监控】全局变量条目数。 [Category("注册表监控")] [DisplayName("全局变量数")] [ReadOnly(true)] public int GlobalVariableCount { get { lock (_lock) return _store.TryGetValue(GlobalVariablesKey, out var g) ? g.Count : 0; } } /// 【监控】是否已初始化(已订阅全局变量变化事件)。 [Category("注册表监控")] [DisplayName("已初始化")] [ReadOnly(true)] public bool IsInitialized { get { lock (_lock) return _initialized; } } /// /// 【监控】完整内容快照(多行文本):流程 → 节点 → 结果键值,用于排查 Main / Debug 是否被正确管理。 /// 大对象(图像 / CogRecord 等)只显示类型名,避免 ToString 噪音。 /// [Category("注册表监控")] [DisplayName("内容快照")] [ReadOnly(true)] public string Snapshot { get { lock (_lock) { var sb = new StringBuilder(); foreach (var flow in _store) { if (flow.Key == GlobalVariablesKey) { sb.AppendLine($"[全局变量 Gloab] {flow.Value.Count} 项"); foreach (var v in flow.Value) { object gv = v.Value != null && v.Value.TryGetValue("Value", out var raw) ? raw : null; sb.AppendLine($" {v.Key} = {DescribeValue(gv)}"); } continue; } sb.AppendLine($"[流程 {flow.Key}] 节点 {flow.Value.Count} 个"); foreach (var node in flow.Value) { sb.AppendLine($" · {node.Key}({node.Value.Count} 项)"); foreach (var kv in node.Value) sb.AppendLine($" {kv.Key} = {DescribeValue(kv.Value)}"); } } return sb.Length == 0 ? "(空)" : sb.ToString(); } } } /// 监控快照的值格式化:基础类型直接 ToString,集合显示项数,其余大对象只显示类型名。 private static string DescribeValue(object v) { if (v == null) return "null"; var t = v.GetType(); bool basic = t.IsPrimitive || v is string || v is decimal || v is DateTime || t.IsEnum; if (basic) return v.ToString(); if (v is System.Collections.IEnumerable en) { int c = 0; foreach (var _ in en) c++; return $"{t.Name}({c} 项)"; } return t.Name; } #endregion } }