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
}
}