using Serein.Library.Api; using Serein.Library.Utils; using System.Collections.Concurrent; namespace Serein.Library.Core { /// /// 动态流程上下文 /// public class DynamicContext : IDynamicContext { /// /// 动态流程上下文 /// /// public DynamicContext(IFlowEnvironment flowEnvironment) { Env = flowEnvironment; RunState = RunState.Running; } private readonly string _guid = global::System.Guid.NewGuid().ToString(); string IDynamicContext.Guid => _guid; /// /// 运行环境 /// public IFlowEnvironment Env { get; } /// /// 运行状态 /// public RunState RunState { get; set; } = RunState.NoStart; /// /// 用来在当前流程上下文间传递数据 /// //public Dictionary ContextShareData { get; } = new Dictionary(); public object Tag { get; set; } /// /// 当前节点执行完成后,设置该属性,让运行环境判断接下来要执行哪个分支的节点。 /// public ConnectionInvokeType NextOrientation { get; set; } /// /// 运行时异常信息 /// public Exception ExceptionOfRuning { get; set; } /// /// 每个流程上下文分别存放节点的当前数据 /// private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); /// /// 每个流程上下文存储运行时节点的调用关系 /// private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary(); /// /// 设置运行时上一节点 /// /// 当前节点 /// 上一节点 public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode) { dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (_, _) => PreviousNode); } /// /// 获取当前节点的运行时上一节点 /// /// /// public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel) { if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node)) { return node; } else { return null; } } /// /// 获取节点当前数据 /// /// 节点 /// public object? GetFlowData(string nodeGuid) { if (dictNodeFlowData.TryGetValue(nodeGuid, out var data)) { return data; } else { return null; } } /// /// 添加或更新当前节点数据 /// /// 节点 /// 新的数据 public void AddOrUpdate(string nodeGuid, object? flowData) { // this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData); dictNodeFlowData.AddOrUpdate(nodeGuid, _ => flowData, (_, _) => flowData); } /// /// 上一节点数据透传到下一节点 /// /// public object? TransmissionData(NodeModelBase nodeModel) { if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点 { if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据 { return data; //AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中 } } return null; } /// /// 结束流程 /// public void Exit() { foreach (var nodeObj in dictNodeFlowData.Values) { if (nodeObj is not null) { if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable) { disposable?.Dispose(); } } else { } } if (Tag != null && typeof(IDisposable).IsAssignableFrom(Tag?.GetType()) && Tag is IDisposable tagDisposable) { tagDisposable?.Dispose(); } this.Tag = null; this.dictNodeFlowData?.Clear(); RunState = RunState.Completion; } private void Dispose(ref IDictionary keyValuePairs) { foreach (var nodeObj in keyValuePairs.Values) { if (nodeObj is null) { continue; } if (nodeObj is IDisposable disposable) /* typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) &&*/ { disposable?.Dispose(); } else if (nodeObj is IDictionary tmpDict) { Dispose(ref tmpDict); } else if (nodeObj is ICollection tmpList) { Dispose(ref tmpList); } else if (nodeObj is IList tmpList2) { Dispose(ref tmpList2); } } keyValuePairs.Clear(); } private void Dispose(ref ICollection list) { foreach (var nodeObj in list) { if (nodeObj is null) { continue; } if (nodeObj is IDisposable disposable) /* typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) &&*/ { disposable?.Dispose(); } else if (nodeObj is IDictionary tmpDict) { Dispose(ref tmpDict); } else if (nodeObj is ICollection tmpList) { Dispose(ref tmpList); } else if (nodeObj is IList tmpList2) { Dispose(ref tmpList2); } } list.Clear(); } private void Dispose(ref IList list) { foreach (var nodeObj in list) { if (nodeObj is null) { continue; } if (nodeObj is IDisposable disposable) /* typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) &&*/ { disposable?.Dispose(); } else if (nodeObj is IDictionary tmpDict) { Dispose(ref tmpDict); } else if (nodeObj is ICollection tmpList) { Dispose(ref tmpList); } else if (nodeObj is IList tmpList2) { Dispose(ref tmpList2); } } list.Clear(); } } }