using Newtonsoft.Json.Linq; using Serein.Library.Api; using Serein.Library.Attributes; using Serein.Library.Entity; using Serein.Library.Enums; using Serein.Library.Utils; using Serein.NodeFlow.Base; using Serein.NodeFlow.Model; using Serein.NodeFlow.Tool; using System.Collections; using System.Collections.Concurrent; using System.Reflection; using System.Xml.Linq; using static Serein.Library.Utils.ChannelFlowInterrupt; using static Serein.NodeFlow.FlowStarter; namespace Serein.NodeFlow { /* 脱离wpf平台独立运行。 加载文件。 创建节点对象,设置节点属性,确定连接关系,设置起点。 ↓抽象↓ wpf依赖于运行环境,而不是运行环境依赖于wpf。 运行环境实现以下功能: ①从项目文件加载数据,生成项目文件对象。 ②运行项目,调试项目,中止项目,终止项目。 ③自动包装数据类型,在上下文中传递数据。 */ /// /// 运行环境 /// public class FlowEnvironment : IFlowEnvironment, ISereinIOC { public FlowEnvironment() { sereinIOC = new SereinIOC(); ChannelFlowInterrupt = new ChannelFlowInterrupt(); LoadedAssemblyPaths = new List(); LoadedAssemblies = new List(); MethodDetailss = new List(); Nodes = new Dictionary(); FlipflopNodes = new List(); IsGlobalInterrupt = false; flowStarter = null; sereinIOC.OnIOCMembersChanged += e => this?.OnIOCMembersChanged?.Invoke(e) ; // 监听IOC容器的注册 } /// /// 节点的命名空间 /// public const string SpaceName = $"{nameof(Serein)}.{nameof(Serein.NodeFlow)}.{nameof(Serein.NodeFlow.Model)}"; #region 环境接口事件 /// /// 加载Dll /// public event LoadDLLHandler OnDllLoad; /// /// 项目加载完成 /// public event ProjectLoadedHandler OnProjectLoaded; /// /// 节点连接属性改变事件 /// public event NodeConnectChangeHandler OnNodeConnectChange; /// /// 节点创建事件 /// public event NodeCreateHandler OnNodeCreate; /// /// 移除节点事件 /// public event NodeRemoteHandler OnNodeRemote; /// /// 起始节点变化事件 /// public event StartNodeChangeHandler OnStartNodeChange; /// /// 流程运行完成事件 /// public event FlowRunCompleteHandler OnFlowRunComplete; /// /// 被监视的对象改变事件 /// public event MonitorObjectChangeHandler OnMonitorObjectChange; /// /// 节点中断状态改变事件 /// public event NodeInterruptStateChangeHandler OnNodeInterruptStateChange; /// /// 节点触发了中断 /// public event ExpInterruptTriggerHandler OnInterruptTrigger; /// /// 容器改变 /// public event IOCMembersChangedHandler OnIOCMembersChanged; #endregion #region 属性 /// /// 环境名称 /// public string EnvName { get; set; } = SpaceName; /// /// 是否全局中断 /// public bool IsGlobalInterrupt { get; set; } /// /// 流程中断器 /// public ChannelFlowInterrupt ChannelFlowInterrupt { get; set; } public ISereinIOC IOC { get => this; } #endregion #region 私有变量 /// /// 容器管理 /// private readonly SereinIOC sereinIOC; /// /// 存储加载的程序集路径 /// private List LoadedAssemblyPaths { get; } /// /// 存储加载的程序集 /// private List LoadedAssemblies { get; } /// /// 存储所有方法信息 /// private List MethodDetailss { get; } /// /// 环境加载的节点集合 /// private Dictionary Nodes { get; } /// /// 存放触发器节点(运行时全部调用) /// private List FlipflopNodes { get; } /// /// 起始节点私有属性 /// private NodeModelBase _startNode; /// /// 起始节点 /// private NodeModelBase StartNode { get { return _startNode; } set { if (_startNode is not null) { _startNode.IsStart = false; } value.IsStart = true; _startNode = value; } } /// /// 流程启动器(每次运行时都会重新new一个) /// private FlowStarter? flowStarter; #endregion #region 对外暴露的接口 /// /// 异步运行 /// /// public async Task StartAsync() { ChannelFlowInterrupt?.CancelAllTasks(); flowStarter = new FlowStarter(); var nodes = Nodes.Values.ToList(); List initMethods; List loadingMethods; List exitMethods; initMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Init).ToList(); loadingMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Loading).ToList(); exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList(); await flowStarter.RunAsync(this, nodes, initMethods, loadingMethods, exitMethods); if (flowStarter?.FlipFlopState == RunState.NoStart) { this.Exit(); // 未运行触发器时,才会调用结束方法 } flowStarter = null; } public async Task StartFlowInSelectNodeAsync(string startNodeGuid) { if (flowStarter is null) { return; } if (flowStarter.FlowState == RunState.Running || flowStarter.FlipFlopState == RunState.Running) { NodeModelBase? nodeModel = GuidToModel(startNodeGuid); if (nodeModel is null || nodeModel is SingleFlipflopNode) { return; } await flowStarter.StartFlowInSelectNodeAsync(nodeModel); } else { return; } } /// /// 退出 /// public void Exit() { ChannelFlowInterrupt?.CancelAllTasks(); flowStarter?.Exit(); foreach (var node in Nodes.Values) { if (node is not null) { node.ReleaseFlowData(); // 退出时释放对象计数 } } OnFlowRunComplete?.Invoke(new FlowEventArgs()); GC.Collect(); } /// /// 清除所有 /// public void ClearAll() { LoadedAssemblyPaths.Clear(); LoadedAssemblies.Clear(); MethodDetailss.Clear(); } /// /// 加载项目文件 /// /// /// public void LoadProject(SereinProjectData project, string filePath) { // 加载项目配置文件 var dllPaths = project.Librarys.Select(it => it.Path).ToList(); List methodDetailss = []; // 遍历依赖项中的特性注解,生成方法详情 foreach (var dll in dllPaths) { var dllFilePath = System.IO.Path.GetFullPath(System.IO.Path.Combine(filePath, dll)); (var assembly, var list) = LoadAssembly(dllFilePath); if (assembly is not null && list.Count > 0) { MethodDetailss.AddRange(list); // 暂存方法描述 OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list)); // 通知UI创建dll面板显示 } } // 方法加载完成,缓存到运行环境中。 //MethodDetailss.AddRange(methodDetailss); //methodDetailss.Clear(); List<(NodeModelBase, string[])> regionChildNodes = new List<(NodeModelBase, string[])>(); List<(NodeModelBase, Position)> ordinaryNodes = new List<(NodeModelBase, Position)>(); // 加载节点 foreach (var nodeInfo in project.Nodes) { var controlType = GetNodeControlType(nodeInfo); if (controlType == NodeControlType.None) { continue; } else { TryGetMethodDetails(nodeInfo.MethodName, out MethodDetails? methodDetails); // 加载项目时尝试获取方法信息 if(controlType == NodeControlType.ExpOp || controlType == NodeControlType.ExpOp) { methodDetails ??= new MethodDetails(); } if(methodDetails is null) { continue; // 节点对应的方法不存在于DLL中 } var nodeModel = CreateNode(controlType, methodDetails); nodeModel.LoadInfo(nodeInfo); // 创建节点model if (nodeModel is null) { nodeInfo.Guid = string.Empty; continue; } TryAddNode(nodeModel); if (nodeInfo.ChildNodeGuids?.Length > 0) { regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids)); OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position)); } else { ordinaryNodes.Add((nodeModel, nodeInfo.Position)); } } } // 加载区域的子项 foreach ((NodeModelBase region, string[] childNodeGuids) item in regionChildNodes) { foreach (var childNodeGuid in item.childNodeGuids) { Nodes.TryGetValue(childNodeGuid, out NodeModelBase? childNode); if (childNode is null) { // 节点尚未加载 continue; } // 存在节点 OnNodeCreate?.Invoke(new NodeCreateEventArgs(childNode, true, item.region.Guid)); } } // 加载节点 foreach ((NodeModelBase nodeModel, Position position) item in ordinaryNodes) { bool IsContinue = false; foreach ((NodeModelBase region, string[] childNodeGuids) item2 in regionChildNodes) { foreach (var childNodeGuid in item2.childNodeGuids) { if (item.nodeModel.Guid.Equals(childNodeGuid)) { IsContinue = true; } } } if (IsContinue) continue; OnNodeCreate?.Invoke(new NodeCreateEventArgs(item.nodeModel, item.position)); } // 确定节点之间的连接关系 foreach (var nodeInfo in project.Nodes) { if (!Nodes.TryGetValue(nodeInfo.Guid, out NodeModelBase? fromNode)) { // 不存在对应的起始节点 continue; } List<(ConnectionType connectionType, string[] guids)> allToNodes = [(ConnectionType.IsSucceed,nodeInfo.TrueNodes), (ConnectionType.IsFail, nodeInfo.FalseNodes), (ConnectionType.IsError, nodeInfo.ErrorNodes), (ConnectionType.Upstream, nodeInfo.UpstreamNodes)]; List<(ConnectionType, NodeModelBase[])> fromNodes = allToNodes.Where(info => info.guids.Length > 0) .Select(info => (info.connectionType, info.guids.Where(guid => Nodes.ContainsKey(guid)).Select(guid => Nodes[guid]) .ToArray())) .ToList(); // 遍历每种类型的节点分支(四种) foreach ((ConnectionType connectionType, NodeModelBase[] toNodes) item in fromNodes) { // 遍历当前类型分支的节点(确认连接关系) foreach (var toNode in item.toNodes) { ConnectNode(fromNode, toNode, item.connectionType); // 加载时确定节点间的连接关系 } } } SetStartNode(project.StartNode); OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs()); } /// /// 保存项目为项目文件 /// /// public SereinProjectData SaveProject() { var projectData = new SereinProjectData() { Librarys = LoadedAssemblies.Select(assemblies => assemblies.ToLibrary()).ToArray(), Nodes = Nodes.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(), StartNode = Nodes.Values.FirstOrDefault(it => it.IsStart)?.Guid, }; return projectData; } /// /// 从文件路径中加载DLL /// /// /// public void LoadDll(string dllPath) { (var assembly, var list) = LoadAssembly(dllPath); if (assembly is not null && list.Count > 0) { MethodDetailss.AddRange(list); OnDllLoad?.Invoke(new LoadDLLEventArgs(assembly, list)); } } /// /// 运行时创建节点 /// /// public void CreateNode(NodeControlType nodeControlType, Position position, MethodDetails? methodDetails = null) { var nodeModel = CreateNode(nodeControlType, methodDetails); TryAddNode(nodeModel); if (flowStarter?.FlowState != RunState.Completion && nodeControlType == NodeControlType.Flipflop && nodeModel is SingleFlipflopNode flipflopNode) { // 当前添加节点属于触发器,且当前正在运行,则加载到运行环境中 flowStarter?.AddFlipflopInRuning(flipflopNode, this); } // 通知UI更改 OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position)); // 因为需要UI先布置了元素,才能通知UI变更特效 // 如果不存在流程起始控件,默认设置为流程起始控件 if (StartNode is null) { SetStartNode(nodeModel); } } /// /// 移除节点 /// /// /// public void RemoteNode(string nodeGuid) { var remoteNode = GuidToModel(nodeGuid); if (remoteNode is null) return; if (remoteNode.IsStart) { return; } // 遍历所有父节点,从那些父节点中的子节点集合移除该节点 foreach (var pnc in remoteNode.PreviousNodes) { var pCType = pnc.Key; // 连接类型 for (int i = 0; i < pnc.Value.Count; i++) { NodeModelBase? pNode = pnc.Value[i]; //pNode.SuccessorNodes[pCType].RemoveAt(i); pNode.SuccessorNodes[pCType].Remove(pNode); OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(pNode.Guid, remoteNode.Guid, pCType, NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI } } // 遍历所有子节点,从那些子节点中的父节点集合移除该节点 foreach (var snc in remoteNode.SuccessorNodes) { var connectionType = snc.Key; // 连接类型 for (int i = 0; i < snc.Value.Count; i++) { NodeModelBase? toNode = snc.Value[i]; RemoteConnect(remoteNode, toNode, connectionType); } } // 从集合中移除节点 Nodes.Remove(nodeGuid); OnNodeRemote?.Invoke(new NodeRemoteEventArgs(nodeGuid)); } /// /// 连接节点 /// /// 起始节点 /// 目标节点 /// 连接关系 public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType) { // 获取起始节点与目标节点 var fromNode = GuidToModel(fromNodeGuid); var toNode = GuidToModel(toNodeGuid); if (fromNode is null) return; if (toNode is null) return; // 开始连接 ConnectNode(fromNode, toNode, connectionType); // 外部调用连接方法 } /// /// 移除连接关系 /// /// 起始节点Guid /// 目标节点Guid /// 连接关系 /// public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType) { // 获取起始节点与目标节点 var fromNode = GuidToModel(fromNodeGuid); var toNode = GuidToModel(toNodeGuid); if (fromNode is null) return; if (toNode is null) return; RemoteConnect(fromNode, toNode, connectionType); } /// /// 移除连接关系 /// /// 起始节点Model /// 目标节点Model /// 连接关系 /// private void RemoteConnect(NodeModelBase fromNode, NodeModelBase toNode, ConnectionType connectionType) { fromNode.SuccessorNodes[connectionType].Remove(toNode); toNode.PreviousNodes[connectionType].Remove(fromNode); if (toNode is SingleFlipflopNode flipflopNode) { if (flowStarter?.FlowState != RunState.Completion && flipflopNode.NotExitPreviousNode()) { // 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中 flowStarter?.AddFlipflopInRuning(flipflopNode, this); } } // 通知UI OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid, toNode.Guid, connectionType, NodeConnectChangeEventArgs.ConnectChangeType.Remote)); } /// /// 获取方法描述 /// public bool TryGetMethodDetails(string name, out MethodDetails? md) { if (!string.IsNullOrEmpty(name)) { md = MethodDetailss.FirstOrDefault(it => it.MethodName == name); return md != null; } else { md = null; return false; } } /// /// 设置起点控件 /// /// public void SetStartNode(string newNodeGuid) { var newStartNodeModel = GuidToModel(newNodeGuid); if (newStartNodeModel is null) return; SetStartNode(newStartNodeModel); } /// /// 中断指定节点,并指定中断等级。 /// /// 被中断的目标节点Guid /// 中断级别 /// 操作是否成功 public bool SetNodeInterrupt(string nodeGuid, InterruptClass interruptClass) { var nodeModel = GuidToModel(nodeGuid); if (nodeModel is null) return false; if (interruptClass == InterruptClass.None) { nodeModel.CancelInterrupt(); } else if (interruptClass == InterruptClass.Branch) { nodeModel.DebugSetting.CancelInterruptCallback?.Invoke(); nodeModel.DebugSetting.GetInterruptTask = () => { TriggerInterrupt(nodeGuid, "", InterruptTriggerEventArgs.InterruptTriggerType.Monitor); return ChannelFlowInterrupt.GetOrCreateChannelAsync(nodeGuid); }; nodeModel.DebugSetting.CancelInterruptCallback = () => { ChannelFlowInterrupt.TriggerSignal(nodeGuid); }; } else if (interruptClass == InterruptClass.Global) // 全局……做不了omg { return false; } nodeModel.DebugSetting.InterruptClass = interruptClass; OnNodeInterruptStateChange.Invoke(new NodeInterruptStateChangeEventArgs(nodeGuid, interruptClass)); return true; } /// /// 添加表达式中断 /// /// /// /// public bool AddInterruptExpression(string key, string expression) { if (dictMonitorObjExpInterrupt.TryGetValue(key, out var condition)) { condition.Clear(); // 暂时 condition.Add(expression);// 暂时 return true; } else { var exps = new List(); exps.Add(expression); dictMonitorObjExpInterrupt.TryAdd(key, exps); return true; } } //public bool AddInterruptExpression(string nodeGuid, string expression) //{ // var nodeModel = GuidToModel(nodeGuid); // if (nodeModel is null) return false; // if (string.IsNullOrEmpty(expression)) // { // nodeModel.DebugSetting.InterruptExpressions.Clear(); // 传入空表达式时清空 // return true; // } // if (nodeModel.DebugSetting.InterruptExpressions.Contains(expression)) // { // Console.WriteLine("表达式已存在"); // return false; // } // else // { // nodeModel.DebugSetting.InterruptExpressions.Clear();// 暂时删除,等UI做好了 // nodeModel.DebugSetting.InterruptExpressions.Add(expression); // return true; // } //} /// /// 监视节点的数据(暂时注释) /// /// 需要监视的节点Guid //public void SetMonitorObjState(string nodeGuid, bool isMonitor) //{ // var nodeModel = GuidToModel(nodeGuid); // if (nodeModel is null) return; // nodeModel.DebugSetting.IsMonitorFlowData = isMonitor; // if (isMonitor) // { // var obj = nodeModel.GetFlowData(); // if(obj is not null) // { // FlowDataNotification(nodeGuid, obj); // } // } // else // { // // 不再监视的节点清空表达式 // nodeModel.DebugSetting.InterruptExpressions.Clear(); // } //} /// /// 要监视的对象,以及与其关联的表达式 /// private ConcurrentDictionary> dictMonitorObjExpInterrupt = []; /// /// 设置对象的监视状态 /// /// /// /// public void SetMonitorObjState(string key, bool isMonitor) { if (string.IsNullOrEmpty(key)) { return; } var isExist = dictMonitorObjExpInterrupt.ContainsKey(key); if (isExist) { if (!isMonitor) // 对象存在且需要不监视 { dictMonitorObjExpInterrupt.Remove(key, out _); } } else { if (isMonitor) // 对象不存在且需要监视,添加在集合中。 { dictMonitorObjExpInterrupt.TryAdd(key, new List()); ; } } } /// /// 检查一个对象是否处于监听状态,如果是,则传出与该对象相关的表达式(用于中断),如果不是,则返回false。 /// /// /// /// public bool CheckObjMonitorState(string key, out List? exps) { if (string.IsNullOrEmpty(key)) { exps = null; return false; } return dictMonitorObjExpInterrupt.TryGetValue(key, out exps); } /// /// 启动器调用,节点数据更新通知 /// /// public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType) { OnMonitorObjectChange?.Invoke(new MonitorObjectEventArgs(nodeGuid, monitorData, sourceType)); } /// /// 启动器调用,节点触发了中断。 /// /// 节点 /// 表达式 /// 类型,0用户主动的中断,1表达式中断 public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type) { OnInterruptTrigger?.Invoke(new InterruptTriggerEventArgs(nodeGuid, expression, type)); } public Task GetOrCreateGlobalInterruptAsync() { IsGlobalInterrupt = true; return ChannelFlowInterrupt.GetOrCreateChannelAsync(this.EnvName); } /// /// Guid 转 NodeModel /// /// 节点Guid /// 节点Model /// 无法获取节点、Guid/节点为null时报错 private NodeModelBase? GuidToModel(string nodeGuid) { if (string.IsNullOrEmpty(nodeGuid)) { //throw new ArgumentNullException("not contains - Guid没有对应节点:" + (nodeGuid)); return null; } if (!Nodes.TryGetValue(nodeGuid, out NodeModelBase? nodeModel) || nodeModel is null) { //throw new ArgumentNullException("null - Guid存在对应节点,但节点为null:" + (nodeGuid)); return null; } return nodeModel; } #endregion #region 私有方法 /// /// 加载指定路径的DLL文件 /// /// private (Assembly?, List) LoadAssembly(string dllPath) { try { Assembly assembly = Assembly.LoadFrom(dllPath); // 加载DLL文件 Type[] types = assembly.GetTypes(); // 获取程序集中的所有类型 List scanTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute()?.Scan == true).ToList(); if (scanTypes.Count == 0) { return (null, []); } List methodDetails = new List(); // 遍历扫描的类型 foreach (var item in scanTypes) { // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 var itemMethodDetails = MethodDetailsHelperTmp.GetList(item); methodDetails.AddRange(itemMethodDetails); //foreach (var md in itemMethodDetails) //{ // // var instanceType = // // Activator.CreateInstance(md.ActingInstanceType); // // SereinIoc.RegisterInstantiate(md.ActingInstance); // SereinIoc.Register(md.ActingInstanceType); //} } LoadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中 LoadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径 return (assembly, methodDetails); } catch (Exception ex) { Console.WriteLine(ex.ToString()); return (null, []); } } /// /// 运行环节加载了项目文件,需要创建节点控件 /// /// /// /// /// private NodeControlType GetNodeControlType(NodeInfo nodeInfo) { // 创建控件实例 NodeControlType controlType = nodeInfo.Type switch { $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleActionNode)}" => NodeControlType.Action,// 动作节点控件 $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleFlipflopNode)}" => NodeControlType.Flipflop, // 触发器节点控件 $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleConditionNode)}" => NodeControlType.ExpCondition,// 条件表达式控件 $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleExpOpNode)}" => NodeControlType.ExpOp, // 操作表达式控件 $"{NodeStaticConfig.NodeSpaceName}.{nameof(CompositeConditionNode)}" => NodeControlType.ConditionRegion, // 条件区域控件 _ => NodeControlType.None, }; return controlType; } /// /// 创建节点 /// /// private NodeModelBase CreateNode(NodeControlType nodeControlType, MethodDetails? methodDetails = null) { // 确定创建的节点类型 Type? nodeType = nodeControlType switch { NodeControlType.Action => typeof(SingleActionNode), NodeControlType.Flipflop => typeof(SingleFlipflopNode), NodeControlType.ExpOp => typeof(SingleExpOpNode), NodeControlType.ExpCondition => typeof(SingleConditionNode), NodeControlType.ConditionRegion => typeof(CompositeConditionNode), _ => null }; if (nodeType is null) { throw new Exception($"节点类型错误[{nodeControlType}]"); } // 生成实例 var nodeObj = Activator.CreateInstance(nodeType); if (nodeObj is not NodeModelBase nodeBase) { throw new Exception($"无法创建目标节点类型的实例[{nodeControlType}]"); } // 配置基础的属性 nodeBase.ControlType = nodeControlType; if (methodDetails != null) { var md = methodDetails.Clone(); nodeBase.DisplayName = md.MethodTips; nodeBase.MethodDetails = md; } // 如果是触发器,则需要添加到专属集合中 if (nodeControlType == NodeControlType.Flipflop && nodeBase is SingleFlipflopNode flipflopNode) { var guid = flipflopNode.Guid; if (!FlipflopNodes.Exists(it => it.Guid.Equals(guid))) { FlipflopNodes.Add(flipflopNode); } } return nodeBase; } private bool TryAddNode(NodeModelBase nodeModel) { nodeModel.Guid ??= Guid.NewGuid().ToString(); Nodes[nodeModel.Guid] = nodeModel; return true; } /// /// 连接节点 /// /// 起始节点 /// 目标节点 /// 连接关系 private void ConnectNode(NodeModelBase fromNode, NodeModelBase toNode, ConnectionType connectionType) { if (fromNode is null || toNode is null || fromNode == toNode) { return; } var ToExistOnFrom = true; var FromExistInTo = true; ConnectionType[] ct = [ConnectionType.IsSucceed, ConnectionType.IsFail, ConnectionType.IsError, ConnectionType.Upstream]; foreach (ConnectionType ctType in ct) { var FToTo = fromNode.SuccessorNodes[ctType].Where(it => it.Guid.Equals(toNode.Guid)).ToArray(); var ToOnF = toNode.PreviousNodes[ctType].Where(it => it.Guid.Equals(fromNode.Guid)).ToArray(); ToExistOnFrom = FToTo.Length > 0; FromExistInTo = ToOnF.Length > 0; if (ToExistOnFrom && FromExistInTo) { Console.WriteLine("起始节点已与目标节点存在连接"); return; } else { // 检查是否可能存在异常 if (!ToExistOnFrom && FromExistInTo) { Console.WriteLine("目标节点不是起始节点的子节点,起始节点却是目标节点的父节点"); return; } else if (ToExistOnFrom && !FromExistInTo) { // Console.WriteLine(" 起始节点不是目标节点的父节点,目标节点却是起始节点的子节点"); return; } else // if (!ToExistOnFrom && !FromExistInTo) { // 可以正常连接 } } } fromNode.SuccessorNodes[connectionType].Add(toNode); // 添加到起始节点的子分支 toNode.PreviousNodes[connectionType].Add(fromNode); // 添加到目标节点的父分支 OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid, toNode.Guid, connectionType, NodeConnectChangeEventArgs.ConnectChangeType.Create)); // 通知UI } /// /// 更改起点节点 /// /// /// private void SetStartNode(NodeModelBase newStartNode) { var oldNodeGuid = StartNode?.Guid; StartNode = newStartNode; OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(oldNodeGuid, StartNode.Guid)); } #endregion #region 网络交互 #endregion #region IOC容器相关 ISereinIOC ISereinIOC.Reset() { sereinIOC.Reset(); return this; } ISereinIOC ISereinIOC.Register(Type type, params object[] parameters) { sereinIOC.Register(type, parameters); return this; } ISereinIOC ISereinIOC.Register(params object[] parameters) { sereinIOC.Register(parameters); return this; } ISereinIOC ISereinIOC.Register(params object[] parameters) { sereinIOC.Register(parameters); return this; } T ISereinIOC.GetOrRegisterInstantiate() { return sereinIOC.GetOrRegisterInstantiate(); } object ISereinIOC.GetOrRegisterInstantiate(Type type) { return sereinIOC.GetOrRegisterInstantiate(type); } object ISereinIOC.Get(Type type) { return sereinIOC.Get(type); } T ISereinIOC.Get(string key) { return sereinIOC.Get(key); } void ISereinIOC.CustomRegisterInstance(string key, object instance, bool needInjectProperty) { sereinIOC.CustomRegisterInstance(key, instance, needInjectProperty); } object ISereinIOC.Instantiate(Type type, params object[] parameters) { return sereinIOC.Instantiate(type, parameters); } ISereinIOC ISereinIOC.Build() { sereinIOC.Build(); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } ISereinIOC ISereinIOC.Run(Action action) { sereinIOC.Run(action); return this; } #endregion } public static class FlowFunc { public static Library.Entity.Library ToLibrary(this Assembly assembly) { return new Library.Entity.Library { Name = assembly.GetName().Name, Path = assembly.Location, }; } public static ConnectionType ToContentType(this FlipflopStateType flowStateType) { return flowStateType switch { FlipflopStateType.Succeed => ConnectionType.IsSucceed, FlipflopStateType.Fail => ConnectionType.IsFail, FlipflopStateType.Error => ConnectionType.IsError, FlipflopStateType.Cancel => ConnectionType.None, _ => throw new NotImplementedException("未定义的流程状态") }; } public static Type? ControlTypeToModel(this NodeControlType nodeControlType) { // 确定创建的节点类型 Type? nodeType = nodeControlType switch { NodeControlType.Action => typeof(SingleActionNode), NodeControlType.Flipflop => typeof(SingleFlipflopNode), NodeControlType.ExpOp => typeof(SingleExpOpNode), NodeControlType.ExpCondition => typeof(SingleConditionNode), NodeControlType.ConditionRegion => typeof(CompositeConditionNode), _ => null }; return nodeType; } public static NodeControlType ModelToControlType(this NodeControlType nodeControlType) { var type = nodeControlType.GetType(); NodeControlType controlType = type switch { Type when type == typeof(SingleActionNode) => NodeControlType.Action, Type when type == typeof(SingleFlipflopNode) => NodeControlType.Flipflop, Type when type == typeof(SingleExpOpNode) => NodeControlType.ExpOp, Type when type == typeof(SingleConditionNode) => NodeControlType.ExpCondition, Type when type == typeof(CompositeConditionNode) => NodeControlType.ConditionRegion, _ => NodeControlType.None, }; return controlType; } public static bool NotExitPreviousNode(this SingleFlipflopNode node) { ConnectionType[] ct = [ConnectionType.IsSucceed, ConnectionType.IsFail, ConnectionType.IsError, ConnectionType.Upstream]; foreach (ConnectionType ctType in ct) { if (node.PreviousNodes[ctType].Count > 0) { return false; } } return true; } } }