diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs
index 80f0b2e..e572334 100644
--- a/Library/FlowNode/ParameterDetails.cs
+++ b/Library/FlowNode/ParameterDetails.cs
@@ -168,15 +168,57 @@ namespace Serein.Library
IsParams = info.IsParams;
}
-
+ ///
+ /// 禁止将 IFlowContext 类型显式入参设置为 true
+ ///
+ ///
+ ///
partial void BeforeTheIsExplicitData(ref bool __isAllow, bool newValue)
{
- if(DataType == typeof(IFlowContext))
+ if(DataType == typeof(IFlowContext) && newValue == true)
{
__isAllow = false;
}
}
+ ///
+ /// 脚本节点的类型缓存。
+ ///
+ private Type? cacheType;
+ private bool cacheIsExplicit;
+
+ ///
+ /// 脚本节点的名称变更为流程上下文时,调整 DataType 和 IsExplicitData 的值。
+ ///
+ ///
+ ///
+ partial void OnNameChanged(string oldValue, string newValue)
+ {
+ if (NodeModel is null)
+ return;
+ if (NodeModel.ControlType == NodeControlType.Script)
+ {
+ var isIgnore = StringComparison.OrdinalIgnoreCase;
+ if ("context".Equals(newValue, isIgnore) ||
+ "flowcontext".Equals(newValue, isIgnore) ||
+ "flow_context".Equals(newValue, isIgnore))
+ {
+ cacheType = DataType;
+ cacheIsExplicit = IsExplicitData;
+ DataType = typeof(IFlowContext);
+ IsExplicitData = false;
+ }
+ else
+ {
+ if (cacheType is not null)
+ {
+ DataType = cacheType;
+ IsExplicitData = cacheIsExplicit;
+ }
+ }
+ }
+ }
+
///
/// 转为描述
diff --git a/NodeFlow/Model/Nodes/SingleConditionNode.cs b/NodeFlow/Model/Nodes/SingleConditionNode.cs
index 38a9f10..1f7e290 100644
--- a/NodeFlow/Model/Nodes/SingleConditionNode.cs
+++ b/NodeFlow/Model/Nodes/SingleConditionNode.cs
@@ -223,7 +223,7 @@ namespace Serein.NodeFlow.Model.Nodes
}
- IScriptInvokeContext scriptContext = new ScriptInvokeContext(flowContext);
+ IScriptInvokeContext scriptContext = new ScriptInvokeContext();
scriptContext.SetVarValue(dataName, data);
var result = await getValueScript.InterpreterAsync(scriptContext);
@@ -262,7 +262,7 @@ namespace Serein.NodeFlow.Model.Nodes
});
}
- IScriptInvokeContext scriptContext = new ScriptInvokeContext(flowContext);
+ IScriptInvokeContext scriptContext = new ScriptInvokeContext();
scriptContext.SetVarValue(dataName, data);
var result = await conditionScript.InterpreterAsync(scriptContext);
diff --git a/NodeFlow/Model/Nodes/SingleExpOpNode.cs b/NodeFlow/Model/Nodes/SingleExpOpNode.cs
index 2e7397c..61f9226 100644
--- a/NodeFlow/Model/Nodes/SingleExpOpNode.cs
+++ b/NodeFlow/Model/Nodes/SingleExpOpNode.cs
@@ -178,7 +178,7 @@ namespace Serein.NodeFlow.Model.Nodes
}
- IScriptInvokeContext scriptContext = new ScriptInvokeContext(flowContext);
+ IScriptInvokeContext scriptContext = new ScriptInvokeContext();
scriptContext.SetVarValue(dataName, data);
var result = await getValueScript.InterpreterAsync(scriptContext);
diff --git a/NodeFlow/Model/Nodes/SingleScriptNode.cs b/NodeFlow/Model/Nodes/SingleScriptNode.cs
index e4f4227..1807748 100644
--- a/NodeFlow/Model/Nodes/SingleScriptNode.cs
+++ b/NodeFlow/Model/Nodes/SingleScriptNode.cs
@@ -1,6 +1,7 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
+using Serein.NodeFlow.Services;
using Serein.Script;
using Serein.Script.Node.FlowControl;
using System;
@@ -49,7 +50,6 @@ namespace Serein.NodeFlow.Model.Nodes
public SingleScriptNode(IFlowEnvironment environment) : base(environment)
{
sereinScript = new SereinScript();
-
}
static SingleScriptNode()
@@ -195,7 +195,11 @@ namespace Serein.NodeFlow.Model.Nodes
ScriptArgInfo[] array = JsonHelper.Deserialize(paramsTypeNameJson);
string returnTypeName = nodeInfo.CustomData?.ReturnTypeName ?? typeof(object);
- Type?[] argType = array.Select(item => string.IsNullOrWhiteSpace(item.ArgType) ? null : Type.GetType(item.ArgType) ?? typeof(Unit)).ToArray();
+
+ var flowLibService = Env.IOC.Get();
+
+ Type?[] argType = array.Select(item => string.IsNullOrWhiteSpace(item.ArgType) ? null : flowLibService.GetType(item.ArgType) ?? typeof(Unit)).ToArray();
+
Type? resType = Type.GetType(returnTypeName);
for (int i = 0; i < paramCount; i++)
{
@@ -352,7 +356,7 @@ namespace Serein.NodeFlow.Model.Nodes
var @params = await flowCallNode.GetParametersAsync(context, token);
- IScriptInvokeContext scriptContext = new ScriptInvokeContext(context);
+ IScriptInvokeContext scriptContext = new ScriptInvokeContext();
if (@params[0] is object[] agrDatas)
{
diff --git a/NodeFlow/Model/Operations/ChangeNodeConnectionOperation.cs b/NodeFlow/Model/Operations/ChangeNodeConnectionOperation.cs
index 4f3e63b..2700059 100644
--- a/NodeFlow/Model/Operations/ChangeNodeConnectionOperation.cs
+++ b/NodeFlow/Model/Operations/ChangeNodeConnectionOperation.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
+using System.Reflection;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
@@ -429,6 +430,11 @@ namespace Serein.NodeFlow.Model.Operations
return false;
}
+ if (typeof(IFlowContext).IsAssignableFrom(ToNode.MethodDetails.ParameterDetailss[ArgIndex].DataType))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"连接失败, IFlowContext 流程上下文由运行环境自动注入,作为节点入参时不允许外部给定。起始节点[{FromNode.Guid}],目标节点[{FromNode.Guid}]。");
+ return false;
+ }
var toNodeArgSourceGuid = ToNode.MethodDetails.ParameterDetailss[ArgIndex].ArgDataSourceNodeGuid; // 目标节点对应参数可能已经有其它连接
var toNodeArgSourceType = ToNode.MethodDetails.ParameterDetailss[ArgIndex].ArgDataSourceType;
diff --git a/NodeFlow/Services/FlowLibraryService.cs b/NodeFlow/Services/FlowLibraryService.cs
index 499ca4d..02b1360 100644
--- a/NodeFlow/Services/FlowLibraryService.cs
+++ b/NodeFlow/Services/FlowLibraryService.cs
@@ -147,6 +147,46 @@ namespace Serein.NodeFlow.Services
#region 获取流程依赖的相关方法
+ ///
+ /// 搜索类型
+ ///
+ ///
+ ///
+ ///
+ public bool TryGetType(string fullName,[NotNullWhen(true)] out Type? type)
+ {
+ var assemblys = _flowLibraryCaches.Values.Select(key => key.Assembly).ToArray();
+ foreach(var assembly in assemblys)
+ {
+ type = assembly.GetType(fullName);
+ if(type is not null)
+ {
+ return true;
+ }
+ }
+ type = null;
+ return false;
+ }
+ ///
+ /// 搜索类型
+ ///
+ ///
+ ///
+ public Type? GetType(string fullName)
+ {
+ var assemblys = _flowLibraryCaches.Values.Select(key => key.Assembly).ToArray();
+ Type? type;
+ foreach (var assembly in assemblys)
+ {
+ type = assembly.GetType(fullName);
+ if(type is not null)
+ {
+ return type;
+ }
+ }
+ return null;
+ }
+
///
/// 获取方法描述
///
diff --git a/Serein.Script/IScriptInvokeContext.cs b/Serein.Script/IScriptInvokeContext.cs
index a5dfa3c..c842a8a 100644
--- a/Serein.Script/IScriptInvokeContext.cs
+++ b/Serein.Script/IScriptInvokeContext.cs
@@ -7,10 +7,6 @@ namespace Serein.Script
///
public interface IScriptInvokeContext
{
- ///
- /// 脚本运行的流程上下文,包含了流程上下文和变量等信息
- ///
- IFlowContext FlowContext { get; }
///
/// 是否该退出了(由 TokenSource 控制,用于响应外部发出停止信号)
diff --git a/Serein.Script/ScriptInvokeContext.cs b/Serein.Script/ScriptInvokeContext.cs
index 8d3b71c..7ad1b15 100644
--- a/Serein.Script/ScriptInvokeContext.cs
+++ b/Serein.Script/ScriptInvokeContext.cs
@@ -4,15 +4,6 @@ namespace Serein.Script
{
public sealed class ScriptInvokeContext : IScriptInvokeContext
{
- ///
- /// 脚本使用流程上下文
- ///
- ///
- public ScriptInvokeContext(IFlowContext flowContext)
- {
- FlowContext = flowContext;
- }
-
///
/// 不使用流程上下文
///
@@ -20,10 +11,6 @@ namespace Serein.Script
{
}
-#pragma warning disable CS8766 // 返回类型中引用类型的为 Null 性与隐式实现的成员不匹配(可能是由于为 Null 性特性)。
- public IFlowContext? FlowContext{ get; }
-#pragma warning restore CS8766 // 返回类型中引用类型的为 Null 性与隐式实现的成员不匹配(可能是由于为 Null 性特性)。
-
///
/// 定义的变量
///
diff --git a/Serein.Script/SereinScriptInterpreter.cs b/Serein.Script/SereinScriptInterpreter.cs
index 139d6a7..8583a3c 100644
--- a/Serein.Script/SereinScriptInterpreter.cs
+++ b/Serein.Script/SereinScriptInterpreter.cs
@@ -13,10 +13,10 @@ namespace Serein.Script
public class SereinScriptInterpreter
{
private readonly Dictionary symbolInfos;
+
///
/// 缓存对象方法调用节点
///
- //private Dictionary MethodNodeDelegateCaches { get; } = new Dictionary();
private static Dictionary ASTDelegateDetails { get; } = new Dictionary();
@@ -322,15 +322,6 @@ namespace Serein.Script
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
async Task