mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 15:50:47 +08:00
修改了流程运行中的bug
This commit is contained in:
@@ -36,25 +36,55 @@ namespace Serein.Library.Core.NodeFlow
|
||||
public ConnectionInvokeType NextOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个上下文分别存放节点的当前数据
|
||||
/// 每个流程上下文分别存放节点的当前数据
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string,object?> dictNodeFlowData = new ConcurrentDictionary<string, object?>();
|
||||
private readonly ConcurrentDictionary<string, object?> dictNodeFlowData = new ConcurrentDictionary<string, object?>();
|
||||
|
||||
/// <summary>
|
||||
/// 每个流程上下文存储运行时节点的调用关系
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<NodeModelBase, NodeModelBase> dictPreviousNodes = new ConcurrentDictionary<NodeModelBase, NodeModelBase>();
|
||||
|
||||
/// <summary>
|
||||
/// 设置运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel">当前节点</param>
|
||||
/// <param name="PreviousNode">上一节点</param>
|
||||
public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
|
||||
{
|
||||
dictPreviousNodes.AddOrUpdate(currentNodeModel, (_)=> PreviousNode, (_,_) => PreviousNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel"></param>
|
||||
/// <returns></returns>
|
||||
public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel)
|
||||
{
|
||||
if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点当前数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <returns></returns>
|
||||
public object? GetFlowData(string nodeGuid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if(dictNodeFlowData.TryGetValue(nodeGuid,out var data))
|
||||
if(dictNodeFlowData.TryGetValue(nodeGuid, out var data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -63,14 +93,32 @@ namespace Serein.Library.Core.NodeFlow
|
||||
/// <summary>
|
||||
/// 添加或更新当前节点数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <param name="flowData">新的数据</param>
|
||||
public void AddOrUpdate(string nodeGuid,object? flowData)
|
||||
public void AddOrUpdate(string nodeGuid, object? flowData)
|
||||
{
|
||||
// this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData);
|
||||
this.dictNodeFlowData.AddOrUpdate(nodeGuid, _ => flowData, (_, _) => flowData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一节点数据透传到下一节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
public object? TransmissionData(NodeModelBase nodeModel)
|
||||
{
|
||||
if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点
|
||||
{
|
||||
if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据
|
||||
{
|
||||
return data;
|
||||
//AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
RunState = RunState.Running;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
@@ -40,10 +39,38 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, object> dictNodeFlowData = new ConcurrentDictionary<string, object>();
|
||||
|
||||
private readonly ConcurrentDictionary<NodeModelBase, NodeModelBase> dictPreviousNodes = new ConcurrentDictionary<NodeModelBase, NodeModelBase>();
|
||||
|
||||
/// <summary>
|
||||
/// 设置运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel">当前节点</param>
|
||||
/// <param name="PreviousNode">上一节点</param>
|
||||
public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
|
||||
{
|
||||
dictPreviousNodes.AddOrUpdate(currentNodeModel, (n1) => PreviousNode, (n1, n2) => PreviousNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel"></param>
|
||||
/// <returns></returns>
|
||||
public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel)
|
||||
{
|
||||
if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点当前数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <returns></returns>
|
||||
public object GetFlowData(string nodeGuid)
|
||||
{
|
||||
@@ -51,6 +78,7 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -59,14 +87,32 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
/// <summary>
|
||||
/// 添加或更新当前节点数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <param name="flowData">新的数据</param>
|
||||
public void AddOrUpdate(string nodeGuid, object flowData)
|
||||
{
|
||||
// this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData);
|
||||
this.dictNodeFlowData[nodeGuid] = flowData;
|
||||
this.dictNodeFlowData.AddOrUpdate(nodeGuid, n1 => flowData, (n1, n2)=> flowData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一节点数据透传到下一节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
public object TransmissionData(NodeModelBase nodeModel)
|
||||
{
|
||||
if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点
|
||||
{
|
||||
if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据
|
||||
{
|
||||
return data;
|
||||
//AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
@@ -74,7 +120,11 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
{
|
||||
foreach (var nodeObj in dictNodeFlowData.Values)
|
||||
{
|
||||
if (nodeObj != null)
|
||||
if (nodeObj is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable)
|
||||
{
|
||||
@@ -85,7 +135,6 @@ namespace Serein.Library.Framework.NodeFlow
|
||||
this.dictNodeFlowData?.Clear();
|
||||
RunState = RunState.Completion;
|
||||
}
|
||||
|
||||
// public NodeRunCts NodeRunCts { get; set; }
|
||||
// public ISereinIOC SereinIoc { get; }
|
||||
//public Task CreateTimingTask(Action action, int time = 100, int count = -1)
|
||||
|
||||
@@ -21,10 +21,24 @@ namespace Serein.Library.Api
|
||||
RunState RunState { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下一个要执行的节点
|
||||
/// 下一个要执行的节点类别
|
||||
/// </summary>
|
||||
ConnectionInvokeType NextOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置节点的运行时上一节点,用以多线程中隔开不同流程的数据
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel">当前节点</param>
|
||||
/// <param name="PreviousNode">运行时上一节点</param>
|
||||
void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode);
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的运行时上一节点,用以流程中获取数据
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel"></param>
|
||||
/// <returns></returns>
|
||||
NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel);
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取
|
||||
/// </summary>
|
||||
@@ -32,6 +46,13 @@ namespace Serein.Library.Api
|
||||
/// <returns></returns>
|
||||
object GetFlowData(string nodeGuid);
|
||||
|
||||
/// <summary>
|
||||
/// 上一节点数据透传到下一节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
object TransmissionData(NodeModelBase nodeModel);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新当前节点的数据
|
||||
/// </summary>
|
||||
|
||||
@@ -13,11 +13,11 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 取消触发器当前所在分支的继续执行
|
||||
/// </summary>
|
||||
Branch,
|
||||
CancelBranch,
|
||||
/// <summary>
|
||||
/// 取消整个触发器流程的再次执行(用于停止全局触发器)
|
||||
/// </summary>
|
||||
Flow,
|
||||
CancelFlow,
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否已取消
|
||||
@@ -27,7 +27,7 @@ namespace Serein.Library
|
||||
/// 取消类型
|
||||
/// </summary>
|
||||
public CancelClass Type { get; }
|
||||
public FlipflopException(string message, bool isCancel = true,CancelClass clsss = CancelClass.Branch) :base(message)
|
||||
public FlipflopException(string message, bool isCancel = true,CancelClass clsss = CancelClass.CancelBranch) :base(message)
|
||||
{
|
||||
IsCancel = isCancel;
|
||||
Type = clsss;
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace Serein.Library
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine($"方法别名:{this.MethodAnotherName}");
|
||||
sb.AppendLine($"方法名称:{this.MethodName}");
|
||||
sb.AppendLine($"需要实例:{this.ActingInstanceType.FullName}");
|
||||
sb.AppendLine($"需要实例:{this.ActingInstanceType?.FullName}");
|
||||
sb.AppendLine($"");
|
||||
sb.AppendLine($"入参参数信息:");
|
||||
foreach (var arg in this.ParameterDetailss)
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 中断级别,暂时停止继续执行后继分支。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"
|
||||
[PropertyInfo(IsNotification = true, CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);")] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"
|
||||
private bool _isInterrupt = false;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -66,8 +66,8 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 运行时的上一节点
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
private NodeModelBase _previousNode ;
|
||||
//[PropertyInfo]
|
||||
//private NodeModelBase _previousNode ;
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点执行完毕后需要执行的下一个分支的类别
|
||||
@@ -86,6 +86,11 @@ namespace Serein.Library
|
||||
|
||||
public abstract partial class NodeModelBase : IDynamicFlowNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public abstract void OnLoading();
|
||||
|
||||
public NodeModelBase(IFlowEnvironment environment)
|
||||
{
|
||||
PreviousNodes = new Dictionary<ConnectionInvokeType, List<NodeModelBase>>();
|
||||
@@ -100,7 +105,6 @@ namespace Serein.Library
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 不同分支的父节点
|
||||
/// </summary>
|
||||
@@ -111,210 +115,7 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public Dictionary<ConnectionInvokeType, List<NodeModelBase>> SuccessorNodes { get; }
|
||||
|
||||
|
||||
/// <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();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
|
||||
/// </summary>
|
||||
public abstract partial class NodeModelBase : IDynamicFlowNode
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 节点保留对环境的引用,因为需要在属性更改时通知
|
||||
/// </summary>
|
||||
public IFlowEnvironment Env { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 在画布中的位置
|
||||
/// </summary>
|
||||
public PositionOfUI Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 附加的调试功能
|
||||
/// </summary>
|
||||
public NodeDebugSetting DebugSetting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述节点对应的控件类型
|
||||
/// </summary>
|
||||
public NodeControlType ControlType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 方法描述。不包含Method与委托,需要通过MethodName从环境中获取委托进行调用。
|
||||
/// </summary>
|
||||
public MethodDetails MethodDetails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标识节点对象全局唯一
|
||||
/// </summary>
|
||||
public string Guid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为起点控件
|
||||
/// </summary>
|
||||
public bool IsStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 运行时的上一节点
|
||||
/// </summary>
|
||||
public NodeModelBase PreviousNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点执行完毕后需要执行的下一个分支的类别
|
||||
/// </summary>
|
||||
public ConnectionType NextOrientation { get; set; } = ConnectionType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
|
||||
/// </summary>
|
||||
public Exception RuningException { get; set; } = null;
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
|
||||
/// </summary>
|
||||
//public class NodeModelBaseBuilder
|
||||
//{
|
||||
// public NodeModelBaseBuilder(NodeModelBase builder)
|
||||
// {
|
||||
// this.ControlType = builder.ControlType;
|
||||
// this.MethodDetails = builder.MethodDetails;
|
||||
// this.Guid = builder.Guid;
|
||||
// this.DisplayName = builder.DisplayName;
|
||||
// this.IsStart = builder.IsStart;
|
||||
// this.PreviousNode = builder.PreviousNode;
|
||||
// this.PreviousNodes = builder.PreviousNodes;
|
||||
// this.SucceedBranch = builder.SucceedBranch;
|
||||
// this.FailBranch = builder.FailBranch;
|
||||
// this.ErrorBranch = builder.ErrorBranch;
|
||||
// this.UpstreamBranch = builder.UpstreamBranch;
|
||||
// this.FlowState = builder.FlowState;
|
||||
// this.RuningException = builder.RuningException;
|
||||
// this.FlowData = builder.FlowData;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// 节点对应的控件类型
|
||||
// /// </summary>
|
||||
// public NodeControlType ControlType { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// 方法描述,对应DLL的方法
|
||||
// /// </summary>
|
||||
// public MethodDetails MethodDetails { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// 节点guid
|
||||
// /// </summary>
|
||||
// public string Guid { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// 显示名称
|
||||
// /// </summary>
|
||||
// public string DisplayName { get;}
|
||||
|
||||
// /// <summary>
|
||||
// /// 是否为起点控件
|
||||
// /// </summary>
|
||||
// public bool IsStart { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// 运行时的上一节点
|
||||
// /// </summary>
|
||||
// public NodeModelBase? PreviousNode { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// 上一节点集合
|
||||
// /// </summary>
|
||||
// public List<NodeModelBase> PreviousNodes { get; } = [];
|
||||
|
||||
// /// <summary>
|
||||
// /// 下一节点集合(真分支)
|
||||
// /// </summary>
|
||||
// public List<NodeModelBase> SucceedBranch { get; } = [];
|
||||
|
||||
// /// <summary>
|
||||
// /// 下一节点集合(假分支)
|
||||
// /// </summary>
|
||||
// public List<NodeModelBase> FailBranch { get; } = [];
|
||||
|
||||
// /// <summary>
|
||||
// /// 异常分支
|
||||
// /// </summary>
|
||||
// public List<NodeModelBase> ErrorBranch { get; } = [];
|
||||
|
||||
// /// <summary>
|
||||
// /// 上游分支
|
||||
// /// </summary>
|
||||
// public List<NodeModelBase> UpstreamBranch { get; } = [];
|
||||
|
||||
// /// <summary>
|
||||
// /// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定)
|
||||
// /// </summary>
|
||||
// public FlowStateType FlowState { get; set; } = FlowStateType.None;
|
||||
|
||||
// /// <summary>
|
||||
// /// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
|
||||
// /// </summary>
|
||||
// public Exception RuningException { get; set; } = null;
|
||||
|
||||
// /// <summary>
|
||||
// /// 当前传递数据(执行了节点对应的方法,才会存在值)
|
||||
// /// </summary>
|
||||
// public object? FlowData { get; set; } = null;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Serein.Library
|
||||
var cancelType = await upstreamNode.DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{upstreamNode.MethodDetails?.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
upstreamNode.PreviousNode = currentNode;
|
||||
context.SetPreviousNode(upstreamNode, currentNode);
|
||||
await upstreamNode.StartFlowAsync(context); // 执行流程节点的上游分支
|
||||
if (context.NextOrientation == ConnectionInvokeType.IsError)
|
||||
{
|
||||
@@ -186,6 +186,7 @@ namespace Serein.Library
|
||||
}
|
||||
// 上游分支执行完成,才执行当前节点
|
||||
if (IsBradk(context, flowCts)) break; // 退出执行
|
||||
context.NextOrientation = ConnectionInvokeType.None; // 重置上下文状态
|
||||
object newFlowData = await currentNode.ExecutingAsync(context);
|
||||
if (IsBradk(context, flowCts)) break; // 退出执行
|
||||
|
||||
@@ -204,7 +205,7 @@ namespace Serein.Library
|
||||
// 筛选出启用的节点的节点
|
||||
if (nextNodes[i].DebugSetting.IsEnable)
|
||||
{
|
||||
nextNodes[i].PreviousNode = currentNode;
|
||||
context.SetPreviousNode(nextNodes[i], currentNode);
|
||||
stack.Push(nextNodes[i]);
|
||||
}
|
||||
}
|
||||
@@ -248,7 +249,10 @@ namespace Serein.Library
|
||||
{
|
||||
object[] args = await GetParametersAsync(context, this, md);
|
||||
var result = await dd.InvokeAsync(md.ActingInstance, args);
|
||||
context.NextOrientation = ConnectionInvokeType.IsSucceed;
|
||||
if(context.NextOrientation == ConnectionInvokeType.None) // 没有手动设置时,进行自动设置
|
||||
{
|
||||
context.NextOrientation = ConnectionInvokeType.IsSucceed;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -342,7 +346,10 @@ namespace Serein.Library
|
||||
{
|
||||
if (ed.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var previousFlowData = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
|
||||
var previousNode = context.GetPreviousNode(nodeModel);
|
||||
var previousFlowData = context.GetFlowData(previousNode.Guid); // 当前传递的数据
|
||||
|
||||
|
||||
// 执行表达式从上一节点获取对象
|
||||
inputParameter = SerinExpressionEvaluator.Evaluate(ed.DataValue, previousFlowData, out _);
|
||||
}
|
||||
@@ -356,7 +363,8 @@ namespace Serein.Library
|
||||
{
|
||||
if (ed.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
inputParameter = context.GetFlowData(nodeModel?.PreviousNode?.Guid); // 当前传递的数据
|
||||
var previousNode = context.GetPreviousNode(nodeModel);
|
||||
inputParameter = context.GetFlowData(previousNode.Guid); // 当前传递的数据
|
||||
}
|
||||
else if (ed.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeData)
|
||||
{
|
||||
@@ -509,6 +517,7 @@ namespace Serein.Library
|
||||
public static async Task RefreshFlowDataAndExpInterrupt(IDynamicContext context, NodeModelBase nodeModel, object newData = null)
|
||||
{
|
||||
string guid = nodeModel.Guid;
|
||||
context.AddOrUpdate(guid, newData); // 上下文中更新数据
|
||||
if (newData is null)
|
||||
{
|
||||
}
|
||||
@@ -517,7 +526,6 @@ namespace Serein.Library
|
||||
await MonitorObjExpInterrupt(context, nodeModel, newData, 0); // 首先监视对象
|
||||
await MonitorObjExpInterrupt(context, nodeModel, newData, 1); // 然后监视节点
|
||||
//nodeModel.FlowData = newData; // 替换数据
|
||||
context.AddOrUpdate(guid, newData); // 上下文中更新数据
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Serein.Library
|
||||
{
|
||||
if(_convertor is null)
|
||||
{
|
||||
return $"[{this.Index}] {this.Name} : {this.DataType.FullName}";
|
||||
return $"[{this.Index}] {this.Name} : {this.DataType?.FullName}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Utils.SereinExpression
|
||||
{
|
||||
@@ -152,53 +155,88 @@ namespace Serein.Library.Utils.SereinExpression
|
||||
throw new ArgumentException($"Invalid array syntax for member {member}");
|
||||
}
|
||||
|
||||
// 提取数组索引
|
||||
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
|
||||
if (!int.TryParse(indexStr, out int index))
|
||||
var targetType = target?.GetType(); // 目标对象的类型
|
||||
if(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
||||
{
|
||||
throw new ArgumentException($"Invalid array index '{indexStr}' for member {member}");
|
||||
}
|
||||
|
||||
// 获取数组或集合对象
|
||||
var arrayProperty = target?.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty is null)
|
||||
{
|
||||
var arrayField = target?.GetType().GetField(arrayName);
|
||||
if (arrayField is null)
|
||||
var typetmp = target.GetType().FullName;
|
||||
// 目标是键值对
|
||||
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
|
||||
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
|
||||
if(method != null)
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} not found on target.");
|
||||
var result = method.Invoke(target, new object[] { indexStr });
|
||||
if(result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//var dict = target as Dictionary<string, string>;
|
||||
////var dict = (Dictionary<dynamic, dynamic>)target;
|
||||
//var temp = dict[indexStr];
|
||||
////if (target is Dictionary<object, object> dict)
|
||||
////{
|
||||
//// var temp = dict[indexStr];
|
||||
////}
|
||||
//var TMP2= target.GetType().GetEnumValues();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#region 表达式处理集合对象
|
||||
// 获取数组或集合对象
|
||||
var arrayProperty = target?.GetType().GetProperty(arrayName);
|
||||
if (arrayProperty is null)
|
||||
{
|
||||
var arrayField = target?.GetType().GetField(arrayName);
|
||||
if (arrayField is null)
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} not found on target.");
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayField.GetValue(target);
|
||||
target = arrayProperty.GetValue(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = arrayProperty.GetValue(target);
|
||||
|
||||
|
||||
// 提取数组索引
|
||||
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
|
||||
if (!int.TryParse(indexStr, out int index))
|
||||
{
|
||||
throw new ArgumentException($"Invalid array index '{indexStr}' for member {member}");
|
||||
}
|
||||
// 访问数组或集合中的指定索引
|
||||
if (target is Array array)
|
||||
{
|
||||
if (index < 0 || index >= array.Length)
|
||||
{
|
||||
throw new ArgumentException($"Index {index} out of bounds for array {arrayName}");
|
||||
}
|
||||
target = array.GetValue(index);
|
||||
}
|
||||
else if (target is IList<object> list)
|
||||
{
|
||||
if (index < 0 || index >= list.Count)
|
||||
{
|
||||
throw new ArgumentException($"Index {index} out of bounds for list {arrayName}");
|
||||
}
|
||||
target = list[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} is not an array or list.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
// 访问数组或集合中的指定索引
|
||||
if (target is Array array)
|
||||
{
|
||||
if (index < 0 || index >= array.Length)
|
||||
{
|
||||
throw new ArgumentException($"Index {index} out of bounds for array {arrayName}");
|
||||
}
|
||||
target = array.GetValue(index);
|
||||
}
|
||||
else if (target is IList<object> list)
|
||||
{
|
||||
if (index < 0 || index >= list.Count)
|
||||
{
|
||||
throw new ArgumentException($"Index {index} out of bounds for list {arrayName}");
|
||||
}
|
||||
target = list[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Member {arrayName} is not an array or list.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1438,8 +1438,7 @@ namespace Serein.NodeFlow.Env
|
||||
try
|
||||
{
|
||||
Assembly assembly = Assembly.LoadFrom(dllPath); // 加载DLL文件
|
||||
Type[] types = assembly.GetTypes(); // 获取程序集中的所有类型
|
||||
|
||||
List<Type> types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
||||
Dictionary<RegisterSequence, List<Type>> autoRegisterTypes = new Dictionary<RegisterSequence, List<Type>>();
|
||||
foreach (Type type in types)
|
||||
{
|
||||
@@ -1720,10 +1719,6 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
if (!string.IsNullOrEmpty(toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceNodeGuid))
|
||||
{
|
||||
//if(toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceType == connectionArgSourceType)
|
||||
//{
|
||||
// return ;
|
||||
//}
|
||||
await RemoteConnectAsync(fromNode,toNode,argIndex); // 已经存在连接,将其移除
|
||||
}
|
||||
toNode.MethodDetails.ParameterDetailss[argIndex].ArgDataSourceNodeGuid = fromNode.Guid;
|
||||
|
||||
@@ -55,8 +55,7 @@ namespace Serein.NodeFlow.Env
|
||||
var md = methodDetails.CloneOfNode(nodeModel.Env, nodeModel);
|
||||
nodeModel.DisplayName = md.MethodAnotherName;
|
||||
nodeModel.MethodDetails = md;
|
||||
|
||||
|
||||
nodeModel.OnLoading();
|
||||
return nodeModel;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,21 +169,6 @@ namespace Serein.NodeFlow
|
||||
|
||||
#endregion
|
||||
|
||||
#region 检查并修正初始化、加载时、退出时方法作用的对象,保证后续不会报错(已注释)
|
||||
//foreach (var md in initMethods) // 初始化
|
||||
//{
|
||||
// md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||
//}
|
||||
//foreach (var md in loadingMethods) // 加载
|
||||
//{
|
||||
// md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||
//}
|
||||
//foreach (var md in exitMethods) // 初始化
|
||||
//{
|
||||
// md.ActingInstance ??= Context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||
//}
|
||||
#endregion
|
||||
|
||||
#region 执行初始化,绑定IOC容器,再执行加载时
|
||||
|
||||
if (autoRegisterTypes.TryGetValue(RegisterSequence.FlowInit, out var flowInitTypes))
|
||||
@@ -356,7 +341,9 @@ namespace Serein.NodeFlow
|
||||
/// <param name="env">流程运行全局环境</param>
|
||||
/// <param name="singleFlipFlopNode">需要全局监听信号的触发器</param>
|
||||
/// <returns></returns>
|
||||
private async Task FlipflopExecuteAsync(IFlowEnvironment env, SingleFlipflopNode singleFlipFlopNode, CancellationTokenSource cts)
|
||||
private async Task FlipflopExecuteAsync(IFlowEnvironment env,
|
||||
SingleFlipflopNode singleFlipFlopNode,
|
||||
CancellationTokenSource cts)
|
||||
{
|
||||
if(_flipFlopCts is null)
|
||||
{
|
||||
@@ -369,34 +356,38 @@ namespace Serein.NodeFlow
|
||||
try
|
||||
{
|
||||
var newFlowData = await singleFlipFlopNode.ExecutingAsync(context); // 获取触发器等待Task
|
||||
context.AddOrUpdate(singleFlipFlopNode.Guid, newFlowData);
|
||||
await NodeModelBase.RefreshFlowDataAndExpInterrupt(context, singleFlipFlopNode, newFlowData); // 全局触发器触发后刷新该触发器的节点数据
|
||||
if (context.NextOrientation == ConnectionInvokeType.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var nextNodes = singleFlipFlopNode.SuccessorNodes[context.NextOrientation];
|
||||
for (int i = nextNodes.Count - 1; i >= 0 && !_flipFlopCts.IsCancellationRequested; i--)
|
||||
{
|
||||
// 筛选出启用的节点
|
||||
if (!nextNodes[i].DebugSetting.IsEnable)
|
||||
_ = Task.Run(async () => {
|
||||
var nextNodes = singleFlipFlopNode.SuccessorNodes[context.NextOrientation];
|
||||
for (int i = nextNodes.Count - 1; i >= 0 && !_flipFlopCts.IsCancellationRequested; i--)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// 筛选出启用的节点
|
||||
if (!nextNodes[i].DebugSetting.IsEnable)
|
||||
{
|
||||
continue ;
|
||||
}
|
||||
|
||||
nextNodes[i].PreviousNode = singleFlipFlopNode;
|
||||
if (nextNodes[i].DebugSetting.IsInterrupt) // 执行触发前
|
||||
{
|
||||
var cancelType = await nextNodes[i].DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{nextNodes[i].MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
context.SetPreviousNode(nextNodes[i], singleFlipFlopNode);
|
||||
if (nextNodes[i].DebugSetting.IsInterrupt) // 执行触发前
|
||||
{
|
||||
var cancelType = await nextNodes[i].DebugSetting.GetInterruptTask();
|
||||
await Console.Out.WriteLineAsync($"[{nextNodes[i].MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||
}
|
||||
await nextNodes[i].StartFlowAsync(context); // 启动执行触发器后继分支的节点
|
||||
context.Exit();
|
||||
}
|
||||
await nextNodes[i].StartFlowAsync(context); // 启动执行触发器后继分支的节点
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
catch (FlipflopException ex)
|
||||
{
|
||||
await Console.Out.WriteLineAsync($"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
|
||||
if (ex.Type == FlipflopException.CancelClass.Flow)
|
||||
if (ex.Type == FlipflopException.CancelClass.CancelFlow)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -407,7 +398,7 @@ namespace Serein.NodeFlow
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.Exit();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ namespace Serein.NodeFlow.Model
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public override void OnLoading()
|
||||
{
|
||||
Console.WriteLine("CompositeConditionNode 暂未实现 OnLoading");
|
||||
}
|
||||
|
||||
public void AddNode(SingleConditionNode node)
|
||||
{
|
||||
@@ -59,7 +66,8 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(context.GetFlowData(PreviousNode.Guid)); // 条件区域透传上一节点的数据
|
||||
//var previousNode = context.GetPreviousNode()
|
||||
return Task.FromResult(context.TransmissionData(this)); // 条件区域透传上一节点的数据
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,15 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public override void OnLoading()
|
||||
{
|
||||
Console.WriteLine("SingleActionNode 暂未实现 OnLoading");
|
||||
}
|
||||
|
||||
public override ParameterData[] GetParameterdatas()
|
||||
{
|
||||
if (base.MethodDetails.ParameterDetailss.Length > 0)
|
||||
|
||||
@@ -39,8 +39,34 @@ namespace Serein.NodeFlow.Model
|
||||
this.IsCustomData = false;
|
||||
this.CustomData = null;
|
||||
this.Expression = "PASS";
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public override void OnLoading()
|
||||
{
|
||||
var pd = new ParameterDetails
|
||||
{
|
||||
Index = 0,
|
||||
Name = "Exp",
|
||||
DataType = typeof(object),
|
||||
ExplicitType = typeof(object),
|
||||
IsExplicitData = false,
|
||||
DataValue = string.Empty,
|
||||
ArgDataSourceNodeGuid = string.Empty,
|
||||
ArgDataSourceType = ConnectionArgSourceType.GetPreviousNodeData,
|
||||
NodeModel = this,
|
||||
Convertor = null,
|
||||
ExplicitTypeName = "Value",
|
||||
Items = Array.Empty<string>(),
|
||||
};
|
||||
|
||||
this.MethodDetails.ParameterDetailss = new ParameterDetails[] { pd };
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重写节点的方法执行
|
||||
/// </summary>
|
||||
@@ -50,7 +76,7 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
// 接收上一节点参数or自定义参数内容
|
||||
object? parameter;
|
||||
object? result = context.GetFlowData(PreviousNode.Guid); // 条件节点透传上一节点的数据
|
||||
object? result = context.TransmissionData(this); // 条件节点透传上一节点的数据
|
||||
if (IsCustomData) // 是否使用自定义参数
|
||||
{
|
||||
// 表达式获取上一节点数据
|
||||
|
||||
@@ -28,10 +28,18 @@ namespace Serein.NodeFlow.Model
|
||||
|
||||
}
|
||||
|
||||
//public override async Task<object?> Executing(IDynamicContext context)
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public override void OnLoading()
|
||||
{
|
||||
Console.WriteLine("SingleExpOpNode 暂未实现 OnLoading");
|
||||
}
|
||||
|
||||
|
||||
public override Task<object?> ExecutingAsync(IDynamicContext context)
|
||||
{
|
||||
var data = context.GetFlowData(PreviousNode.Guid); // 表达式节点使用上一节点数据
|
||||
var data = context.TransmissionData(this); // 表达式节点使用上一节点数据
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -16,6 +16,14 @@ namespace Serein.NodeFlow.Model
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载完成后调用的方法
|
||||
/// </summary>
|
||||
public override void OnLoading()
|
||||
{
|
||||
Console.WriteLine("SingleFlipflopNode 暂未实现 OnLoading");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行触发器进行等待触发
|
||||
@@ -56,7 +64,7 @@ namespace Serein.NodeFlow.Model
|
||||
}
|
||||
catch (FlipflopException ex)
|
||||
{
|
||||
if(ex.Type == FlipflopException.CancelClass.Flow)
|
||||
if(ex.Type == FlipflopException.CancelClass.CancelFlow)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
30
Serein.BaseNode/Serein.BaseNode.csproj
Normal file
30
Serein.BaseNode/Serein.BaseNode.csproj
Normal file
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>1.0.0</Version>
|
||||
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
|
||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Title>SereinFow</Title>
|
||||
<Description>基础节点</Description>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
<None Include="..\README.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
52
Serein.BaseNode/SereinBaseNodes.cs
Normal file
52
Serein.BaseNode/SereinBaseNodes.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils.SereinExpression;
|
||||
|
||||
namespace Serein.BaseNode
|
||||
{
|
||||
|
||||
public enum ExpType
|
||||
{
|
||||
Get,
|
||||
Set
|
||||
}
|
||||
[DynamicFlow(Name ="基础节点")]
|
||||
internal class SereinBaseNodes
|
||||
{
|
||||
[NodeAction(NodeType.Action,"条件节点")]
|
||||
private bool SereinConditionNode(IDynamicContext context,
|
||||
object targetObject,
|
||||
string exp = "ISPASS")
|
||||
{
|
||||
var isPass = SereinConditionParser.To(targetObject, exp);
|
||||
context.NextOrientation = isPass ? ConnectionInvokeType.IsSucceed : ConnectionInvokeType.IsFail;
|
||||
return isPass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "表达式节点")]
|
||||
private object SereinExpNode(IDynamicContext context,
|
||||
object targetObject,
|
||||
string exp)
|
||||
{
|
||||
|
||||
exp = "@" + exp;
|
||||
var newData = SerinExpressionEvaluator.Evaluate(exp, targetObject, out bool isChange);
|
||||
object result;
|
||||
if (isChange || exp.StartsWith("@GET",System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = newData;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = targetObject;
|
||||
}
|
||||
context.NextOrientation = ConnectionInvokeType.IsSucceed;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,11 +20,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library", "Library\S
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net462DllTest", "Net462DllTest\Net462DllTest.csproj", "{E40EE629-1A38-4011-88E3-9AD036869987}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Extend.RemoteControl", "Extend.FlowRemoteManagement\Serein.Extend.RemoteControl.csproj", "{3E568C47-74C6-4C28-9D43-C9BA29008DB7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.FlowStartTool", "FlowStartTool\Serein.FlowStartTool.csproj", "{38D0FA92-5139-4616-A41E-8186AA4C1532}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serein.Library.NodeGenerator", "Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj", "{5F7DE0B2-A5D3-492D-AC6C-F0C39EBEF365}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library.NodeGenerator", "Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj", "{5F7DE0B2-A5D3-492D-AC6C-F0C39EBEF365}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serein.BaseNode", "Serein.BaseNode\Serein.BaseNode.csproj", "{9E7CEECB-EC9F-4D5F-8A04-49865B6DEC99}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -56,10 +56,6 @@ Global
|
||||
{E40EE629-1A38-4011-88E3-9AD036869987}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E40EE629-1A38-4011-88E3-9AD036869987}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E40EE629-1A38-4011-88E3-9AD036869987}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -68,6 +64,10 @@ Global
|
||||
{5F7DE0B2-A5D3-492D-AC6C-F0C39EBEF365}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5F7DE0B2-A5D3-492D-AC6C-F0C39EBEF365}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5F7DE0B2-A5D3-492D-AC6C-F0C39EBEF365}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E7CEECB-EC9F-4D5F-8A04-49865B6DEC99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E7CEECB-EC9F-4D5F-8A04-49865B6DEC99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E7CEECB-EC9F-4D5F-8A04-49865B6DEC99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E7CEECB-EC9F-4D5F-8A04-49865B6DEC99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace Serein.Workbench
|
||||
void LoadLocalProject()
|
||||
{
|
||||
#if DEBUG
|
||||
if (1 == 1)
|
||||
if (1 == 11)
|
||||
{
|
||||
string filePath;
|
||||
filePath = @"F:\临时\project\linux\project.dnf";
|
||||
filePath = @"F:\临时\project\linux\http\project.dnf";
|
||||
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
||||
App.FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||
App.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
|
||||
|
||||
@@ -89,15 +89,16 @@
|
||||
<!--<Button Grid.Row="0" Content="卸载清空" Click="UnloadAllButton_Click" HorizontalAlignment="Right" Margin="5,5,5,5"/>--><!--
|
||||
</Grid>-->
|
||||
|
||||
<!--暂时隐藏基础面板-->
|
||||
<ScrollViewer Grid.Row="0" Visibility="Collapsed" HorizontalScrollBarVisibility="Auto">
|
||||
<!--暂时隐藏基础面板 Visibility="Collapsed" -->
|
||||
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<nodeView:ExpOpNodeControl x:Name="ExpOpNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ConditionNodeControl x:Name="ConditionNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ConditionRegionControl x:Name="ConditionRegionControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<ScrollViewer VerticalAlignment="Top" Grid.Row="1" VerticalScrollBarVisibility="Auto" MaxHeight="400" Grid.RowSpan="2">
|
||||
|
||||
<ScrollViewer VerticalAlignment="Top" Grid.Row="1" VerticalScrollBarVisibility="Auto" Grid.RowSpan="2">
|
||||
<StackPanel x:Name="DllStackPanel" Margin="5"/>
|
||||
</ScrollViewer>
|
||||
<!--<GridSplitter Grid.Row="3" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" ResizeBehavior="PreviousAndNext" Background="Gray"/>-->
|
||||
|
||||
@@ -511,10 +511,6 @@ namespace Serein.Workbench
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<Grid>
|
||||
<Grid.ToolTip>
|
||||
<ToolTip Background="LightYellow" Foreground="Black" Content="{Binding NodeModel.MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ToolTip Background="LightYellow" Foreground="Black" Content="{Binding NodeModel.MethodDetails.MethodAnotherName, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</Grid.ToolTip>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
@@ -25,16 +25,39 @@
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Border Grid.Row="0" Background="#A8D8EA" BorderBrush="#A8D8EA" BorderThickness="1" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="条件节点" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<Grid Grid.Row="1" Background="#F1FFDF" HorizontalAlignment="Stretch">
|
||||
|
||||
<Grid Grid.Row="0" Background="#A8D8EA" >
|
||||
<!--<Grid Grid.Row="0" >-->
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<local:ExecuteJunctionControl Grid.Column="0" MyNode="{Binding NodeModel}" x:Name="ExecuteJunctionControl" HorizontalAlignment="Left" Grid.RowSpan="2"/>
|
||||
<Border Grid.Column="1" BorderThickness="1" HorizontalAlignment="Stretch">
|
||||
<TextBlock Text="条件节点" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<local:NextStepJunctionControl Grid.Column="2" MyNode="{Binding NodeModel}" x:Name="NextStepJunctionControl" HorizontalAlignment="Right" Grid.RowSpan="2"/>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Background="#F1FFDF" HorizontalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox Grid.Column="0" IsChecked="{Binding NodeModel.IsCustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <!--Converter={StaticResource BoolToVis}-->
|
||||
<TextBox Grid.Column="1" MinWidth="50" Text="{Binding NodeModel.CustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
<local:ArgJunctionControl Grid.Column="0" x:Name="ArgJunctionControl" ArgIndex="0" MyNode="{Binding NodeModel}" />
|
||||
<CheckBox Grid.Column="1" IsChecked="{Binding NodeModel.IsCustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center"/> <!--Converter={StaticResource BoolToVis}-->
|
||||
<TextBox Grid.Column="2" MinWidth="50" Text="{Binding NodeModel.CustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
||||
<TextBox.Style>
|
||||
<Style TargetType="TextBox">
|
||||
@@ -48,7 +71,7 @@
|
||||
</TextBox.Style>
|
||||
</TextBox>
|
||||
|
||||
<TextBlock Grid.Column="1" MinWidth="50" Text="上一节点数据" HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
||||
<TextBlock Grid.Column="2" MinWidth="50" Text="上一节点数据" HorizontalAlignment="Stretch" VerticalAlignment="Center">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
@@ -60,9 +83,12 @@
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBox Grid.Row="1" Grid.ColumnSpan="3" Background="#F1FFDF" MinWidth="100" Text="{Binding NodeModel.Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
<TextBox Grid.Row="2" Background="#f1F66F" MinWidth="100" Text="{Binding NodeModel.Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Row="2" Background="#A8D8EA">
|
||||
<local:ResultJunctionControl Grid.Column="2" MyNode="{Binding NodeModel}" x:Name="ResultJunctionControl" HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
|
||||
<!--<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />
|
||||
<Border Grid.Row="2" Background="#EAFFD0" BorderBrush="#EAFFD0" BorderThickness="1">
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Serein.Workbench.Node.View
|
||||
/// <summary>
|
||||
/// ConditionNode.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ConditionNodeControl : NodeControlBase
|
||||
public partial class ConditionNodeControl : NodeControlBase, INodeJunction
|
||||
{
|
||||
public ConditionNodeControl() : base()
|
||||
{
|
||||
@@ -21,6 +21,37 @@ namespace Serein.Workbench.Node.View
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
/// <summary>
|
||||
/// 入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
|
||||
|
||||
/// <summary>
|
||||
/// 下一个调用方法控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
|
||||
|
||||
/// <summary>
|
||||
/// 返回值控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
private JunctionControlBase[] argDataJunction;
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction
|
||||
{
|
||||
get
|
||||
{
|
||||
argDataJunction = new JunctionControlBase[1];
|
||||
argDataJunction[0] = this.ArgJunctionControl;
|
||||
return argDataJunction;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,30 +10,30 @@ namespace Serein.Workbench.Node.ViewModel
|
||||
{
|
||||
public new SingleConditionNode NodeModel { get; }
|
||||
|
||||
///// <summary>
|
||||
///// 是否为自定义参数
|
||||
///// </summary>
|
||||
//public bool IsCustomData
|
||||
//{
|
||||
// get => Node.IsCustomData;
|
||||
// set { Node.IsCustomData= value; OnPropertyChanged(); }
|
||||
//}
|
||||
///// <summary>
|
||||
// /// 自定义参数值
|
||||
// /// </summary>
|
||||
//public object? CustomData
|
||||
//{
|
||||
// get => Node.CustomData;
|
||||
// set { Node.CustomData = value ; OnPropertyChanged(); }
|
||||
//}
|
||||
///// <summary>
|
||||
///// 表达式
|
||||
///// </summary>
|
||||
//public string Expression
|
||||
//{
|
||||
// get => Node.Expression;
|
||||
// set { Node.Expression = value; OnPropertyChanged(); }
|
||||
//}
|
||||
/// <summary>
|
||||
/// 是否为自定义参数
|
||||
/// </summary>
|
||||
public bool IsCustomData
|
||||
{
|
||||
get => NodeModel.IsCustomData;
|
||||
set { NodeModel.IsCustomData= value; OnPropertyChanged(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 自定义参数值
|
||||
/// </summary>
|
||||
public object? CustomData
|
||||
{
|
||||
get => NodeModel.CustomData;
|
||||
set { NodeModel.CustomData = value ; OnPropertyChanged(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// 表达式
|
||||
/// </summary>
|
||||
public string Expression
|
||||
{
|
||||
get => NodeModel.Expression;
|
||||
set { NodeModel.Expression = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 条件节点
|
||||
@@ -42,9 +42,9 @@ namespace Serein.Workbench.Node.ViewModel
|
||||
public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
|
||||
{
|
||||
this.NodeModel = node;
|
||||
//IsCustomData = false;
|
||||
//CustomData = "";
|
||||
//Expression = "PASS";
|
||||
IsCustomData = false;
|
||||
CustomData = "";
|
||||
Expression = "PASS";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user