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.Tool;
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.Text;
namespace Serein.NodeFlow.Env
{
///
/// 运行环境
///
public class LocalFlowEnvironment : IFlowEnvironment, IFlowEnvironmentEvent
{
///
/// 节点的命名空间
///
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()
{
this.sereinIOC = new SereinIOC();
this.IsGlobalInterrupt = false;
this.flowTaskManagement = null;
this.sereinIOC.OnIOCMembersChanged += e =>
{
if (OperatingSystem.IsWindows())
{
UIContextOperation?.Invoke(() => this?.OnIOCMembersChanged?.Invoke(e)); // 监听IOC容器的注册
}
};
this.FlowLibraryManagement = new FlowLibraryManagement(this); // 实例化类库管理
this.NodeMVVMManagement = new NodeMVVMManagement();
#region 注册基本节点类型
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.ConditionRegion, typeof(CompositeConditionNode)); // 条件区域
NodeMVVMManagement.RegisterModel(NodeControlType.GlobalData, typeof(SingleGlobalDataNode)); // 全局数据节点
NodeMVVMManagement.RegisterModel(NodeControlType.Script, typeof(SingleScriptNode)); // 脚本节点
NodeMVVMManagement.RegisterModel(NodeControlType.NetScript, typeof(SingleNetScriptNode)); // 脚本节点
NodeMVVMManagement.RegisterModel(NodeControlType.FlowCall, typeof(SingleFlowCallNode)); // 流程调用节点
#endregion
#region 注册基本服务类
PersistennceInstance.Add(typeof(FlowInterruptTool), new FlowInterruptTool()); // 缓存流程实例
PersistennceInstance.Add(typeof(IFlowEnvironment), (LocalFlowEnvironment)this); // 缓存流程实例
PersistennceInstance.Add(typeof(ISereinIOC), this); // 缓存容器服务
ReRegisterPersistennceInstance();
#endregion
}
#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? OnDllLoad;
///
/// 移除DLL
///
public event RemoteDllHandler? OnDllRemote;
///
/// 项目加载完成
///
public event ProjectLoadedHandler? OnProjectLoaded;
///
/// 项目准备保存
///
public event ProjectSavingHandler? OnProjectSaving;
///
/// 节点连接属性改变事件
///
public event NodeConnectChangeHandler? OnNodeConnectChange;
///
/// 节点创建事件
///
public event NodeCreateHandler? OnNodeCreate;
///
/// 移除节点事件
///
public event NodeRemoveHandler? OnNodeRemove;
///
/// 节点放置事件
///
public event NodePlaceHandler OnNodePlace;
///
/// 节点取出事件
///
public event NodeTakeOutHandler OnNodeTakeOut;
///
/// 起始节点变化事件
///
public event StartNodeChangeHandler? OnStartNodeChange;
///
/// 流程运行完成事件
///
public event FlowRunCompleteHandler? OnFlowRunComplete;
///
/// 被监视的对象改变事件
///
public event MonitorObjectChangeHandler? OnMonitorObjectChange;
///
/// 节点中断状态改变事件
///
public event NodeInterruptStateChangeHandler? OnNodeInterruptStateChange;
///
/// 节点触发了中断
///
public event ExpInterruptTriggerHandler? OnInterruptTrigger;
///
/// 容器改变
///
public event IOCMembersChangedHandler? OnIOCMembersChanged;
///
/// 节点需要定位
///
public event NodeLocatedHandler? OnNodeLocated;
///
/// 节点移动了(远程插件)
///
public event NodeMovedHandler? OnNodeMoved;
///
/// 运行环境输出
///
public event EnvOutHandler? OnEnvOut;
///
/// 本地环境添加了画布
///
public event CanvasCreateHandler OnCanvasCreate;
///
/// 本地环境移除了画布
///
public event CanvasRemoveHandler OnCanvasRemove;
#endregion
#region 属性
///
/// 当前环境
///
public IFlowEnvironment CurrentEnv { get => this; }
///
/// UI线程操作类
///
public UIContextOperation UIContextOperation { get; private set; }
///
/// 节点视图模型管理类
///
public NodeMVVMManagement NodeMVVMManagement { get; 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; }
/////
///// 流程中断器
/////
//public ChannelFlowInterrupt ChannelFlowInterrupt { get; set; }
///
/// 单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。
/// 当某个类型注册绑定成功后,将不会因为其它地方尝试注册相同类型的行为导致类型被重新创建。
///
public ISereinIOC IOC
{
get
{
if(ioc is null)
{
ioc = new SereinIOC();
}
return ioc;
}
}
#endregion
#region 私有变量
///
/// IOC容器
///
private ISereinIOC ioc;
///
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
///
private readonly FlowLibraryManagement FlowLibraryManagement;
///
/// IOC对象容器管理
///
private readonly SereinIOC sereinIOC;
///
/// 本地运行环境缓存的持久化实例
///
private Dictionary PersistennceInstance { get; } = new Dictionary();
///
/// 环境加载的节点集合
/// 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)
{
OnEnvOut?.Invoke(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;
}
if (!FlowCanvass.ContainsKey(canvasGuid))
{
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
isBreak = true;
}
var count = NodeModels.Values.Count(n => n.CanvasDetails.Guid.Equals(canvasGuid));
if(count == 0)
{
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 = () => NodeModels.Values.Where(node => node.CanvasDetails.Guid.Equals(guid)).ToList();
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(); // 注册脚本接口
var flowTaskOptions = new FlowWorkOptions
{
Environment = this, // 流程
Flows = flowTasks,
FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
AutoRegisterTypes = this.FlowLibraryManagement.GetaAutoRegisterType(), // 需要自动实例化的类型
InitMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Init),
LoadMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Loading),
ExitMds = this.FlowLibraryManagement.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)
{
if (flowTaskManagement is null)
{
SereinEnv.WriteLine(InfoType.ERROR, "没有启动流程,无法运行单个节点");
return false;
}
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
{
if (!TryGetNodeModel(startNodeGuid,out var nodeModel) || nodeModel is SingleFlipflopNode)
{
return false;
}
await flowTaskManagement.StartFlowInSelectNodeAsync(this, nodeModel);
return true;
}
else
{
return false;
}
}
/*///
/// 单独运行一个节点
///
///
///
public async Task