1. 新增了脚本节点之间连接时,入参类型伴随来源节点的返回类型改变而改变。

2. 重新优化了Script项目脚本生成代码的缩进排版
3. 修复了Script中对于Double字面量错误的使用了Float解析的bug
This commit is contained in:
fengjiayi
2025-07-31 15:45:02 +08:00
parent 827a9242ae
commit 5f6a58168a
10 changed files with 273 additions and 183 deletions

View File

@@ -49,6 +49,7 @@ namespace Serein.NodeFlow.Model.Nodes
public SingleScriptNode(IFlowEnvironment environment) : base(environment)
{
sereinScript = new SereinScript();
}
static SingleScriptNode()
@@ -78,9 +79,9 @@ namespace Serein.NodeFlow.Model.Nodes
IsScriptChanged = true;
}
/// <summary>
/// 节点创建时
/// </summary>
/// <summary>
/// 节点创建时
/// </summary>
public override void OnCreating()
{
var md = MethodDetails;
@@ -106,6 +107,38 @@ namespace Serein.NodeFlow.Model.Nodes
}
/// <summary>
/// 更新节点返回类型
/// </summary>
/// <param name="newType"></param>
private void UploadNodeReturnType(Type newType)
{
MethodDetails.ReturnType = newType;
foreach (var ct in NodeStaticConfig.ConnectionArgSourceTypes)
{
var newResultNodes = NeedResultNodes[ct].ToArray();
foreach (var node in newResultNodes)
{
if(node is SingleScriptNode scriptNode)
{
var pds = scriptNode.MethodDetails.ParameterDetailss;
foreach (var pd in pds)
{
if (pd.ArgDataSourceType == ct &&
pd.ArgDataSourceNodeGuid == this.Guid)
{
pd.DataType = newType; // 更新参数类型
}
}
//scriptNode.ReloadScript(); // 重新加载目标脚本节点
}
}
}
}
/// <summary>
/// 保存项目时保存脚本代码、方法入参类型、返回值类型
/// </summary>
@@ -181,58 +214,77 @@ namespace Serein.NodeFlow.Model.Nodes
}
private object reloadLockObj = new object();
/// <summary>
/// 重新加载脚本代码
/// </summary>
public bool ReloadScript()
{
try
lock (reloadLockObj)
{
HashSet<string> varNames = new HashSet<string>();
foreach (var pd in MethodDetails.ParameterDetailss)
if (!CheckRepeatParamter())
return false;
var argTypes = GetParamterTypeInfo();
try
{
if (varNames.Contains(pd.Name))
{
throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}");
}
varNames.Add(pd.Name);
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
UploadNodeReturnType(returnType);
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.WARN, ex.Message);
return false; // 解析失败
}
var argTypes = MethodDetails.ParameterDetailss
.Select(pd =>
{
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
{
var Type = pd.DataType;
return (pd.Name, Type);
}
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
node.MethodDetails?.ReturnType is not null)
{
pd.DataType = node.MethodDetails.ReturnType;
var Type = node.MethodDetails.ReturnType;
return (pd.Name, Type);
}
return default;
})
.Where(x => x != default)
.ToDictionary(x => x.Name, x => x.Type); // 准备预定义类型
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
MethodDetails.ReturnType = returnType;
return true;
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.WARN, ex.Message);
return false; // 解析失败
}
}
/// <summary>
/// 检查脚本参数是否有重复的名称
/// </summary>
/// <returns></returns>
private bool CheckRepeatParamter()
{
bool isSueccess = true;
HashSet<string> varNames = new HashSet<string>();
foreach (var pd in MethodDetails.ParameterDetailss)
{
if (varNames.Contains(pd.Name))
{
SereinEnv.WriteLine(InfoType.ERROR, $"脚本节点重复的变量名称:{pd.Name} - {Guid}");
isSueccess = false;
}
varNames.Add(pd.Name);
}
return isSueccess;
}
/// <summary>
/// 获取参数类型信息
/// </summary>
/// <returns></returns>
private Dictionary<string, Type> GetParamterTypeInfo()
{
Dictionary<string, Type> argTypes = [];
var pds = MethodDetails.ParameterDetailss.ToArray();
foreach (var pd in pds)
{
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
{
argTypes[pd.Name] = pd.DataType;
}
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
node.MethodDetails?.ReturnType is not null)
{
pd.DataType = node.MethodDetails.ReturnType;
var Type = node.MethodDetails.ReturnType;
argTypes[pd.Name] = Type;
}
}
return argTypes;
}
/// <summary>
/// 转换为 C# 代码,并且附带方法信息
/// </summary>
@@ -246,39 +298,11 @@ namespace Serein.NodeFlow.Model.Nodes
methodName = $"FlowMethod_{tmp}";
}
HashSet<string> varNames = new HashSet<string>();
foreach (var pd in MethodDetails.ParameterDetailss)
{
if (varNames.Contains(pd.Name))
{
throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}");
}
varNames.Add(pd.Name);
}
var argTypes = MethodDetails.ParameterDetailss
.Select(pd =>
{
if(pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
{
var Type = pd.DataType;
return (pd.Name, Type);
}
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
node.MethodDetails?.ReturnType is not null)
{
pd.DataType = node.MethodDetails.ReturnType;
var Type = node.MethodDetails.ReturnType;
return (pd.Name, Type);
}
return default;
})
.Where(x => x != default)
.ToDictionary(x => x.Name, x => x.Type); // 准备预定义类型
if (!CheckRepeatParamter())
throw new Exception($"脚本节点入参重复");
var argTypes = GetParamterTypeInfo();
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
MethodDetails.ReturnType = returnType;
UploadNodeReturnType(returnType);
var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes);
return scriptMethodInfo;
}
@@ -297,6 +321,13 @@ namespace Serein.NodeFlow.Model.Nodes
/// <returns></returns>
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{
if (IsScriptChanged)
{
if (!ReloadScript())
{
return FlowResult.Fail(this.Guid, context, "脚本解析失败,请检查脚本代码");
}
}
var result = await ExecutingAsync(this, context, token);
return result;
}
@@ -311,6 +342,14 @@ namespace Serein.NodeFlow.Model.Nodes
public async Task<FlowResult> ExecutingAsync(NodeModelBase flowCallNode, IFlowContext context, CancellationToken token)
{
if (token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");
if (IsScriptChanged)
{
if (!ReloadScript())
{
return FlowResult.Fail(this.Guid, context, "脚本解析失败,请检查脚本代码");
}
}
var @params = await flowCallNode.GetParametersAsync(context, token);
IScriptInvokeContext scriptContext = new ScriptInvokeContext(context);