修改了很多

This commit is contained in:
fengjiayi
2024-10-27 00:54:10 +08:00
parent 6f26d303e4
commit cb2553ac69
66 changed files with 2215 additions and 1402 deletions

View File

@@ -0,0 +1,103 @@
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static Serein.Library.Utils.EmitHelper;
namespace Serein.Library
{
/// <summary>
/// Emit创建的委托描述用于WebApi、WebSocket、NodeFlow动态调用方法的场景。
/// 一般情况下你无须内部细节,只需要调用 Invoke() 方法即可。
/// </summary>
public class DelegateDetails
{
/// <summary>
/// 根据方法信息构建Emit委托
/// </summary>
/// <param name="methodInfo"></param>
public DelegateDetails(MethodInfo methodInfo)
{
var emitMethodType = EmitHelper.CreateDynamicMethod(methodInfo, out var emitDelegate);
_emitMethodType = emitMethodType;
_emitDelegate = emitDelegate;
}
/// <summary>
/// 记录Emit委托
/// </summary>
/// <param name="EmitMethodType"></param>
/// <param name="EmitDelegate"></param>
public DelegateDetails(EmitMethodType EmitMethodType, Delegate EmitDelegate)
{
_emitMethodType = EmitMethodType;
_emitDelegate = EmitDelegate;
}
/// <summary>
/// 更新委托方法
/// </summary>
/// <param name="EmitMethodType"></param>
/// <param name="EmitDelegate"></param>
public void Upload(EmitMethodType EmitMethodType, Delegate EmitDelegate)
{
_emitMethodType = EmitMethodType;
_emitDelegate = EmitDelegate;
}
private Delegate _emitDelegate;
private EmitMethodType _emitMethodType;
///// <summary>
///// <para>普通方法Func&lt;object,object[],object&gt;</para>
///// <para>异步方法Func&lt;object,object[],Task&gt;</para>
///// <para>异步有返回值方法Func&lt;object,object[],Task&lt;object&gt;&gt;</para>
///// </summary>
//public Delegate EmitDelegate { get => _emitDelegate; }
///// <summary>
///// 表示Emit构造的委托类型
///// </summary>
//public EmitMethodType EmitMethodType { get => _emitMethodType; }
/// <summary>
/// <para>使用的实例必须能够正确调用该委托,传入的参数也必须符合方法入参信息。</para>
/// </summary>
/// <param name="instance">拥有符合委托签名的方法信息的实例</param>
/// <param name="args">如果方法没有入参,也需要传入一个空数组</param>
/// <returns>void方法自动返回null</returns>
public async Task<object> InvokeAsync(object instance, object[] args)
{
if (args is null)
{
args = Array.Empty<object>();
}
object result = null;
try
{
if (_emitMethodType == EmitMethodType.HasResultTask && _emitDelegate is Func<object, object[], Task<object>> hasResultTask)
{
result = await hasResultTask(instance, args);
}
else if (_emitMethodType == EmitMethodType.Task && _emitDelegate is Func<object, object[], Task> task)
{
await task.Invoke(instance, args);
result = null;
}
else if (_emitMethodType == EmitMethodType.Func && _emitDelegate is Func<object, object[], object> func)
{
result = func.Invoke(instance, args);
}
else
{
throw new NotImplementedException("创建了非预期委托(应该不会出现)");
}
return result;
}
catch
{
throw;
}
}
}
}

View File

@@ -35,15 +35,16 @@ namespace Serein.Library
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
[PropertyInfo]
private InterruptClass _interruptClass = InterruptClass.None;
//[PropertyInfo]
//private InterruptClass _interruptClass = InterruptClass.None;
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
[PropertyInfo(IsNotification = true)]
[PropertyInfo(IsNotification = true, CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);")]
private bool _isInterrupt = false;
//private const string MyInteruptCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"; // 添加到中断的自定义代码
/// <summary>
/// 取消中断的回调函数
@@ -56,29 +57,30 @@ namespace Serein.Library
/// </summary>
[PropertyInfo]
private Func<Task<CancelType>> _getInterruptTask;
}
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
//public enum InterruptClass
//{
// /// <summary>
// /// 不中断
// /// </summary>
// None,
// /// <summary>
// /// 分支中断,中断进入当前节点的分支。
// /// </summary>
// Branch,
// /// <summary>
// /// 全局中断,中断全局所有节点的运行。(暂未实现相关)
// /// </summary>
// Global,
//}
}
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
public enum InterruptClass
{
/// <summary>
/// 不中断
/// </summary>
None,
/// <summary>
/// 分支中断,中断进入当前节点的分支。
/// </summary>
Branch,
/// <summary>
/// 全局中断,中断全局所有节点的运行。(暂未实现相关)
/// </summary>
Global,
}
}

View File

@@ -85,9 +85,6 @@ namespace Serein.Library
}
public abstract partial class NodeModelBase : IDynamicFlowNode
{
public NodeModelBase(IFlowEnvironment environment)
@@ -119,39 +116,40 @@ namespace Serein.Library
/// <summary>
/// 控制FlowData在同一时间只会被同一个线程更改。
/// </summary>
private readonly ReaderWriterLockSlim _flowDataLock = new ReaderWriterLockSlim();
private object _flowData;
/// <summary>
/// 当前传递数据(执行了节点对应的方法,才会存在值)。
/// </summary>
protected object FlowData
{
get
{
_flowDataLock.EnterReadLock();
try
{
return _flowData;
}
finally
{
_flowDataLock.ExitReadLock();
}
}
set
{
_flowDataLock.EnterWriteLock();
try
{
_flowData = value;
}
finally
{
_flowDataLock.ExitWriteLock();
}
}
}
//private readonly ReaderWriterLockSlim _flowDataLock = new ReaderWriterLockSlim();
//private object _flowData;
///// <summary>
///// 当前传递数据(执行了节点对应的方法,才会存在值)。
///// </summary>
//protected object FlowData
//{
// get
// {
// _flowDataLock.EnterReadLock();
// try
// {
// return _flowData;
// }
// finally
// {
// _flowDataLock.ExitReadLock();
// }
// }
// set
// {
// _flowDataLock.EnterWriteLock();
// try
// {
// _flowData = value;
// }
// finally
// {
// _flowDataLock.ExitWriteLock();
// }
// }
//}
}
}
@@ -319,5 +317,5 @@ namespace Serein.Library
//}
}

View File

@@ -31,7 +31,7 @@ namespace Serein.Library
/// 获取节点参数
/// </summary>
/// <returns></returns>
public abstract Parameterdata[] GetParameterdatas();
public abstract ParameterData[] GetParameterdatas();
/// <summary>
/// 导出为节点信息
@@ -47,7 +47,7 @@ namespace Serein.Library
var upstreamNodes = SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支
// 生成参数列表
Parameterdata[] parameterData = GetParameterdatas();
ParameterData[] parameterData = GetParameterdatas();
return new NodeInfo
{
@@ -82,9 +82,13 @@ namespace Serein.Library
{
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
{
Parameterdata pd = nodeInfo.ParameterData[i];
this.MethodDetails.ParameterDetailss[i].IsExplicitData = pd.State;
this.MethodDetails.ParameterDetailss[i].DataValue = pd.Value;
var mdPd = this.MethodDetails.ParameterDetailss[i];
ParameterData pd = nodeInfo.ParameterData[i];
mdPd.IsExplicitData = pd.State;
mdPd.DataValue = pd.Value;
mdPd.ArgDataSourceType = EnumHelper.ConvertEnum<ConnectionArgSourceType>(pd.SourceType);
mdPd.ArgDataSourceNodeGuid = pd.SourceNodeGuid;
}
}
return this;
@@ -93,13 +97,12 @@ namespace Serein.Library
#region
/// <summary>
/// 不再中断
/// </summary>
public void CancelInterrupt()
{
this.DebugSetting.InterruptClass = InterruptClass.None;
this.DebugSetting.IsInterrupt = false;
DebugSetting.CancelInterruptCallback?.Invoke();
}
@@ -165,7 +168,7 @@ namespace Serein.Library
NodeModelBase upstreamNode = upstreamNodes[index];
if (!(upstreamNode is null) && upstreamNode.DebugSetting.IsEnable)
{
if (upstreamNode.DebugSetting.InterruptClass != InterruptClass.None) // 执行触发前
if (upstreamNode.DebugSetting.IsInterrupt) // 执行触发前
{
var cancelType = await upstreamNode.DebugSetting.GetInterruptTask();
await Console.Out.WriteLineAsync($"[{upstreamNode.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
@@ -220,7 +223,7 @@ namespace Serein.Library
{
#region
if (DebugSetting.InterruptClass != InterruptClass.None) // 执行触发检查是否需要中断
if (DebugSetting.IsInterrupt) // 执行触发检查是否需要中断
{
var cancelType = await this.DebugSetting.GetInterruptTask(); // 等待中断结束
await Console.Out.WriteLineAsync($"[{this.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
@@ -312,8 +315,9 @@ namespace Serein.Library
}
object[] parameters = new object[md.ParameterDetailss.Length];
var previousFlowData = nodeModel.PreviousNode?.FlowData; // 当前传递的数据
var previousDataType = previousFlowData?.GetType(); // 当前传递数据的类型
//var previousFlowData = nodeModel.PreviousNode?.FlowData; // 当前传递数据
for (int i = 0; i < parameters.Length; i++)
{
@@ -336,41 +340,48 @@ namespace Serein.Library
object inputParameter; // 存放解析的临时参数
if (ed.IsExplicitData) // 判断是否使用显示的输入参数
{
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase) && !(previousFlowData is null))
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
{
var previousFlowData = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
// 执行表达式从上一节点获取对象
inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, previousFlowData, out _);
}
else
{
// 使用输入的固定值
inputParameter = ed.DataValue;
inputParameter = ed.DataValue;
}
}
else
{
if (ed.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
{
inputParameter = previousFlowData; // 使用运行时上一节点的返回值
inputParameter = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
}
else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
{
// 获取指定节点的数据
// 如果指定节点没有被执行会返回null
// 如果执行过,会获取上一次执行结果作为预入参数据
inputParameter = ed.ArgDataSourceNodeMoels[i].FlowData;
inputParameter = context.GetFlowData(ed.ArgDataSourceNodeGuid);
}
else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
{
// 立刻调用对应节点获取数据。
var result = await ed.ArgDataSourceNodeMoels[i].InvokeAsync(nodeModel.Env);
var result = await context.Env.InvokeNodeAsync(ed.ArgDataSourceNodeGuid);
inputParameter = result;
}
else
{
throw new Exception("节点执行方法获取入参参数时ConnectionArgSourceType枚举是意外的枚举值");
}
}
}
if (inputParameter is null)
{
throw new Exception($"[arg{ed.Index}][{ed.Name}][{ed.DataType}]参数不能为null");
}
#endregion
#region
@@ -418,7 +429,7 @@ namespace Serein.Library
#endregion
#region
if (inputParameter.GetType() == ed.DataType)
{
parameters[i] = inputParameter; // 类型一致无需转换,直接装入入参数组
@@ -506,8 +517,8 @@ namespace Serein.Library
{
await MonitorObjExpInterrupt(context, nodeModel, newData, 0); // 首先监视对象
await MonitorObjExpInterrupt(context, nodeModel, newData, 1); // 然后监视节点
nodeModel.FlowData = newData; // 替换数据
context.AddOrUpdate(guid, nodeModel); // 上下文中更新数据
//nodeModel.FlowData = newData; // 替换数据
context.AddOrUpdate(guid, newData); // 上下文中更新数据
}
}
@@ -548,12 +559,13 @@ namespace Serein.Library
if (isExpInterrupt) // 触发中断
{
InterruptClass interruptClass = InterruptClass.Branch; // 分支中断
if (await context.Env.SetNodeInterruptAsync(nodeModel.Guid, interruptClass))
nodeModel.DebugSetting.IsInterrupt = true;
if (await context.Env.SetNodeInterruptAsync(nodeModel.Guid,true))
{
context.Env.TriggerInterrupt(nodeModel.Guid, exp, InterruptTriggerEventArgs.InterruptTriggerType.Exp);
var cancelType = await nodeModel.DebugSetting.GetInterruptTask();
await Console.Out.WriteLineAsync($"[{data}]中断已{cancelType},开始执行后继分支");
nodeModel.DebugSetting.IsInterrupt = false;
}
}
}
@@ -561,26 +573,26 @@ namespace Serein.Library
}
}
/// <summary>
/// 释放对象
/// </summary>
public void ReleaseFlowData()
{
if (typeof(IDisposable).IsAssignableFrom(FlowData?.GetType()) && FlowData is IDisposable disposable)
{
disposable?.Dispose();
}
this.FlowData = null;
}
///// <summary>
///// 释放对象
///// </summary>
//public void ReleaseFlowData()
//{
// if (typeof(IDisposable).IsAssignableFrom(FlowData?.GetType()) && FlowData is IDisposable disposable)
// {
// disposable?.Dispose();
// }
// this.FlowData = null;
//}
/// <summary>
/// 获取节点数据
/// </summary>
/// <returns></returns>
public object GetFlowData()
{
return this.FlowData;
}
///// <summary>
///// 获取节点数据
///// </summary>
///// <returns></returns>
//public object GetFlowData()
//{
// return this.FlowData;
//}
#endregion
}

View File

@@ -1,4 +1,5 @@
using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Linq;
@@ -62,11 +63,10 @@ namespace Serein.Library
/// <summary>
/// 当 ArgDataSourceType 不为 GetPreviousNodeData 时(从运行时上一节点获取数据)。
/// 则通过该集合对应的节点,获取其 FlowData 作为预处理的入参参数。
/// 则通过当前上下文获取该Guid对应的数据作为预处理的入参参数。
/// </summary>
[PropertyInfo(IsProtection = true)]
public NodeModelBase[] _argDataSourceNodeMoels;
[PropertyInfo]
private string _argDataSourceNodeGuid;
/// <summary>
@@ -97,6 +97,16 @@ namespace Serein.Library
public partial class ParameterDetails
{
/// <summary>
/// 用于创建元数据
/// </summary>
public ParameterDetails()
{
}
/// <summary>
/// 为节点实例化新的入参描述
/// </summary>
@@ -112,27 +122,15 @@ namespace Serein.Library
/// <param name="info">参数信息</param>
public ParameterDetails(ParameterDetailsInfo info)
{
//this.env = env;
Index = info.Index;
Name = info.Name;
DataType = Type.GetType(info.DataTypeFullName);
ExplicitType = Type.GetType(info.ExplicitTypeFullName);
ExplicitTypeName = info.ExplicitTypeName;
Items = info.Items;
}
/// <summary>
/// 用于创建元数据
/// </summary>
public ParameterDetails()
{
}
/// <summary>
/// 转为描述
/// </summary>
@@ -141,12 +139,12 @@ namespace Serein.Library
{
return new ParameterDetailsInfo
{
Index = Index,
DataTypeFullName = DataType.FullName,
Name = Name,
ExplicitTypeFullName = ExplicitType.FullName,
ExplicitTypeName = ExplicitTypeName,
Items = Items,
Index = this.Index,
DataTypeFullName = this.DataType.FullName,
Name = this.Name,
ExplicitTypeFullName = this.ExplicitType.FullName,
ExplicitTypeName = this.ExplicitTypeName,
Items = this.Items.Select(it => it).ToArray(),
};
}
@@ -154,7 +152,7 @@ namespace Serein.Library
/// 为某个节点拷贝方法描述的入参描述
/// </summary>
/// <param name="env">运行环境</param>
/// <param name="nodeGuid">运行环境</param>
/// <param name="nodeModel">对应的节点</param>
/// <returns></returns>
public ParameterDetails CloneOfClone(IFlowEnvironment env, NodeModelBase nodeModel)
{

View File

@@ -8,7 +8,7 @@ namespace Serein.Library
{
/// <summary>
/// 方法入参描述
/// 方法入参描述(远程用)
/// </summary>
public class ParameterDetailsInfo
{
@@ -26,6 +26,7 @@ namespace Serein.Library
/// 方法入参参数名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 显式类型
/// </summary>

View File

@@ -202,14 +202,13 @@ namespace Serein.Library
/// <summary>
/// 参数
/// </summary>
public Parameterdata[] ParameterData { get; set; }
public ParameterData[] ParameterData { get; set; }
/// <summary>
/// 如果是区域控件,则会存在子项。
/// </summary>
public string[] ChildNodeGuids { get; set; }
/// <summary>
/// 于画布中的位置
/// </summary>
@@ -223,14 +222,26 @@ namespace Serein.Library
}
/// <summary>
/// 显示参数,项目文件相关
/// 参数信息,项目文件相关
/// </summary>
public class Parameterdata
public class ParameterData
{
/// <summary>
/// 参数类型true时使用自定义的入参false时由运行环境自动传参
/// </summary>
public bool State { get; set; }
/// <summary>
/// 参数来源节点
/// </summary>
public string SourceNodeGuid { get; set; }
/// <summary>
/// 来源类型
/// </summary>
public string SourceType { get; set; }
/// <summary>
/// 自定义入参
/// </summary>