mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-28 18:43:23 +08:00
优化了流程的进行
This commit is contained in:
@@ -65,15 +65,15 @@ namespace Serein.Library.Core.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class FlipflopContext : IFlipflopContext
|
public class FlipflopContext : IFlipflopContext
|
||||||
{
|
{
|
||||||
public FlowStateType State { get; set; }
|
public FlipflopStateType State { get; set; }
|
||||||
|
|
||||||
public object Data { get; set; }
|
public object Data { get; set; }
|
||||||
|
|
||||||
public FlipflopContext(FlowStateType ffState)
|
public FlipflopContext(FlipflopStateType ffState)
|
||||||
{
|
{
|
||||||
State = ffState;
|
State = ffState;
|
||||||
}
|
}
|
||||||
public FlipflopContext(FlowStateType ffState, object data)
|
public FlipflopContext(FlipflopStateType ffState, object data)
|
||||||
{
|
{
|
||||||
State = ffState;
|
State = ffState;
|
||||||
Data = data;
|
Data = data;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ namespace Serein.Library.Framework.NodeFlow
|
|||||||
SereinIoc = sereinIoc;
|
SereinIoc = sereinIoc;
|
||||||
FlowEnvironment = flowEnvironment;
|
FlowEnvironment = flowEnvironment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeRunCts NodeRunCts { get; set; }
|
public NodeRunCts NodeRunCts { get; set; }
|
||||||
public ISereinIoc SereinIoc { get; }
|
public ISereinIoc SereinIoc { get; }
|
||||||
public IFlowEnvironment FlowEnvironment { get; }
|
public IFlowEnvironment FlowEnvironment { get; }
|
||||||
|
|||||||
@@ -5,24 +5,6 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Serein.Library.Framework.NodeFlow
|
namespace Serein.Library.Framework.NodeFlow
|
||||||
{
|
{
|
||||||
//public enum FfState
|
|
||||||
//{
|
|
||||||
// Succeed,
|
|
||||||
// Cancel,
|
|
||||||
// Error,
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public class FlipflopContext
|
|
||||||
//{
|
|
||||||
// public FlowStateType State { get; set; }
|
|
||||||
// public object? Data { get; set; }
|
|
||||||
// public FlipflopContext(FlowStateType ffState, object? data = null)
|
|
||||||
// {
|
|
||||||
// State = ffState;
|
|
||||||
// Data = data;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public static class FlipflopFunc
|
public static class FlipflopFunc
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -75,20 +57,19 @@ namespace Serein.Library.Framework.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class FlipflopContext : IFlipflopContext
|
public class FlipflopContext : IFlipflopContext
|
||||||
{
|
{
|
||||||
public FlowStateType State { get; set; }
|
public FlipflopStateType State { get; set; }
|
||||||
//public TResult? Data { get; set; }
|
//public TResult? Data { get; set; }
|
||||||
public object Data { get; set; }
|
public object Data { get; set; }
|
||||||
public FlipflopContext(FlowStateType ffState)
|
public FlipflopContext(FlipflopStateType ffState)
|
||||||
{
|
{
|
||||||
State = ffState;
|
State = ffState;
|
||||||
}
|
}
|
||||||
public FlipflopContext(FlowStateType ffState, object data)
|
public FlipflopContext(FlipflopStateType ffState, object data)
|
||||||
{
|
{
|
||||||
State = ffState;
|
State = ffState;
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Library\Serein.Library.csproj">
|
<ProjectReference Include="..\Library\Serein.Library.csproj">
|
||||||
<Project>{5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3}</Project>
|
<Project>{55C77D23-2FD3-43D1-918C-DC3DE9614F0F}</Project>
|
||||||
<Name>Serein.Library</Name>
|
<Name>Serein.Library</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Serein.Library.Api
|
|||||||
{
|
{
|
||||||
public interface IFlipflopContext
|
public interface IFlipflopContext
|
||||||
{
|
{
|
||||||
FlowStateType State { get; set; }
|
FlipflopStateType State { get; set; }
|
||||||
object Data { get; set; }
|
object Data { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ namespace Serein.Library.Enums
|
|||||||
{
|
{
|
||||||
public enum ConnectionType
|
public enum ConnectionType
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 不执行分支
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 真分支
|
/// 真分支
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -7,12 +7,8 @@ using System.Threading.Tasks;
|
|||||||
namespace Serein.Library.Enums
|
namespace Serein.Library.Enums
|
||||||
{
|
{
|
||||||
|
|
||||||
public enum FlowStateType
|
public enum FlipflopStateType
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 待执行
|
|
||||||
/// </summary>
|
|
||||||
None,
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 成功(方法成功执行)
|
/// 成功(方法成功执行)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,5 +21,11 @@ namespace Serein.Library.Enums
|
|||||||
/// 异常(节点没有成功执行,执行时发生非预期的错误)
|
/// 异常(节点没有成功执行,执行时发生非预期的错误)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Error,
|
Error,
|
||||||
|
/// <summary>
|
||||||
|
/// 取消
|
||||||
|
/// </summary>
|
||||||
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
16
Library/Ex/FlipflopException.cs
Normal file
16
Library/Ex/FlipflopException.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Serein.Library.Ex
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器
|
||||||
|
/// </summary>
|
||||||
|
public class FlipflopException: Exception
|
||||||
|
{
|
||||||
|
public bool IsCancel { get; }
|
||||||
|
public FlipflopException(string message, bool isCancel = true) :base(message)
|
||||||
|
{
|
||||||
|
IsCancel = isCancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ namespace Serein.Library.Attributes
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 标记一个方法是什么类型,加载dll后用来拖拽到画布中
|
/// 建议触发器手动设置返回类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
public class NodeActionAttribute : Attribute
|
public class NodeActionAttribute : Attribute
|
||||||
@@ -45,9 +45,6 @@ namespace Serein.Library.Attributes
|
|||||||
public bool Scan;
|
public bool Scan;
|
||||||
public string MethodTips;
|
public string MethodTips;
|
||||||
public NodeType MethodDynamicType;
|
public NodeType MethodDynamicType;
|
||||||
/// <summary>
|
|
||||||
/// 推荐触发器手动设置返回类型
|
|
||||||
/// </summary>
|
|
||||||
public Type ReturnType;
|
public Type ReturnType;
|
||||||
public string LockName;
|
public string LockName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using Serein.Library.Ex;
|
||||||
using System.Threading.Tasks;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Serein.Library.Core.NodeFlow.Tool
|
namespace Serein.Library.Core.NodeFlow.Tool
|
||||||
{
|
{
|
||||||
@@ -13,9 +14,8 @@ namespace Serein.Library.Core.NodeFlow.Tool
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public class TcsSignal<TSignal> where TSignal : struct, Enum
|
public class TcsSignalFlipflop<TSignal> where TSignal : struct, Enum
|
||||||
{
|
{
|
||||||
//public ConcurrentDictionary<TSignal, Queue<TaskCompletionSource<object>>> TcsEvent { get; } = new();
|
|
||||||
public ConcurrentDictionary<TSignal, TaskCompletionSource<object>> TcsEvent { get; } = new ConcurrentDictionary<TSignal, TaskCompletionSource<object>>();
|
public ConcurrentDictionary<TSignal, TaskCompletionSource<object>> TcsEvent { get; } = new ConcurrentDictionary<TSignal, TaskCompletionSource<object>>();
|
||||||
|
|
||||||
public ConcurrentDictionary<TSignal, object> TcsLock { get; } = new ConcurrentDictionary<TSignal, object>();
|
public ConcurrentDictionary<TSignal, object> TcsLock { get; } = new ConcurrentDictionary<TSignal, object>();
|
||||||
@@ -56,7 +56,7 @@ namespace Serein.Library.Core.NodeFlow.Tool
|
|||||||
{
|
{
|
||||||
foreach (var tcs in TcsEvent.Values)
|
foreach (var tcs in TcsEvent.Values)
|
||||||
{
|
{
|
||||||
tcs.SetException(new Exception("任务取消"));
|
tcs.SetException(new FlipflopException("任务取消"));
|
||||||
}
|
}
|
||||||
TcsEvent.Clear();
|
TcsEvent.Clear();
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
using Newtonsoft.Json;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Api;
|
|
||||||
using Serein.Library.Entity;
|
using Serein.Library.Entity;
|
||||||
using Serein.Library.Enums;
|
using Serein.Library.Enums;
|
||||||
using Serein.NodeFlow.Model;
|
|
||||||
using Serein.NodeFlow.Tool.SerinExpression;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Serein.NodeFlow.Base
|
namespace Serein.NodeFlow.Base
|
||||||
{
|
{
|
||||||
@@ -65,12 +61,14 @@ namespace Serein.NodeFlow.Base
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 不同分支的子节点
|
/// 不同分支的子节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<ConnectionType,List<NodeModelBase>> SuccessorNodes { get; }
|
public Dictionary<ConnectionType,List<NodeModelBase>> SuccessorNodes { get; }
|
||||||
|
|
||||||
|
public ConnectionType NextOrientation { get; set; } = ConnectionType.None;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定)
|
/// 当前执行状态(进入真分支还是假分支,异常分支在异常中确定)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FlowStateType FlowState { get; set; } = FlowStateType.None;
|
// public FlowStateType FlowState { get; set; } = FlowStateType.Cancel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
|
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Entity;
|
using Serein.Library.Entity;
|
||||||
using Serein.Library.Enums;
|
using Serein.Library.Enums;
|
||||||
|
using Serein.Library.Ex;
|
||||||
using Serein.NodeFlow.Tool.SerinExpression;
|
using Serein.NodeFlow.Tool.SerinExpression;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -92,14 +93,13 @@ namespace Serein.NodeFlow.Base
|
|||||||
currentNode.FlowData = currentNode.Execute(context);
|
currentNode.FlowData = currentNode.Execute(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionType connection = currentNode.FlowState switch
|
if(currentNode.NextOrientation == ConnectionType.None)
|
||||||
{
|
{
|
||||||
FlowStateType.Succeed => ConnectionType.IsSucceed,
|
// 不再执行
|
||||||
FlowStateType.Fail => ConnectionType.IsFail,
|
break;
|
||||||
FlowStateType.Error => ConnectionType.IsError,
|
}
|
||||||
_ => throw new Exception("非预期的枚举值")
|
|
||||||
};
|
var nextNodes = currentNode.SuccessorNodes[currentNode.NextOrientation];
|
||||||
var nextNodes = currentNode.SuccessorNodes[connection];
|
|
||||||
|
|
||||||
// 将下一个节点集合中的所有节点逆序推入栈中
|
// 将下一个节点集合中的所有节点逆序推入栈中
|
||||||
for (int i = nextNodes.Count - 1; i >= 0; i--)
|
for (int i = nextNodes.Count - 1; i >= 0; i--)
|
||||||
@@ -148,12 +148,12 @@ namespace Serein.NodeFlow.Base
|
|||||||
result = func?.Invoke(md.ActingInstance, parameters);
|
result = func?.Invoke(md.ActingInstance, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FlowState = FlowStateType.Succeed;
|
NextOrientation = ConnectionType.IsSucceed;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
FlowState = FlowStateType.Error;
|
NextOrientation = ConnectionType.IsError;
|
||||||
RuningException = ex;
|
RuningException = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,23 +184,16 @@ namespace Serein.NodeFlow.Base
|
|||||||
object?[]? parameters = GetParameters(context, MethodDetails);
|
object?[]? parameters = GetParameters(context, MethodDetails);
|
||||||
flipflopContext = await ((Func<object, object[], Task<IFlipflopContext>>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance, parameters);
|
flipflopContext = await ((Func<object, object[], Task<IFlipflopContext>>)md.MethodDelegate).Invoke(MethodDetails.ActingInstance, parameters);
|
||||||
}
|
}
|
||||||
|
if (flipflopContext == null)
|
||||||
if (flipflopContext != null)
|
|
||||||
{
|
{
|
||||||
FlowState = flipflopContext.State;
|
throw new FlipflopException("没有返回上下文");
|
||||||
if (flipflopContext.State == FlowStateType.Succeed)
|
|
||||||
{
|
|
||||||
result = flipflopContext.Data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
NextOrientation = flipflopContext.State.ToContentType();
|
||||||
|
result = flipflopContext.Data;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
FlowState = FlowStateType.Error;
|
NextOrientation = ConnectionType.IsError;
|
||||||
RuningException = ex;
|
RuningException = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Serein.NodeFlow.Base;
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.NodeFlow.Tool;
|
using Serein.NodeFlow.Tool;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@@ -618,6 +619,18 @@ namespace Serein.NodeFlow
|
|||||||
Path = assembly.Location,
|
Path = assembly.Location,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ConnectionType ToContentType(this FlipflopStateType flowStateType)
|
||||||
|
{
|
||||||
|
return flowStateType switch
|
||||||
|
{
|
||||||
|
FlipflopStateType.Succeed => ConnectionType.IsSucceed,
|
||||||
|
FlipflopStateType.Fail => ConnectionType.IsFail,
|
||||||
|
FlipflopStateType.Error => ConnectionType.IsError,
|
||||||
|
FlipflopStateType.Cancel => ConnectionType.None,
|
||||||
|
_ => throw new NotImplementedException("未定义的流程状态")
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -159,11 +159,14 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
||||||
|
|
||||||
if (flipflopContext.State == FlowStateType.Succeed)
|
ConnectionType connection = flipflopContext.State.ToContentType();
|
||||||
|
|
||||||
|
if (connection != ConnectionType.None)
|
||||||
{
|
{
|
||||||
singleFlipFlopNode.FlowState = FlowStateType.Succeed;
|
singleFlipFlopNode.NextOrientation = connection;
|
||||||
singleFlipFlopNode.FlowData = flipflopContext.Data;
|
singleFlipFlopNode.FlowData = flipflopContext.Data;
|
||||||
var tasks = singleFlipFlopNode.SuccessorNodes[ConnectionType.IsSucceed].Select(nextNode =>
|
|
||||||
|
var tasks = singleFlipFlopNode.SuccessorNodes[connection].Select(nextNode =>
|
||||||
{
|
{
|
||||||
var context = new DynamicContext(SereinIoc,flowEnvironment);
|
var context = new DynamicContext(SereinIoc,flowEnvironment);
|
||||||
nextNode.PreviousNode = singleFlipFlopNode;
|
nextNode.PreviousNode = singleFlipFlopNode;
|
||||||
|
|||||||
@@ -26,50 +26,38 @@ namespace Serein.NodeFlow.Model
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public override object? Execute(IDynamicContext context)
|
public override object? Execute(IDynamicContext context)
|
||||||
{
|
{
|
||||||
// bool allTrue = ConditionNodes.All(condition => Judge(context,condition.MethodDetails));
|
// NextOrientation = ConnectionType.IsSucceed;
|
||||||
// bool IsAllTrue = true; // 初始化为 true
|
|
||||||
FlowState = FlowStateType.Succeed;
|
// 条件区域中遍历每个条件节点
|
||||||
foreach (SingleConditionNode? node in ConditionNodes)
|
foreach (SingleConditionNode? node in ConditionNodes)
|
||||||
{
|
{
|
||||||
var state = Judge(context, node);
|
var state = Judge(context, node);
|
||||||
if (state == FlowStateType.Fail || FlowStateType.Fail == FlowStateType.Error)
|
NextOrientation = state; // 每次判读完成后,设置区域后继方向为判断结果
|
||||||
|
if (state != ConnectionType.IsSucceed)
|
||||||
{
|
{
|
||||||
FlowState = state;
|
// 如果条件不通过,立刻推出循环
|
||||||
break;// 一旦发现条件为假,立即退出循环
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PreviousNode?.FlowData;
|
return PreviousNode?.FlowData;
|
||||||
//if (IsAllTrue)
|
|
||||||
//{
|
|
||||||
// foreach (var nextNode in TrueBranchNextNodes)
|
|
||||||
// {
|
|
||||||
// nextNode.ExecuteStack(context);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// foreach (var nextNode in FalseBranchNextNodes)
|
|
||||||
// {
|
|
||||||
// nextNode.ExecuteStack(context);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ConnectionType Judge(IDynamicContext context, SingleConditionNode node)
|
||||||
|
|
||||||
private FlowStateType Judge(IDynamicContext context, SingleConditionNode node)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
node.Execute(context);
|
node.Execute(context);
|
||||||
return node.FlowState;
|
return node.NextOrientation;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.Message);
|
Console.WriteLine(ex.Message);
|
||||||
return FlowStateType.Error;
|
NextOrientation = ConnectionType.IsError;
|
||||||
|
RuningException = ex;
|
||||||
|
return ConnectionType.IsError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,15 +43,15 @@ namespace Serein.NodeFlow.Model
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var isPass = SerinConditionParser.To(result, Expression);
|
var isPass = SerinConditionParser.To(result, Expression);
|
||||||
FlowState = isPass ? FlowStateType.Succeed : FlowStateType.Fail;
|
NextOrientation = isPass ? ConnectionType.IsSucceed : ConnectionType.IsFail;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
FlowState = FlowStateType.Error;
|
NextOrientation = ConnectionType.IsError;
|
||||||
RuningException = ex;
|
RuningException = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"{result} {Expression} -> " + FlowState);
|
Console.WriteLine($"{result} {Expression} -> " + NextOrientation);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Serein.Library.Entity;
|
|||||||
using Serein.Library.Enums;
|
using Serein.Library.Enums;
|
||||||
using Serein.NodeFlow.Base;
|
using Serein.NodeFlow.Base;
|
||||||
using Serein.NodeFlow.Tool.SerinExpression;
|
using Serein.NodeFlow.Tool.SerinExpression;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Serein.NodeFlow.Model
|
namespace Serein.NodeFlow.Model
|
||||||
{
|
{
|
||||||
@@ -21,16 +22,27 @@ namespace Serein.NodeFlow.Model
|
|||||||
{
|
{
|
||||||
var data = PreviousNode?.FlowData;
|
var data = PreviousNode?.FlowData;
|
||||||
|
|
||||||
var newData = SerinExpressionEvaluator.Evaluate(Expression, data, out bool isChange);
|
try
|
||||||
|
{
|
||||||
|
var newData = SerinExpressionEvaluator.Evaluate(Expression, data, out bool isChange);
|
||||||
|
Console.WriteLine(newData);
|
||||||
|
object? result = null;
|
||||||
|
if (isChange)
|
||||||
|
{
|
||||||
|
result = newData;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = PreviousNode?.FlowData;
|
||||||
|
}
|
||||||
|
|
||||||
FlowState = FlowStateType.Succeed;
|
NextOrientation = ConnectionType.IsSucceed;
|
||||||
Console.WriteLine(newData);
|
return result;
|
||||||
if (isChange)
|
|
||||||
{
|
|
||||||
return newData;
|
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
NextOrientation = ConnectionType.IsError;
|
||||||
|
RuningException = ex;
|
||||||
return PreviousNode?.FlowData;
|
return PreviousNode?.FlowData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Entity;
|
using Serein.Library.Entity;
|
||||||
|
using Serein.Library.Ex;
|
||||||
using Serein.NodeFlow.Base;
|
using Serein.NodeFlow.Base;
|
||||||
|
|
||||||
namespace Serein.NodeFlow.Model
|
namespace Serein.NodeFlow.Model
|
||||||
@@ -7,9 +8,11 @@ namespace Serein.NodeFlow.Model
|
|||||||
|
|
||||||
public class SingleFlipflopNode : NodeModelBase
|
public class SingleFlipflopNode : NodeModelBase
|
||||||
{
|
{
|
||||||
public override object Execute(IDynamicContext context)
|
public override object? Execute(IDynamicContext context)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("无法以非await/async的形式调用触发器");
|
NextOrientation = Library.Enums.ConnectionType.IsError;
|
||||||
|
RuningException = new FlipflopException ("无法以非await/async的形式调用触发器");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Parameterdata[] GetParameterdatas()
|
public override Parameterdata[] GetParameterdatas()
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ public static class MethodDetailsHelperTmp
|
|||||||
|
|
||||||
var methodName = method.Name;
|
var methodName = method.Name;
|
||||||
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
|
var attribute = method.GetCustomAttribute<NodeActionAttribute>();
|
||||||
|
if(attribute is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
|
var explicitDataOfParameters = GetExplicitDataOfParameters(method.GetParameters());
|
||||||
// 生成委托
|
// 生成委托
|
||||||
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
|
var methodDelegate = GenerateMethodDelegate(type, // 方法所在的对象类型
|
||||||
@@ -74,6 +78,16 @@ public static class MethodDetailsHelperTmp
|
|||||||
method.GetParameters(),// 方法参数
|
method.GetParameters(),// 方法参数
|
||||||
method.ReturnType);// 返回值
|
method.ReturnType);// 返回值
|
||||||
|
|
||||||
|
Type returnType;
|
||||||
|
if (attribute?.MethodDynamicType == Library.Enums.NodeType.Flipflop)
|
||||||
|
{
|
||||||
|
// 触发器节点
|
||||||
|
returnType = attribute.ReturnType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
returnType = method.ReturnType;
|
||||||
|
}
|
||||||
|
|
||||||
var dllTypeName = $"{assemblyName}.{type.Name}";
|
var dllTypeName = $"{assemblyName}.{type.Name}";
|
||||||
// object instance = Activator.CreateInstance(type);
|
// object instance = Activator.CreateInstance(type);
|
||||||
@@ -89,7 +103,7 @@ public static class MethodDetailsHelperTmp
|
|||||||
MethodLockName = attribute.LockName,
|
MethodLockName = attribute.LockName,
|
||||||
MethodTips = attribute.MethodTips,
|
MethodTips = attribute.MethodTips,
|
||||||
ExplicitDatas = explicitDataOfParameters,
|
ExplicitDatas = explicitDataOfParameters,
|
||||||
ReturnType = method.ReturnType,
|
ReturnType = returnType,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
不定期在Bilibili个人空间上更新相关的视频。
|
不定期在Bilibili个人空间上更新相关的视频。
|
||||||
https://space.bilibili.com/33526379
|
https://space.bilibili.com/33526379
|
||||||
|
|
||||||
# 当前任务 2024年9月12日22:32:10
|
# 当前任务 2024年9月15日22:04:40
|
||||||
1. 将运行环境从UI(WPF)中独立出来,方便控制台程序直接运行项目文件。
|
* 计划新增基础节点“属性包装器”,用来收集各个节点的数据,包装成匿名对象/Json类型
|
||||||
2. 包装数据类型, 优化传递效率(尽可能避免拆箱、装箱)
|
* 计划编写网络方面的通讯,方便传出、传入数据
|
||||||
3. 优化触发器节点(显示传出类型)
|
* 包装数据类型, 优化传递效率(尽可能避免拆箱、装箱)
|
||||||
|
|
||||||
|
|
||||||
# 如何加载我的DLL?
|
# 如何加载我的DLL?
|
||||||
使用 **DynamicFlow** 特性标记你的类,可以参照 **MyDll** 与 **SereinWAT** 的实现。编译为 Dll文件 后,拖入到软件中即可。
|
使用 **DynamicFlow** 特性标记你的类,可以参照 **MyDll** 与 **SereinWAT** 的实现。编译为 Dll文件 后,拖入到软件中即可。
|
||||||
|
|||||||
@@ -28,6 +28,18 @@
|
|||||||
</Border>
|
</Border>
|
||||||
<!--<themes:ExplicitDataControl Grid.Row="1" ExplicitDatas="{Binding ExplicitDatas}" />-->
|
<!--<themes:ExplicitDataControl Grid.Row="1" ExplicitDatas="{Binding ExplicitDatas}" />-->
|
||||||
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />
|
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />
|
||||||
|
<Grid Grid.Row="2" >
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="50"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border Grid.Column="0" Background="#EAFFD0" BorderBrush="#EAFFD0" BorderThickness="1">
|
||||||
|
<TextBlock Text="result" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
<Border Grid.Column="1" Background="#EAFFD0" BorderBrush="#EAFFD0" BorderThickness="1">
|
||||||
|
<TextBlock Text="{Binding MethodDetails.ReturnType}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
<!--<themes:ConditionControl Grid.Row="2" ></themes:ConditionControl>-->
|
<!--<themes:ConditionControl Grid.Row="2" ></themes:ConditionControl>-->
|
||||||
</Grid>
|
</Grid>
|
||||||
</local:NodeControlBase>
|
</local:NodeControlBase>
|
||||||
|
|||||||
Reference in New Issue
Block a user