mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-12 10:56:34 +08:00
优化FlowEnv
This commit is contained in:
@@ -549,6 +549,10 @@ namespace Serein.Library.Utils
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(typeName == IOC_MAIN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var value = CreateInstance(typeName);
|
||||
if(value is null)
|
||||
{
|
||||
@@ -560,10 +564,8 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
_typeMappings.Clear();
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有方法
|
||||
|
||||
@@ -8,6 +8,38 @@ using System.Reflection;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
{
|
||||
|
||||
/*
|
||||
SetExportDirectory(string directory)
|
||||
UseRemoteEdit(string wspath)
|
||||
|
||||
|
||||
|
||||
IFlowEnvironment env = new ();
|
||||
env.LoadProject()
|
||||
|
||||
List<FlowApiInfo> apiInfos = env.GetInterfaceInfo();
|
||||
List<FlowEventInfo> enventInfos = env.GetEventInfo();
|
||||
|
||||
|
||||
flowApiService = env.GetFlowApiService();
|
||||
flowEventService = env.GetFlowEventService();
|
||||
|
||||
|
||||
object result = flowApiService.Invoke("", params);
|
||||
TResult result = flowApiService.Invoke<TResult>("", params);
|
||||
object result = await flowApiService.InvokeAsync("", params);
|
||||
TResult result = await flowApiService.InvokeAsync<TResult>("", params);
|
||||
|
||||
flowEventService.Monitor("", (e) => {
|
||||
object data = e.EventData;
|
||||
Debug.Writeline(e.EventName);
|
||||
});
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
/// </summary>
|
||||
@@ -15,35 +47,23 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
public FlowEnvironment()
|
||||
{
|
||||
ISereinIOC sereinIOC = new SereinIOC();
|
||||
sereinIOC.Reset();
|
||||
sereinIOC.Register<ISereinIOC>(()=> sereinIOC); // 注册IOC
|
||||
sereinIOC.Register<IFlowEnvironment>(() => this);
|
||||
sereinIOC.Register<IFlowEnvironmentEvent, FlowEnvironmentEvent>();
|
||||
sereinIOC.Register<LocalFlowEnvironment>();
|
||||
sereinIOC.Register<FlowModelService>();
|
||||
sereinIOC.Register<FlowOperationService>();
|
||||
sereinIOC.Register<NodeMVVMService>();
|
||||
sereinIOC.Register<FlowLibraryManagement>();
|
||||
sereinIOC.Build();
|
||||
this.IOC = sereinIOC;
|
||||
|
||||
ISereinIOC ioc = new SereinIOC();
|
||||
ioc.Reset()
|
||||
.Register<ISereinIOC>(()=> ioc) // 注册IOC
|
||||
.Register<IFlowEnvironment>(() => this)
|
||||
.Register<IFlowEnvironmentEvent, FlowEnvironmentEvent>()
|
||||
.Register<LocalFlowEnvironment>()
|
||||
.Register<FlowModelService>()
|
||||
.Register<FlowOperationService>()
|
||||
.Register<NodeMVVMService>()
|
||||
.Register<FlowLibraryService>()
|
||||
.Build();
|
||||
// 默认使用本地环境
|
||||
currentFlowEnvironment = sereinIOC.Get<LocalFlowEnvironment>();
|
||||
currentFlowEnvironmentEvent = sereinIOC.Get<IFlowEnvironmentEvent>();
|
||||
currentFlowEnvironment = ioc.Get<LocalFlowEnvironment>();
|
||||
currentFlowEnvironmentEvent = ioc.Get<IFlowEnvironmentEvent>();
|
||||
SereinEnv.SetEnv(currentFlowEnvironment);
|
||||
}
|
||||
|
||||
/* /// <summary>
|
||||
/// 本地环境
|
||||
/// </summary>
|
||||
private readonly LocalFlowEnvironment flowEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 远程环境
|
||||
/// </summary>
|
||||
private RemoteFlowEnvironment remoteFlowEnvironment;*/
|
||||
|
||||
/// <summary>
|
||||
/// 本地环境事件
|
||||
/// </summary>
|
||||
@@ -87,14 +107,14 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironment CurrentEnv { get => currentFlowEnvironment; }
|
||||
public IFlowEnvironment CurrentEnv => currentFlowEnvironment;
|
||||
/// <inheritdoc/>
|
||||
public UIContextOperation UIContextOperation => currentFlowEnvironment.UIContextOperation;
|
||||
/// <inheritdoc/>
|
||||
public NodeMVVMService NodeMVVMManagement => currentFlowEnvironment.NodeMVVMManagement;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ISereinIOC IOC { get; set; }
|
||||
public ISereinIOC IOC => currentFlowEnvironment.IOC;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironmentEvent Event => currentFlowEnvironment.Event;
|
||||
|
||||
@@ -7,6 +7,7 @@ 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;
|
||||
@@ -23,7 +24,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
/// </summary>
|
||||
internal partial class LocalFlowEnvironment : IFlowEnvironment/*, IFlowEnvironmentEvent*/
|
||||
internal partial class LocalFlowEnvironment : IFlowEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点的命名空间
|
||||
@@ -36,16 +37,22 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
/// </summary>
|
||||
public LocalFlowEnvironment(IFlowEnvironmentEvent flowEnvironmentEvent,
|
||||
FlowLibraryManagement flowLibraryManagement,
|
||||
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.FlowLibraryManagement = flowLibraryManagement;
|
||||
this.FlowLibraryService = flowLibraryManagement;
|
||||
this.flowEnvIOC = sereinIOC;
|
||||
this.IOC = sereinIOC;
|
||||
InitNodeMVVM();
|
||||
}
|
||||
|
||||
@@ -224,13 +231,11 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
public UIContextOperation UIContextOperation { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 节点MVVM管理服务
|
||||
/// </summary>
|
||||
public NodeMVVMService NodeMVVMManagement { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 信息输出等级
|
||||
/// </summary>
|
||||
@@ -261,11 +266,6 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
public bool IsGlobalInterrupt { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 流程中断器
|
||||
///// </summary>
|
||||
//public ChannelFlowInterrupt ChannelFlowInterrupt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <para>单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。</para>
|
||||
/// <para>当某个类型注册绑定成功后,将不会因为其它地方尝试注册相同类型的行为导致类型被重新创建。</para>
|
||||
@@ -280,21 +280,35 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
return flowRunIOC;
|
||||
}
|
||||
set
|
||||
{
|
||||
flowRunIOC = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 私有变量
|
||||
|
||||
/// <summary>
|
||||
/// 装饰器运行环境类
|
||||
/// </summary>
|
||||
private readonly IFlowEnvironment mainFlowEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行时的IOC容器
|
||||
/// </summary>
|
||||
private ISereinIOC flowRunIOC;
|
||||
|
||||
/// <summary>
|
||||
/// local环境的IOC容器,主要用于注册本地环境的服务
|
||||
/// </summary>
|
||||
private ISereinIOC flowEnvIOC;
|
||||
|
||||
/// <summary>
|
||||
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
|
||||
/// </summary>
|
||||
private readonly FlowLibraryManagement FlowLibraryManagement;
|
||||
private readonly FlowLibraryService FlowLibraryService;
|
||||
|
||||
/// <summary>
|
||||
/// 流程节点操作服务
|
||||
@@ -302,21 +316,26 @@ namespace Serein.NodeFlow.Env
|
||||
private readonly FlowOperationService flowOperationService;
|
||||
|
||||
/// <summary>
|
||||
/// 环境加载的节点集合
|
||||
/// Node Guid - Node Model
|
||||
/// 流程画布、节点实体管理服务
|
||||
/// </summary>
|
||||
private Dictionary<string, IFlowNode> NodeModels { get; } = [];
|
||||
private readonly FlowModelService flowModelService;
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境加载的画布集合
|
||||
/// </summary>
|
||||
private Dictionary<string, FlowCanvasDetails> FlowCanvass { get; } = [];
|
||||
/* /// <summary>
|
||||
/// 环境加载的节点集合
|
||||
/// Node Guid - Node Model
|
||||
/// </summary>
|
||||
private Dictionary<string, IFlowNode> NodeModels { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 存放触发器节点(运行时全部调用)
|
||||
/// </summary>
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||
/// <summary>
|
||||
/// 运行环境加载的画布集合
|
||||
/// </summary>
|
||||
private Dictionary<string, FlowCanvasDetails> FlowCanvass { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 存放触发器节点(运行时全部调用)
|
||||
/// </summary>
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -344,6 +363,7 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步运行
|
||||
/// </summary>
|
||||
@@ -360,13 +380,12 @@ namespace Serein.NodeFlow.Env
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"画布重复,停止运行。{canvasGuid}");
|
||||
isBreak = true;
|
||||
}
|
||||
if (!FlowCanvass.ContainsKey(canvasGuid))
|
||||
else if (!flowModelService.ContainsCanvasModel(canvasGuid))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
|
||||
isBreak = true;
|
||||
}
|
||||
var count = NodeModels.Values.Count(n => n.CanvasDetails.Guid.Equals(canvasGuid));
|
||||
if (count == 0)
|
||||
else if(!flowModelService.IsExsitNodeOnCanvas(canvasGuid))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"画布没有节点,停止运行。{canvasGuid}");
|
||||
isBreak = true;
|
||||
@@ -394,8 +413,8 @@ namespace Serein.NodeFlow.Env
|
||||
return false;
|
||||
}
|
||||
var ft = new FlowTask();
|
||||
ft.GetNodes = () => NodeModels.Values.Where(node => node.CanvasDetails.Guid.Equals(guid)).ToList();
|
||||
if (canvasModel.StartNode.Guid is null)
|
||||
ft.GetNodes = () => flowModelService.GetAllNodeModel(guid);
|
||||
if (canvasModel.StartNode?.Guid is null)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, $"画布不存在起始节点,将停止运行。{guid}");
|
||||
return false;
|
||||
@@ -405,9 +424,8 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
IOC.Reset();
|
||||
IOC.Register<IFlowEnvironment>(()=> mainFlowEnvironment);
|
||||
IOC.Register<IScriptFlowApi, ScriptFlowApi>(); // 注册脚本接口
|
||||
|
||||
var flowTaskOptions = new FlowWorkOptions
|
||||
@@ -415,10 +433,10 @@ namespace Serein.NodeFlow.Env
|
||||
Environment = this, // 流程
|
||||
Flows = flowTasks,
|
||||
FlowContextPool = new ObjectPool<IDynamicContext>(() => 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),
|
||||
AutoRegisterTypes = this.FlowLibraryService.GetaAutoRegisterType(), // 需要自动实例化的类型
|
||||
InitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Init),
|
||||
LoadMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Loading),
|
||||
ExitMds = this.FlowLibraryService.GetMdsOnFlowStart(NodeType.Exit),
|
||||
};
|
||||
|
||||
|
||||
@@ -453,11 +471,13 @@ namespace Serein.NodeFlow.Env
|
||||
public async Task<bool> StartFlowFromSelectNodeAsync(string startNodeGuid)
|
||||
{
|
||||
|
||||
if (flowTaskManagement is null)
|
||||
var flowTaskOptions = new FlowWorkOptions
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, "没有启动流程,无法运行单个节点");
|
||||
return false;
|
||||
}
|
||||
Environment = this, // 流程
|
||||
FlowContextPool = new ObjectPool<IDynamicContext>(() => new DynamicContext(this)), // 上下文对象池
|
||||
};
|
||||
var flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
|
||||
|
||||
if (true || FlowState == RunState.Running || FlipFlopState == RunState.Running)
|
||||
{
|
||||
|
||||
@@ -465,7 +485,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
return false;
|
||||
}
|
||||
await flowTaskManagement.StartFlowInSelectNodeAsync(this, nodeModel);
|
||||
await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -550,7 +570,7 @@ namespace Serein.NodeFlow.Env
|
||||
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
// 获取所有的程序集对应的方法信息(程序集相关的数据)
|
||||
var libraryMdss = this.FlowLibraryManagement.GetAllLibraryMds().ToArray();
|
||||
var libraryMdss = this.FlowLibraryService.GetAllLibraryMds().ToArray();
|
||||
// 获取当前项目的信息(节点相关的数据)
|
||||
var project = await GetProjectInfoAsync(); // 远程连接获取远程环境项目信息
|
||||
SereinEnv.WriteLine(InfoType.INFO, "已将当前环境信息发送到远程客户端");
|
||||
@@ -666,9 +686,9 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
var projectData = new SereinProjectData()
|
||||
{
|
||||
Librarys = this.FlowLibraryManagement.GetAllLibraryInfo().ToArray(),
|
||||
Nodes = NodeModels.Values.Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||
Canvass = FlowCanvass.Values.Select(canvas => canvas.ToInfo()).ToArray(),
|
||||
Librarys = this.FlowLibraryService.GetAllLibraryInfo().ToArray(),
|
||||
Nodes = flowModelService.GetAllNodeModel().Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||
Canvass = flowModelService.GetAllCanvasModel().Select(canvas => canvas.ToInfo()).ToArray(),
|
||||
//StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||
};
|
||||
|
||||
@@ -689,15 +709,15 @@ namespace Serein.NodeFlow.Env
|
||||
#region 检查是否已经加载本地依赖
|
||||
var thisAssembly = typeof(IFlowEnvironment).Assembly;
|
||||
var thisAssemblyName = thisAssembly.GetName().Name;
|
||||
if (!string.IsNullOrEmpty(thisAssemblyName) && FlowLibraryManagement.GetLibraryMdsOfAssmbly(thisAssemblyName).Count == 0)
|
||||
if (!string.IsNullOrEmpty(thisAssemblyName) && FlowLibraryService.GetLibraryMdsOfAssmbly(thisAssemblyName).Count == 0)
|
||||
{
|
||||
var tmp = FlowLibraryManagement.LoadLibraryOfPath(thisAssembly.Location);
|
||||
var tmp = FlowLibraryService.LoadLibraryOfPath(thisAssembly.Location);
|
||||
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(tmp.Item1, tmp.Item2))); // 通知UI创建dll面板显示
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
(var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibraryOfPath(dllPath);
|
||||
(var libraryInfo, var mdInfos) = FlowLibraryService.LoadLibraryOfPath(dllPath);
|
||||
if (mdInfos.Count > 0)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||
@@ -717,7 +737,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
try
|
||||
{
|
||||
(var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibraryOfPath(flowLibrary);
|
||||
(var libraryInfo, var mdInfos) = FlowLibraryService.LoadLibraryOfPath(flowLibrary);
|
||||
if (mdInfos.Count > 0)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||
@@ -739,10 +759,10 @@ namespace Serein.NodeFlow.Env
|
||||
public bool TryUnloadLibrary(string assemblyName)
|
||||
{
|
||||
// 获取与此程序集相关的节点
|
||||
var groupedNodes = NodeModels.Values.Where(node => !string.IsNullOrWhiteSpace(node.MethodDetails.AssemblyName) && node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray();
|
||||
var groupedNodes = flowModelService.GetAllNodeModel().Where(node => !string.IsNullOrWhiteSpace(node.MethodDetails.AssemblyName) && node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray();
|
||||
if (groupedNodes.Length == 0)
|
||||
{
|
||||
var isPass = FlowLibraryManagement.UnloadLibrary(assemblyName);
|
||||
var isPass = FlowLibraryService.UnloadLibrary(assemblyName);
|
||||
return isPass;
|
||||
}
|
||||
else
|
||||
@@ -822,7 +842,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
var model = new FlowCanvasDetails(this);
|
||||
model.LoadInfo(info);
|
||||
FlowCanvass.Add(model.Guid, model);
|
||||
flowModelService.AddCanvasModel(model);
|
||||
UIContextOperation?.Invoke(() =>
|
||||
{
|
||||
Event.OnCanvasCreated(new CanvasCreateEventArgs(model));
|
||||
@@ -837,7 +857,7 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo? mdInfo)
|
||||
{
|
||||
var isPass = FlowLibraryManagement.TryGetMethodDetails(assemblyName, methodName, out var md);
|
||||
var isPass = FlowLibraryService.TryGetMethodDetails(assemblyName, methodName, out var md);
|
||||
if (!isPass || md is null)
|
||||
{
|
||||
mdInfo = null;
|
||||
@@ -862,7 +882,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <returns></returns>
|
||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails? delegateDetails)
|
||||
{
|
||||
return FlowLibraryManagement.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails);
|
||||
return FlowLibraryService.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -986,7 +1006,7 @@ namespace Serein.NodeFlow.Env
|
||||
canvasDetails = null;
|
||||
return false;
|
||||
}
|
||||
return FlowCanvass.TryGetValue(nodeGuid, out canvasDetails) && canvasDetails is not null;
|
||||
return flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails);
|
||||
|
||||
}
|
||||
|
||||
@@ -1003,7 +1023,7 @@ namespace Serein.NodeFlow.Env
|
||||
nodeModel = null;
|
||||
return false;
|
||||
}
|
||||
return NodeModels.TryGetValue(nodeGuid, out nodeModel) && nodeModel is not null;
|
||||
return flowModelService.TryGetNodeModel(nodeGuid, out nodeModel);
|
||||
|
||||
}
|
||||
|
||||
@@ -1131,7 +1151,7 @@ namespace Serein.NodeFlow.Env
|
||||
else
|
||||
{
|
||||
// 目标节点可能是方法节点
|
||||
FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
|
||||
FlowLibraryService.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
|
||||
}
|
||||
}
|
||||
else if (controlType.IsBaseNode())
|
||||
@@ -1144,7 +1164,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeInfo.MethodName)) return false;
|
||||
// 加载方法节点
|
||||
FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
|
||||
FlowLibraryService.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -1154,7 +1174,7 @@ namespace Serein.NodeFlow.Env
|
||||
nodeInfo.Guid = string.Empty;
|
||||
return false;
|
||||
}
|
||||
if (FlowCanvass.TryGetValue(nodeInfo.CanvasGuid, out var canvasModel))
|
||||
if (TryGetCanvasModel(nodeInfo.CanvasGuid, out var canvasModel))
|
||||
{
|
||||
|
||||
// 节点与画布互相绑定
|
||||
@@ -1185,18 +1205,18 @@ namespace Serein.NodeFlow.Env
|
||||
private bool TryAddNode(IFlowNode nodeModel)
|
||||
{
|
||||
nodeModel.Guid ??= Guid.NewGuid().ToString();
|
||||
NodeModels.TryAdd(nodeModel.Guid, nodeModel);
|
||||
flowModelService.AddNodeModel(nodeModel);
|
||||
|
||||
|
||||
// 如果是触发器,则需要添加到专属集合中
|
||||
if (nodeModel is SingleFlipflopNode flipflopNode)
|
||||
/*if (nodeModel is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
var guid = flipflopNode.Guid;
|
||||
if (!FlipflopNodes.Exists(it => it.Guid.Equals(guid)))
|
||||
{
|
||||
FlipflopNodes.Add(flipflopNode);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1465,8 +1485,11 @@ namespace Serein.NodeFlow.Env
|
||||
ToNodeGuid = toNodeGuid,
|
||||
FromNodeJunctionType = fromNodeJunctionType,
|
||||
ToNodeJunctionType = toNodeJunctionType,
|
||||
ConnectionInvokeType = invokeType
|
||||
ConnectionInvokeType = invokeType,
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create,
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Invoke,
|
||||
};
|
||||
|
||||
flowOperationService.Execute(operation);
|
||||
}
|
||||
|
||||
@@ -1480,7 +1503,9 @@ namespace Serein.NodeFlow.Env
|
||||
FromNodeJunctionType = fromNodeJunctionType,
|
||||
ToNodeJunctionType = toNodeJunctionType,
|
||||
ConnectionArgSourceType = argSourceType,
|
||||
ArgIndex = argIndex
|
||||
ArgIndex = argIndex,
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create,
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Arg,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
}
|
||||
@@ -1493,7 +1518,7 @@ namespace Serein.NodeFlow.Env
|
||||
FromNodeGuid = fromNodeGuid,
|
||||
ToNodeGuid = toNodeGuid,
|
||||
ConnectionInvokeType = connectionType,
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
}
|
||||
@@ -1636,7 +1661,7 @@ namespace Serein.NodeFlow.Env
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(nodeInfo.ParentNodeGuid) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
TryGetNodeModel(nodeInfo.ParentNodeGuid, out var parentNode))
|
||||
{
|
||||
needPlaceNodeInfos.Add(nodeInfo); // 需要重新放置的节点
|
||||
}
|
||||
@@ -1644,8 +1669,8 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
foreach (NodeInfo nodeInfo in needPlaceNodeInfos)
|
||||
{
|
||||
if (NodeModels.TryGetValue(nodeInfo.Guid, out var nodeModel) &&
|
||||
NodeModels.TryGetValue(nodeInfo.ParentNodeGuid, out var containerNode)
|
||||
if (TryGetNodeModel(nodeInfo.Guid, out var nodeModel) &&
|
||||
TryGetNodeModel(nodeInfo.ParentNodeGuid, out var containerNode)
|
||||
&& containerNode is INodeContainer nodeContainer)
|
||||
{
|
||||
var result = nodeContainer.PlaceNode(nodeModel);
|
||||
@@ -1660,6 +1685,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
#endregion
|
||||
|
||||
await Task.Delay(100);
|
||||
#region 确定节点之间的方法调用关系
|
||||
foreach (var nodeInfo in nodeInfos)
|
||||
{
|
||||
@@ -1670,9 +1696,9 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
if (fromNodeModel is null) continue;
|
||||
List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
|
||||
(ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
|
||||
(ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
|
||||
(ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
|
||||
(ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
|
||||
(ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
|
||||
(ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
|
||||
foreach ((ConnectionInvokeType connectionType, string[] toNodeGuids) item in allToNodes)
|
||||
{
|
||||
// 遍历当前类型分支的节点(确认连接关系)
|
||||
@@ -1688,7 +1714,7 @@ namespace Serein.NodeFlow.Env
|
||||
continue;
|
||||
}
|
||||
|
||||
ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.Execute, JunctionType.NextStep, item.connectionType);
|
||||
ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, item.connectionType);
|
||||
|
||||
//var isSuccessful = ConnectInvokeOfNode(canvasGuid, fromNodeModel, toNodeModel, item.connectionType); // 加载时确定节点间的连接关系
|
||||
}
|
||||
@@ -1718,7 +1744,8 @@ namespace Serein.NodeFlow.Env
|
||||
#endregion
|
||||
|
||||
#region 确定节点之间的参数调用关系
|
||||
foreach (var toNode in NodeModels.Values)
|
||||
var nodeModels = flowModelService.GetAllNodeModel();
|
||||
foreach (var toNode in nodeModels)
|
||||
{
|
||||
var canvasGuid = toNode.CanvasDetails.Guid;
|
||||
if (toNode.MethodDetails.ParameterDetailss == null)
|
||||
@@ -1729,7 +1756,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
var pd = toNode.MethodDetails.ParameterDetailss[i];
|
||||
if (!string.IsNullOrEmpty(pd.ArgDataSourceNodeGuid)
|
||||
&& NodeModels.TryGetValue(pd.ArgDataSourceNodeGuid, out var fromNode))
|
||||
&& TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var fromNode))
|
||||
{
|
||||
|
||||
ConnectArgSourceNode(canvasGuid, fromNode.Guid, toNode.Guid, JunctionType.ReturnData, JunctionType.ArgData , pd.ArgDataSourceType, pd.Index);
|
||||
|
||||
@@ -48,8 +48,10 @@ namespace Serein.NodeFlow
|
||||
throw new Exception($"无法创建{nodeControlType}节点,节点类型尚未注册。");
|
||||
}
|
||||
|
||||
|
||||
// 生成实例
|
||||
var nodeObj = Activator.CreateInstance(nodeMVVM.ModelType, env);
|
||||
//var nodeObj = Activator.CreateInstance(nodeMVVM.ModelType, env);
|
||||
var nodeObj = env.IOC.CreateObject(nodeMVVM.ModelType);
|
||||
if (nodeObj is not IFlowNode nodeModel)
|
||||
{
|
||||
throw new Exception($"无法创建目标节点类型的实例[{nodeControlType}]");
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
{
|
||||
public override string Theme => nameof(CreateNodeOperation);
|
||||
|
||||
|
||||
public required string CanvasGuid { get; set; }
|
||||
public required NodeControlType NodeControlType { get; set; }
|
||||
public required PositionOfUI Position { get; set; }
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// 流程依赖服务
|
||||
/// </summary>
|
||||
[AutoInjection]
|
||||
protected FlowLibraryManagement flowLibraryManagement;
|
||||
protected FlowLibraryService flowLibraryManagement;
|
||||
|
||||
/// <summary>
|
||||
/// 流程事件服务
|
||||
|
||||
63
NodeFlow/Services/FlowApiService.cs
Normal file
63
NodeFlow/Services/FlowApiService.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser;
|
||||
|
||||
namespace Serein.NodeFlow.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程API服务,用于外部调用流程接口
|
||||
/// </summary>
|
||||
public class FlowApiService
|
||||
{
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
private readonly FlowModelService flowModelService;
|
||||
|
||||
/// <summary>
|
||||
/// 流程API服务构造函数
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment"></param>
|
||||
/// <param name="flowModelService"></param>
|
||||
public FlowApiService(IFlowEnvironment flowEnvironment,
|
||||
FlowModelService flowModelService)
|
||||
{
|
||||
this.flowEnvironment = flowEnvironment;
|
||||
this.flowModelService = flowModelService;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* object result = flowApiService.Invoke("", params);
|
||||
TResult result = flowApiService.Invoke<TResult>("", params);
|
||||
object result = await flowApiService.InvokeAsync("", params);
|
||||
TResult result = await flowApiService.InvokeAsync<TResult>("", params);*/
|
||||
|
||||
|
||||
public object Invoke(string apiName, object[] param)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TResult Invoke<TResult>(string apiName, object[] param)
|
||||
{
|
||||
return default(TResult);
|
||||
}
|
||||
|
||||
public async Task<object> InvokeAsync(string apiName, object[] param)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<TResult> InvokeAsync<TResult>(string apiName, object[] param)
|
||||
{
|
||||
return default(TResult);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Services
|
||||
{
|
||||
internal class FlowModelService
|
||||
/// <summary>
|
||||
/// 流程模型服务
|
||||
/// </summary>
|
||||
public class FlowModelService
|
||||
{
|
||||
private readonly IFlowEnvironment environment;
|
||||
|
||||
@@ -91,9 +94,24 @@ namespace Serein.NodeFlow.Services
|
||||
}
|
||||
|
||||
public List<IFlowNode> GetAllNodeModel() => [.. NodeModels.Values];
|
||||
public List<IFlowNode> GetAllNodeModel(string canvasGuid) =>
|
||||
NodeModels.Values.Where(x => x.CanvasDetails.Guid == canvasGuid).ToList();
|
||||
public List<FlowCanvasDetails> GetAllCanvasModel() => [.. FlowCanvass.Values];
|
||||
|
||||
|
||||
|
||||
public bool IsExsitCanvas()
|
||||
{
|
||||
return FlowCanvass.Count > 0;
|
||||
}
|
||||
public bool IsExsitNodeOnCanvas(string canvasGuid)
|
||||
{
|
||||
if (!FlowCanvass.TryGetValue(canvasGuid, out var flowCanvasDetails))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return flowCanvasDetails.Nodes.Count > 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,10 +266,9 @@ namespace Serein.NodeFlow.Services
|
||||
/// <summary>
|
||||
/// 从选定的节点开始运行
|
||||
/// </summary>
|
||||
/// <param name="env"></param>
|
||||
/// <param name="startNode"></param>
|
||||
/// <returns></returns>
|
||||
public async Task StartFlowInSelectNodeAsync(IFlowEnvironment env, IFlowNode startNode)
|
||||
public async Task StartFlowInSelectNodeAsync(IFlowNode startNode)
|
||||
{
|
||||
var pool = WorkOptions.FlowContextPool;
|
||||
var context = pool.Allocate();
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Serein.NodeFlow.Tool
|
||||
/// <summary>
|
||||
/// 管理加载在运行环境中的外部程序集
|
||||
/// </summary>
|
||||
internal class FlowLibraryManagement
|
||||
internal class FlowLibraryService
|
||||
{
|
||||
public FlowLibraryManagement(IFlowEnvironment flowEnvironment)
|
||||
public FlowLibraryService(IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
this.flowEnvironment = flowEnvironment;
|
||||
}
|
||||
@@ -234,7 +234,11 @@ namespace Serein.Workbench.Services
|
||||
/// <param name="eventArgs"></param>
|
||||
private void FlowEnvironment_NodeConnectChangeEvemt(NodeConnectChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeConnectChanged?.Invoke(eventArgs);
|
||||
uiContextOperation.Invoke(() =>
|
||||
{
|
||||
Debug.WriteLine(DateTime.Now, $"Node Connect Changed");
|
||||
NodeConnectChanged?.Invoke(eventArgs);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +282,11 @@ namespace Serein.Workbench.Services
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void FlowEnvironment_NodeCreateEvent(NodeCreateEventArgs eventArgs)
|
||||
{
|
||||
NodeCreated?.Invoke(eventArgs);
|
||||
uiContextOperation.Invoke(() =>
|
||||
{
|
||||
Debug.WriteLine(DateTime.Now, $"Create Node {eventArgs.NodeModel.Guid}");
|
||||
NodeCreated?.Invoke(eventArgs);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -342,8 +342,6 @@ namespace Serein.Workbench.Views
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region 接口实现
|
||||
private IFlowCanvas Api => this;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user