using Serein.Library;
using Serein.Library.Api;
using Serein.Library.FlowNode;
using Serein.Library.Utils;
using Serein.Library.Utils.SereinExpression;
using Serein.NodeFlow.Model;
using Serein.NodeFlow.Model.Operation;
using Serein.NodeFlow.Services;
using Serein.NodeFlow.Tool;
using Serein.Script.Node;
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Reactive;
using System.Reflection;
using System.Security.AccessControl;
using System.Text;
namespace Serein.NodeFlow.Env
{
///
/// 运行环境
///
internal partial class LocalFlowEnvironment : IFlowEnvironment
{
///
/// 节点的命名空间
///
public const string SpaceName = $"{nameof(Serein)}.{nameof(NodeFlow)}.{nameof(Model)}";
/*public const string ThemeKey = "theme";
public const string DataKey = "data";
public const string MsgIdKey = "msgid";
*/
///
/// 流程运行环境
///
public LocalFlowEnvironment(IFlowEnvironment flowEnvironment,
IFlowEnvironmentEvent flowEnvironmentEvent,
FlowLibraryService flowLibraryManagement,
FlowOperationService flowOperationService,
FlowModelService flowModelService,
ISereinIOC sereinIOC,
NodeMVVMService nodeMVVMService)
{
this.Event = flowEnvironmentEvent;
this.NodeMVVMManagement = nodeMVVMService;
this.flowOperationService = flowOperationService;
this.flowModelService = flowModelService;
this.IsGlobalInterrupt = false;
this.FlowLibraryService = flowLibraryManagement;
this.flowEnvIOC = sereinIOC;
this.IOC = sereinIOC;
InitNodeMVVM();
}
///
/// 注册基本节点类型
///
private void InitNodeMVVM()
{
NodeMVVMManagement.RegisterModel(NodeControlType.UI, typeof(SingleUINode)); // 动作节点
NodeMVVMManagement.RegisterModel(NodeControlType.Action, typeof(SingleActionNode)); // 动作节点
NodeMVVMManagement.RegisterModel(NodeControlType.Flipflop, typeof(SingleFlipflopNode)); // 触发器节点
NodeMVVMManagement.RegisterModel(NodeControlType.ExpOp, typeof(SingleExpOpNode)); // 表达式节点
NodeMVVMManagement.RegisterModel(NodeControlType.ExpCondition, typeof(SingleConditionNode)); // 条件表达式节点
NodeMVVMManagement.RegisterModel(NodeControlType.GlobalData, typeof(SingleGlobalDataNode)); // 全局数据节点
NodeMVVMManagement.RegisterModel(NodeControlType.Script, typeof(SingleScriptNode)); // 脚本节点
NodeMVVMManagement.RegisterModel(NodeControlType.NetScript, typeof(SingleNetScriptNode)); // 脚本节点
NodeMVVMManagement.RegisterModel(NodeControlType.FlowCall, typeof(SingleFlowCallNode)); // 流程调用节点
}
#region 远程管理
//private MsgControllerOfServer clientMsgManage;
///
/// 表示是否正在控制远程
/// Local control remote env
///
public bool IsControlRemoteEnv { get; set; }
///
/// 打开远程管理
///
///
public async Task StartRemoteServerAsync(int port = 7525)
{
/*if (clientMsgManage is null)
{
clientMsgManage = new MsgControllerOfServer(this);
//clientMsgManage = new MsgControllerOfServer(this,"123456");
}
_ = clientMsgManage.StartRemoteServerAsync(port);*/
}
///
/// 结束远程管理
///
public void StopRemoteServer()
{
/*try
{
clientMsgManage.StopRemoteServer();
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.ERROR, "结束远程管理异常:" + ex);
}*/
}
#endregion
#region 环境运行事件
/*///
/// 加载Dll
///
public event LoadDllHandler? DllLoad;
///
/// 移除DLL
///
public event RemoteDllHandler? OnDllRemote;
///
/// 项目加载完成
///
public event ProjectLoadedHandler? ProjectLoaded;
///
/// 项目准备保存
///
public event ProjectSavingHandler? ProjectSaving;
///
/// 节点连接属性改变事件
///
public event NodeConnectChangeHandler? NodeConnectChanged;
///
/// 节点创建事件
///
public event NodeCreateHandler? NodeCreated;
///
/// 移除节点事件
///
public event NodeRemoveHandler? NodeRemoved;
///
/// 节点放置事件
///
public event NodePlaceHandler NodePlace;
///
/// 节点取出事件
///
public event NodeTakeOutHandler NodeTakeOut;
///
/// 起始节点变化事件
///
public event StartNodeChangeHandler? StartNodeChanged;
///
/// 流程运行完成事件
///
public event FlowRunCompleteHandler? FlowRunComplete;
///
/// 被监视的对象改变事件
///
public event MonitorObjectChangeHandler? MonitorObjectChanged;
///
/// 节点中断状态改变事件
///
public event NodeInterruptStateChangeHandler? NodeInterruptStateChanged;
///
/// 节点触发了中断
///
public event ExpInterruptTriggerHandler? InterruptTriggered;
///
/// 容器改变
///
public event IOCMembersChangedHandler? IOCMembersChanged;
///
/// 节点需要定位
///
public event NodeLocatedHandler? NodeLocated;
///
/// 运行环境输出
///
public event EnvOutHandler? EnvOutput;
///
/// 本地环境添加了画布
///
public event CanvasCreateHandler CanvasCreated;
///
/// 本地环境移除了画布
///
public event CanvasRemoveHandler CanvasRemoved;
*/
#endregion
#region 属性
///
/// 当前环境
///
public IFlowEnvironment CurrentEnv { get => this; }
///
/// 流程事件
///
public IFlowEnvironmentEvent Event { get; set; }
///
/// UI线程操作类
///
public UIContextOperation UIContextOperation { get; private set; }
///
/// 节点MVVM管理服务
///
public NodeMVVMService NodeMVVMManagement { get; private set; }
///
/// 信息输出等级
///
public InfoClass InfoClass { get; set; } = InfoClass.Trivial;
///
/// 如果没有全局触发器,且没有循环分支,流程执行完成后自动为 Completion 。
///
public RunState FlowState { get; set; } = RunState.NoStart;
///
/// 如果全局触发器还在运行,则为 Running 。
///
public RunState FlipFlopState { get; set; } = RunState.NoStart;
///
/// 环境名称
///
public string EnvName { get; set; } = SpaceName;
///
/// 本地加载的项目文件路径
///
public string ProjectFileLocation { get; set; } = string.Empty;
///
/// 是否全局中断
///
public bool IsGlobalInterrupt { get; set; }
///
/// 单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。
/// 当某个类型注册绑定成功后,将不会因为其它地方尝试注册相同类型的行为导致类型被重新创建。
///
public ISereinIOC IOC
{
get
{
if (flowRunIOC is null)
{
flowRunIOC = new SereinIOC();
}
return flowRunIOC;
}
set
{
flowRunIOC = value;
}
}
#endregion
#region 私有变量
///
/// 装饰器运行环境类
///
private readonly IFlowEnvironment mainFlowEnvironment;
///
/// 流程运行时的IOC容器
///
private ISereinIOC flowRunIOC;
///
/// local环境的IOC容器,主要用于注册本地环境的服务
///
private ISereinIOC flowEnvIOC;
///
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
///
private readonly FlowLibraryService FlowLibraryService;
///
/// 流程节点操作服务
///
private readonly FlowOperationService flowOperationService;
///
/// 流程画布、节点实体管理服务
///
private readonly FlowModelService flowModelService;
/* ///
/// 环境加载的节点集合
/// Node Guid - Node Model
///
private Dictionary NodeModels { get; } = [];
///
/// 运行环境加载的画布集合
///
private Dictionary FlowCanvass { get; } = [];
///
/// 存放触发器节点(运行时全部调用)
///
private List FlipflopNodes { get; } = [];
*/
///
/// 流程任务管理
///
private FlowWorkManagement? flowTaskManagement;
#endregion
#region 环境对外接口
///
/// 输出信息
///
/// 日志内容
/// 日志类别
/// 日志级别
public void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial)
{
if (@class >= this.InfoClass)
{
Event.OnEnvOutput(type, message);
}
//Console.WriteLine($"{DateTime.UtcNow} [{type}] : {message}{Environment.NewLine}");
}
///
/// 异步运行
///
///
public async Task StartFlowAsync(string[] canvasGuids)
{
#region 校验参数
HashSet guids = new HashSet();
bool isBreak = false;
foreach (var canvasGuid in canvasGuids)
{
if (guids.Contains(canvasGuid))
{
SereinEnv.WriteLine(InfoType.WARN, $"画布重复,停止运行。{canvasGuid}");
isBreak = true;
}
else if (!flowModelService.ContainsCanvasModel(canvasGuid))
{
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
isBreak = true;
}
else if(!flowModelService.IsExsitNodeOnCanvas(canvasGuid))
{
SereinEnv.WriteLine(InfoType.WARN, $"画布没有节点,停止运行。{canvasGuid}");
isBreak = true;
}
else
{
guids.Add(canvasGuid);
}
}
if (isBreak)
{
guids.Clear();
return false;
}
#endregion
#region 初始化每个画布的数据,转换为流程任务
Dictionary flowTasks = [];
foreach (var guid in guids)
{
if (!TryGetCanvasModel(guid, out var canvasModel))
{
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{guid}");
return false;
}
var ft = new FlowTask();
ft.GetNodes = () => flowModelService.GetAllNodeModel(guid);
if (canvasModel.StartNode?.Guid is null)
{
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在起始节点,将停止运行。{guid}");
return false;
}
ft.GetStartNode = () => canvasModel.StartNode;
flowTasks.Add(guid, ft);
}
#endregion
IOC.Reset();
IOC.Register(()=> mainFlowEnvironment);
IOC.Register(); // 注册脚本接口
var flowTaskOptions = new FlowWorkOptions
{
Environment = this, // 流程
Flows = flowTasks,
FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
AutoRegisterTypes = this.FlowLibraryService.GetaAutoRegisterType(), // 需要自动实例化的类型
InitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Init),
LoadMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Loading),
ExitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Exit),
};
flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
var cts = new CancellationTokenSource();
try
{
var t = await flowTaskManagement.RunAsync(cts.Token);
}
catch (Exception ex)
{
SereinEnv.WriteLine(ex);
}
finally
{
SereinEnv.WriteLine(InfoType.INFO, $"流程运行完毕{Environment.NewLine}"); ;
}
flowTaskOptions = null;
return true;
}
///
/// 从选定节点开始运行
///
///
///
public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
{
var flowTaskOptions = new FlowWorkOptions
{
Environment = this, // 流程
FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
};
var flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
{
if (!TryGetNodeModel(startNodeGuid, out var nodeModel) || nodeModel is SingleFlipflopNode)
{
return false;
}
await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
return true;
}
else
{
return false;
}
}
/*///
/// 单独运行一个节点
///
///
///
public async Task