重写了Script的解释器代码,使其更加直观。重写了流程控制的部分代码,分离运行环境IOC与流程IOC。

This commit is contained in:
fengjiayi
2025-07-18 22:45:06 +08:00
parent 88de5a21f5
commit fc05cd662b
38 changed files with 567 additions and 1418 deletions

View File

@@ -35,19 +35,44 @@ namespace Serein.NodeFlow.Env
this.flowOperationService = flowOperationService;
this.flowModelService = flowModelService;
this.UIContextOperation = UIContextOperation;
contexts = new ObjectPool<IDynamicContext>(() => new DynamicContext(flowEnvironment));
}
private ObjectPool<IDynamicContext> contexts;
private FlowWorkManagement flowWorkManagement;
private ISereinIOC sereinIOC;
private ISereinIOC externalIOC;
private Action<ISereinIOC> setDefultMemberOnReset;
private bool IsUseExternalIOC = false;
private object lockObj = new object();
/// <summary>
/// 如果全局触发器还在运行,则为 Running 。
/// </summary>
private RunState FlipFlopState = RunState.NoStart;
/// <summary>
/// 运行时的IOC容器
/// </summary>
public ISereinIOC IOC
{
get
{
lock (lockObj)
{
if (externalIOC is null) externalIOC = new SereinIOC();
return externalIOC;
}
}
private set
{
lock (lockObj)
{
externalIOC = value;
}
}
}
/// <inheritdoc/>
public async Task<bool> StartFlowAsync(string[] canvasGuids)
{
@@ -104,13 +129,14 @@ namespace Serein.NodeFlow.Env
flowTasks.Add(guid, ft);
}
#endregion
sereinIOC.Reset();
sereinIOC.Register<IFlowEnvironment>(() => flowEnvironment);
sereinIOC.Register<IScriptFlowApi, ScriptFlowApi>(); // 注册脚本接口
IOC.Reset();
setDefultMemberOnReset?.Invoke(IOC);
IOC.Register<IFlowEnvironment>(() => flowEnvironment);
//externalIOC.Register<IScriptFlowApi, ScriptFlowApi>(); // 注册脚本接口
var flowTaskOptions = new FlowWorkOptions
{
FlowIOC = IOC,
Environment = flowEnvironment, // 流程
Flows = flowTasks,
FlowContextPool = contexts, // 上下文对象池
@@ -143,9 +169,9 @@ namespace Serein.NodeFlow.Env
/// <inheritdoc/>
public async Task<TResult> StartFlowAsync<TResult>(string startNodeGuid)
{
var flowTaskOptions = new FlowWorkOptions
{
FlowIOC = IOC,
Environment = flowEnvironment, // 流程
FlowContextPool = contexts, // 上下文对象池
};
@@ -203,7 +229,7 @@ namespace Serein.NodeFlow.Env
{
flowWorkManagement?.Exit();
UIContextOperation?.Invoke(() => flowEnvironmentEvent.OnFlowRunComplete(new FlowEventArgs()));
sereinIOC.Reset();
IOC.Reset();
flowWorkManagement = null;
GC.Collect();
return Task.FromResult(true);
@@ -240,9 +266,11 @@ namespace Serein.NodeFlow.Env
}*/
}
/// <inheritdoc/>
public void UseExternalIOC(ISereinIOC ioc)
public void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC> setDefultMemberOnReset = null)
{
this.sereinIOC = ioc; // 设置IOC容器
IOC = ioc; // 设置IOC容器
this.setDefultMemberOnReset = setDefultMemberOnReset;
IsUseExternalIOC = true;
}
/// <inheritdoc/>
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
@@ -270,10 +298,6 @@ namespace Serein.NodeFlow.Env
/// <inheritdoc/>
public async Task<TResult> InvokeAsync<TResult>(string apiGuid, Dictionary<string, object> dict)
{
if (sereinIOC is null)
{
sereinIOC = flowEnvironment.IOC;
}
if (!flowModelService.TryGetNodeModel(apiGuid, out var nodeModel))
{
throw new ArgumentNullException($"不存在流程接口:{apiGuid}");

View File

@@ -161,7 +161,7 @@ namespace Serein.NodeFlow.Env
}
#endregion
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment, controlType, methodDetails); // 加载项目时创建节点
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment.IOC, controlType, methodDetails); // 加载项目时创建节点
if (nodeModel is null)
{
nodeInfo.Guid = string.Empty;

View File

@@ -1,6 +1,7 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using Serein.NodeFlow.Env;
using Serein.NodeFlow.Model;
using System.Collections.Concurrent;
using System.ComponentModel;
@@ -51,18 +52,17 @@ namespace Serein.NodeFlow
/// <summary>
/// 创建节点
/// </summary>
/// <param name="env">运行环境</param>
/// <param name="envIOC">运行环境使用的IOC</param>
/// <param name="nodeControlType">节点类型</param>
/// <param name="methodDetails">方法描述</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static IFlowNode CreateNode(IFlowEnvironment env, NodeControlType nodeControlType,
MethodDetails? methodDetails = null)
public static IFlowNode CreateNode(ISereinIOC envIOC, NodeControlType nodeControlType, MethodDetails? methodDetails = null)
{
// 尝试获取需要创建的节点类型
if (!env.FlowEdit.NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null)
var flowEdit = envIOC.Get<IFlowEdit>();
if (!flowEdit.NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null)
{
throw new Exception($"无法创建{nodeControlType}节点,节点类型尚未注册。");
}
@@ -70,7 +70,7 @@ namespace Serein.NodeFlow
// 生成实例
//var nodeObj = Activator.CreateInstance(nodeMVVM.ModelType, env);
var nodeObj = env.IOC.CreateObject(nodeMVVM.ModelType);
var nodeObj = envIOC.CreateObject(nodeMVVM.ModelType);
if (nodeObj is not IFlowNode nodeModel)
{
throw new Exception($"无法创建目标节点类型的实例[{nodeControlType}]");

View File

@@ -33,6 +33,10 @@ namespace Serein.NodeFlow
/// </summary>
public class FlowWorkOptions()
{
/// <summary>
/// 流程IOC容器
/// </summary>
public ISereinIOC FlowIOC { get; set; }
/// <summary>
/// 流程运行环境
/// </summary>
@@ -46,7 +50,7 @@ namespace Serein.NodeFlow
/// <summary>
/// 上下文线程池
/// </summary>
public Serein.Library.Utils.ObjectPool<IDynamicContext> FlowContextPool { get; set; }
public Serein.Library.Utils.ObjectPool<IDynamicContext> FlowContextPool { get; set; }
/// <summary>
/// 每个画布需要启用的节点

View File

@@ -141,11 +141,11 @@ namespace Serein.NodeFlow.Model
}
else
{
var instance = Env.IOC.Get(md.ActingInstanceType);
var instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
if (instance is null)
{
Env.IOC.Register(md.ActingInstanceType).Build();
instance = Env.IOC.Get(md.ActingInstanceType);
Env.FlowControl.IOC.Register(md.ActingInstanceType).Build();
instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
}
object[] args = await this.GetParametersAsync(context, token);
var result = await dd.InvokeAsync(instance, args);

View File

@@ -39,11 +39,11 @@ namespace Serein.NodeFlow.Model
throw new Exception("不存在对应委托");
}
var instance = context.Env.IOC.Get(md.ActingInstanceType);
var instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
if (instance is null)
{
Env.IOC.Register(md.ActingInstanceType).Build();
instance = Env.IOC.Get(md.ActingInstanceType);
Env.FlowControl.IOC.Register(md.ActingInstanceType).Build();
instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
}
await dd.InvokeAsync(instance, [context]);
var args = await this.GetParametersAsync(context, token);

View File

@@ -246,6 +246,10 @@ namespace Serein.NodeFlow.Model
}
else
{
/*var tempName = node.MethodDetails.MethodName;
var index = node.MethodDetails.MethodName.IndexOf('(');
var methodName = tempName[..(index - 1)];
return GetApiInvokeName(node, methodName);*/
FlowLibraryService service = node.Env.IOC.Get<FlowLibraryService>();
if (service.TryGetMethodInfo(md.AssemblyName, md.MethodName, out var methodInfo))
{

View File

@@ -69,11 +69,11 @@ namespace Serein.NodeFlow.Model.Operation
public override async Task<bool> ExecuteAsync()
{
if (!ValidationParameter()) return false; // 执行时验证
IFlowNode? nodeModel;
if (IsBaseNode)
{
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment, NodeControlType); // 加载基础节点
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment.IOC, NodeControlType); // 加载基础节点
}
else
{
@@ -89,7 +89,7 @@ namespace Serein.NodeFlow.Model.Operation
return false;
//throw new InvalidOperationException($"无法创建节点,因为没有找到{MethodDetailsInfo.AssemblyName}.{MethodDetailsInfo.MethodName}方法,请检查是否已加载对应程序集");
}
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment, NodeControlType, methodDetails); // 一般的加载节点方法
nodeModel = FlowNodeExtension.CreateNode(flowEnvironment.IOC, NodeControlType, methodDetails); // 一般的加载节点方法
}
nodeModel.Guid ??= Guid.NewGuid().ToString();

View File

@@ -113,8 +113,9 @@ namespace Serein.NodeFlow.Services
private bool RegisterAllType(List<IFlowNode> nodes)
{
var env = WorkOptions.Environment;
var ioc = WorkOptions.FlowIOC;
var nodeMds = nodes.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
var allMds = new List<MethodDetails>();
@@ -127,7 +128,7 @@ namespace Serein.NodeFlow.Services
{
if (md.ActingInstanceType != null)
{
env.IOC.Register(md.ActingInstanceType);
ioc.Register(md.ActingInstanceType);
}
else
{
@@ -135,10 +136,10 @@ namespace Serein.NodeFlow.Services
isSuccessful = false ;
}
}
env.IOC.Build(); // 绑定初始化时注册的类型
ioc.Build(); // 绑定初始化时注册的类型
foreach (var md in allMds)
{
var instance = env.IOC.Get(md.ActingInstanceType);
var instance = ioc.Get(md.ActingInstanceType);
if (instance is null)
{
SereinEnv.WriteLine(InfoType.ERROR, $"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例");
@@ -154,7 +155,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var initMds = WorkOptions.InitMds;
var pool = WorkOptions.FlowContextPool;
var ioc = WorkOptions.Environment.IOC;
var ioc = WorkOptions.FlowIOC;
foreach (var md in initMds) // 初始化
{
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
@@ -167,7 +168,7 @@ namespace Serein.NodeFlow.Services
context.Reset();
pool.Free(context);
}
env.IOC.Build(); // 绑定初始化时注册的类型
ioc.Build(); // 绑定初始化时注册的类型
var isSuccessful = true;
return isSuccessful;
}
@@ -176,7 +177,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var loadMds = WorkOptions.LoadMds;
var pool = WorkOptions.FlowContextPool;
var ioc = WorkOptions.Environment.IOC;
var ioc = WorkOptions.FlowIOC;
foreach (var md in loadMds) // 加载时
{
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
@@ -189,7 +190,7 @@ namespace Serein.NodeFlow.Services
context.Reset();
pool.Free(context);
}
env.IOC.Build(); // 绑定初始化时注册的类型
ioc.Build(); // 绑定初始化时注册的类型
var isSuccessful = true;
return isSuccessful;
@@ -199,7 +200,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var mds = WorkOptions.ExitMds;
var pool = WorkOptions.FlowContextPool;
var ioc = WorkOptions.Environment.IOC;
var ioc = WorkOptions.FlowIOC;
// var fit = ioc.Get<FlowInterruptTool>();
// fit.CancelAllTrigger(); // 取消所有中断