mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 15:50:47 +08:00
1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。
2. 补充了部分注释。 3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
This commit is contained in:
@@ -14,7 +14,7 @@ namespace Serein.FlowStartTool
|
||||
{
|
||||
public readonly IFlowEnvironment flowEnvironment = new FlowEnvironment();
|
||||
public bool IsRuning;
|
||||
public async Task StartFlow(SereinProjectData flowProjectData, string fileDataPath)
|
||||
public void StartFlow(SereinProjectData flowProjectData, string fileDataPath)
|
||||
{
|
||||
IsRuning = true;
|
||||
SynchronizationContext? uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
public interface IEnumConvertor<TEnum, TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// 将枚举值转换为指定类型的值
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
TValue Convertor(TEnum e);
|
||||
}
|
||||
|
||||
|
||||
@@ -252,11 +252,20 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public string Result { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上传当前节点的执行状态和结果信息。
|
||||
/// </summary>
|
||||
/// <param name="runState"></param>
|
||||
public void UploadState(RunState runState)
|
||||
{
|
||||
State = runState;
|
||||
TS = DateTime.Now - StateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传当前节点的执行结果值。
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void UploadResultValue(object value = null)
|
||||
{
|
||||
if(value is null)
|
||||
@@ -269,6 +278,11 @@ namespace Serein.Library.Api
|
||||
Result = $"{type.FullName}::{value}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上传当前节点的执行参数信息。
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
public void UploadParameters(object[] values = null)
|
||||
{
|
||||
if (values is null)
|
||||
@@ -282,6 +296,10 @@ namespace Serein.Library.Api
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回当前节点的执行信息字符串,包含状态、耗时和结果。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{State}]{TS.TotalSeconds:0.000}ms : {Result}";
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Api
|
||||
{
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// 流程运行接口
|
||||
/// </summary>
|
||||
@@ -24,7 +25,7 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
/// <param name="ioc"></param>
|
||||
/// <param name="setDefultMemberOnReset">用于每次启动时,重置IOC后默认注册某些类型</param>
|
||||
void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC> setDefultMemberOnReset = null);
|
||||
void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC>? setDefultMemberOnReset = null);
|
||||
|
||||
/// <summary>
|
||||
/// 开始运行流程
|
||||
|
||||
@@ -153,6 +153,9 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class ProjectLoadedEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目加载完成事件参数
|
||||
/// </summary>
|
||||
public ProjectLoadedEventArgs()
|
||||
{
|
||||
}
|
||||
@@ -163,6 +166,10 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class ProjectSavingEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目保存事件参数
|
||||
/// </summary>
|
||||
/// <param name="projectData"></param>
|
||||
public ProjectSavingEventArgs(SereinProjectData projectData)
|
||||
{
|
||||
ProjectData = projectData;
|
||||
@@ -179,6 +186,10 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class LoadDllEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载了DLL外部依赖事件参数
|
||||
/// </summary>
|
||||
/// <param name="nodeLibraryInfo"></param>
|
||||
public LoadDllEventArgs(FlowLibraryInfo nodeLibraryInfo)
|
||||
{
|
||||
this.NodeLibraryInfo = nodeLibraryInfo;
|
||||
@@ -194,6 +205,9 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class RemoteDllEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 移除了DLL外部依赖事件参数
|
||||
/// </summary>
|
||||
public RemoteDllEventArgs()
|
||||
{
|
||||
}
|
||||
@@ -270,6 +284,9 @@ namespace Serein.Library.Api
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接关系所在的画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -309,11 +326,18 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class CanvasCreateEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 画布添加事件参数
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
public CanvasCreateEventArgs(FlowCanvasDetails model)
|
||||
{
|
||||
Model = model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画布
|
||||
/// </summary>
|
||||
public FlowCanvasDetails Model { get; }
|
||||
}
|
||||
|
||||
@@ -322,11 +346,18 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class CanvasRemoveEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 画布移除事件参数
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
public CanvasRemoveEventArgs(string canvasGuid)
|
||||
{
|
||||
CanvasGuid = canvasGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所处画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
}
|
||||
|
||||
@@ -360,10 +391,6 @@ namespace Serein.Library.Api
|
||||
/// 在UI上的位置
|
||||
/// </summary>
|
||||
public PositionOfUI Position { get; private set; }
|
||||
/// <summary>
|
||||
/// 容器
|
||||
/// </summary>
|
||||
//public string RegeionGuid { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -371,12 +398,20 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class NodeRemoveEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 被移除节点事件参数
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public NodeRemoveEventArgs(string canvasGuid, string nodeGuid)
|
||||
{
|
||||
CanvasGuid = canvasGuid;
|
||||
this.NodeGuid = nodeGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 被移除节点所在的画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -390,6 +425,12 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class NodePlaceEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点放置事件参数
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="containerNodeGuid"></param>
|
||||
public NodePlaceEventArgs(string canvasGuid, string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
CanvasGuid = canvasGuid;
|
||||
@@ -397,6 +438,9 @@ namespace Serein.Library.Api
|
||||
ContainerNodeGuid = containerNodeGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -414,6 +458,12 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class NodeTakeOutEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点取出事件参数
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <param name="containerNodeGuid"></param>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public NodeTakeOutEventArgs(string canvasGuid, string containerNodeGuid, string nodeGuid)
|
||||
{
|
||||
CanvasGuid = canvasGuid;
|
||||
@@ -421,6 +471,9 @@ namespace Serein.Library.Api
|
||||
ContainerNodeGuid = containerNodeGuid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所在画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -438,9 +491,17 @@ namespace Serein.Library.Api
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点发生了变化
|
||||
/// </summary>
|
||||
public class StartNodeChangeEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 起始节点发生了变化事件参数
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <param name="oldNodeGuid"></param>
|
||||
/// <param name="newNodeGuid"></param>
|
||||
public StartNodeChangeEventArgs(string canvasGuid, string oldNodeGuid, string newNodeGuid)
|
||||
{
|
||||
CanvasGuid = canvasGuid;
|
||||
@@ -448,6 +509,9 @@ namespace Serein.Library.Api
|
||||
this.NewNodeGuid = newNodeGuid; ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 所在画布Guid
|
||||
/// </summary>
|
||||
public string CanvasGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -515,6 +579,11 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class NodeInterruptStateChangeEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点中断状态改变事件参数
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="isInterrupt"></param>
|
||||
public NodeInterruptStateChangeEventArgs(string nodeGuid,bool isInterrupt)
|
||||
{
|
||||
NodeGuid = nodeGuid;
|
||||
@@ -526,14 +595,19 @@ namespace Serein.Library.Api
|
||||
/// 中断的节点Guid
|
||||
/// </summary>
|
||||
public string NodeGuid { get;}
|
||||
/// <summary>
|
||||
/// 是否中断
|
||||
/// </summary>
|
||||
public bool IsInterrupt { get;}
|
||||
// public InterruptClass Class { get;}
|
||||
}
|
||||
/// <summary>
|
||||
/// 节点触发了中断事件参数
|
||||
/// </summary>
|
||||
public class InterruptTriggerEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 中断触发类型
|
||||
/// </summary>
|
||||
public enum InterruptTriggerType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -550,6 +624,12 @@ namespace Serein.Library.Api
|
||||
Obj,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 中断触发事件参数
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="expression"></param>
|
||||
/// <param name="type"></param>
|
||||
public InterruptTriggerEventArgs(string nodeGuid, string expression, InterruptTriggerType type)
|
||||
{
|
||||
this.NodeGuid = nodeGuid;
|
||||
@@ -561,7 +641,13 @@ namespace Serein.Library.Api
|
||||
/// 中断的节点Guid
|
||||
/// </summary>
|
||||
public string NodeGuid { get;}
|
||||
/// <summary>
|
||||
/// 被触发的表达式
|
||||
/// </summary>
|
||||
public string Expression { get;}
|
||||
/// <summary>
|
||||
/// 中断触发类型
|
||||
/// </summary>
|
||||
public InterruptTriggerType Type { get;}
|
||||
}
|
||||
|
||||
@@ -572,6 +658,9 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class IOCMembersChangedEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// IOC成员发生改变的事件类型
|
||||
/// </summary>
|
||||
public enum EventType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -583,12 +672,23 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
Completeuild,
|
||||
}
|
||||
/// <summary>
|
||||
/// IOC成员发生改变事件参数
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="instance"></param>
|
||||
public IOCMembersChangedEventArgs(string key, object instance)
|
||||
{
|
||||
this.Key = key;
|
||||
this.Instance = instance;
|
||||
}
|
||||
/// <summary>
|
||||
/// IOC成员发生改变事件参数
|
||||
/// </summary>
|
||||
public string Key { get; private set; }
|
||||
/// <summary>
|
||||
/// IOC成员发生改变事件参数
|
||||
/// </summary>
|
||||
public object Instance { get; private set; }
|
||||
}
|
||||
|
||||
@@ -597,38 +697,20 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public class NodeLocatedEventArgs : FlowEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点需要定位事件参数
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public NodeLocatedEventArgs(string nodeGuid)
|
||||
{
|
||||
NodeGuid = nodeGuid;
|
||||
}
|
||||
/// <summary>
|
||||
/// 节点需要定位事件参数
|
||||
/// </summary>
|
||||
public string NodeGuid { get; private set; }
|
||||
}
|
||||
|
||||
/* /// <summary>
|
||||
/// 节点移动了
|
||||
/// </summary>
|
||||
public class NodeMovedEventArgs : FlowEventArgs
|
||||
{
|
||||
public NodeMovedEventArgs(string nodeGuid, double x, double y)
|
||||
{
|
||||
this.NodeGuid = nodeGuid;
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
/// <summary>
|
||||
/// 节点唯一标识
|
||||
/// </summary>
|
||||
public string NodeGuid { get; private set; }
|
||||
/// <summary>
|
||||
/// 画布上的x坐标
|
||||
/// </summary>
|
||||
public double X { get; private set; }
|
||||
/// <summary>
|
||||
/// 画布上的y坐标
|
||||
/// </summary>
|
||||
public double Y { get; private set; }
|
||||
}*/
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -729,23 +811,113 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
event EnvOutHandler EnvOutput;
|
||||
|
||||
/// <summary>
|
||||
/// 加载了DLL外部依赖事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnDllLoad(LoadDllEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 项目加载完成事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnProjectLoaded(ProjectLoadedEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 项目准备保存事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnProjectSaving(ProjectSavingEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点连接关系发生改变事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeConnectChanged(NodeConnectChangeEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 画布创建事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnCanvasCreated(CanvasCreateEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 画布移除事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnCanvasRemoved(CanvasRemoveEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点创建事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeCreated(NodeCreateEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点移除事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeRemoved(NodeRemoveEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点放置事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodePlace(NodePlaceEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点取出事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeTakeOut(NodeTakeOutEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点发生了变化事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnStartNodeChanged(StartNodeChangeEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行完成事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnFlowRunComplete(FlowEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 被监视的对象发生了改变事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnMonitorObjectChanged(MonitorObjectEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点中断状态发生了改变事件(开启了中断/取消了中断)
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeInterruptStateChanged(NodeInterruptStateChangeEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 触发了中断事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnInterruptTriggered(InterruptTriggerEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// IOC容器成员发生了改变事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 节点需要定位事件
|
||||
/// </summary>
|
||||
/// <param name="eventArgs"></param>
|
||||
public void OnNodeLocated(NodeLocatedEventArgs eventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// 环境输出信息事件
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
public void OnEnvOutput(InfoType type, string value);
|
||||
}
|
||||
|
||||
@@ -864,7 +1036,7 @@ namespace Serein.Library.Api
|
||||
/// 获取当前项目信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<SereinProjectData> GetProjectInfoAsync();
|
||||
SereinProjectData GetProjectInfoAsync();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Serein.Library;
|
||||
|
||||
namespace Serein.Library.Api
|
||||
{
|
||||
@@ -72,11 +67,11 @@ namespace Serein.Library.Api
|
||||
MethodDetails MethodDetails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父节点集合
|
||||
/// 前继节点集合
|
||||
/// </summary>
|
||||
Dictionary<ConnectionInvokeType, List<IFlowNode>> PreviousNodes { get;}
|
||||
/// <summary>
|
||||
/// 子节点集合
|
||||
/// 后继节点集合
|
||||
/// </summary>
|
||||
Dictionary<ConnectionInvokeType, List<IFlowNode>> SuccessorNodes { get; set; }
|
||||
|
||||
|
||||
@@ -118,14 +118,14 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
IJsonToken CreateObject(IDictionary<string, object> values = null);
|
||||
IJsonToken CreateObject(IDictionary<string, object>? values = null);
|
||||
|
||||
/// <summary>
|
||||
/// 创建数组
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
IJsonToken CreateArray(IEnumerable<object> values = null);
|
||||
IJsonToken CreateArray(IEnumerable<object>? values = null);
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为JSON Token,自动转换为 JObject/JArray。
|
||||
|
||||
@@ -11,7 +11,9 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public interface INodeContainer
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 容器节点的Guid,与 IFlowNode.Guid 相同
|
||||
/// </summary>
|
||||
string Guid { get; }
|
||||
/// <summary>
|
||||
/// 放置一个节点
|
||||
|
||||
@@ -20,19 +20,6 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
IFlowNode NodeModel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 根据索引从入参数据获取数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
//object GetArgData(IDynamicContext context, int index);
|
||||
/// <summary>
|
||||
/// 获取流程当前传递的数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
/// FlowResult GetFlowData(IDynamicContext context);
|
||||
|
||||
/// <summary>
|
||||
/// 获取全局数据
|
||||
|
||||
@@ -108,8 +108,32 @@ namespace Serein.Library.Api
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
ISereinIOC Run<T>(Action<T> action);
|
||||
/// <summary>
|
||||
/// 从容器中获取数个类型的实例进行运行
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
ISereinIOC Run<T1, T2>(Action<T1, T2> action);
|
||||
/// <summary>
|
||||
/// 从容器中获取数个类型的实例进行运行
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <typeparam name="T3"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
ISereinIOC Run<T1, T2, T3>(Action<T1, T2, T3> action);
|
||||
/// <summary>
|
||||
/// 从容器中获取数个类型的实例进行运行
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <typeparam name="T3"></typeparam>
|
||||
/// <typeparam name="T4"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
ISereinIOC Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,17 @@ namespace Serein.Library
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class AutoRegisterAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动注册特性
|
||||
/// </summary>
|
||||
/// <param name="Class"></param>
|
||||
public AutoRegisterAttribute(RegisterSequence Class = RegisterSequence.FlowInit)
|
||||
{
|
||||
this.Class = Class;
|
||||
}
|
||||
/// <summary>
|
||||
/// 注册顺序
|
||||
/// </summary>
|
||||
public RegisterSequence Class ;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,20 @@ namespace Serein.Library
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class BindConvertorAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举类型
|
||||
/// </summary>
|
||||
public Type EnumType { get; }
|
||||
/// <summary>
|
||||
/// 转换器类型
|
||||
/// </summary>
|
||||
public Type ConvertorType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定转换器特性
|
||||
/// </summary>
|
||||
/// <param name="enum"></param>
|
||||
/// <param name="convertor"></param>
|
||||
public BindConvertorAttribute(Type @enum, Type convertor)
|
||||
{
|
||||
EnumType = @enum;
|
||||
|
||||
@@ -2,11 +2,21 @@
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// 绑定值特性
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class BindValueAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 绑定的值
|
||||
/// </summary>
|
||||
public object Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 绑定值特性构造函数
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public BindValueAttribute(object value)
|
||||
{
|
||||
Value = value;
|
||||
|
||||
@@ -10,6 +10,11 @@ namespace Serein.Library
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class DynamicFlowAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 动态流程特性构造函数
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="scan"></param>
|
||||
public DynamicFlowAttribute(string name = "",bool scan = true)
|
||||
{
|
||||
Name = name;
|
||||
|
||||
@@ -9,8 +9,16 @@ namespace Serein.Library
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class EnumTypeConvertorAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 枚举类型
|
||||
/// </summary>
|
||||
public Type EnumType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 枚举类型转换器特性构造函数
|
||||
/// </summary>
|
||||
/// <param name="enum"></param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public EnumTypeConvertorAttribute(Type @enum)
|
||||
{
|
||||
if (@enum.IsEnum)
|
||||
|
||||
@@ -9,6 +9,13 @@ namespace Serein.Library
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public sealed class NodeActionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点行为特性构造函数
|
||||
/// </summary>
|
||||
/// <param name="methodDynamicType"></param>
|
||||
/// <param name="methodTips"></param>
|
||||
/// <param name="scan"></param>
|
||||
/// <param name="lockName"></param>
|
||||
public NodeActionAttribute(NodeType methodDynamicType,
|
||||
string methodTips = "",
|
||||
bool scan = true,
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Serein.Library
|
||||
|
||||
/// <summary>
|
||||
/// 表示了两个节点之间的连接关系,同时表示节点运行完成后,所会执行的下一个节点类型。
|
||||
/// </summary
|
||||
/// </summary>
|
||||
public enum ConnectionInvokeType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -6,9 +6,18 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数值输入类型
|
||||
/// </summary>
|
||||
public enum ParameterValueInputType
|
||||
{
|
||||
/// <summary>
|
||||
/// 参数值输入类型 - 输入
|
||||
/// </summary>
|
||||
Input,
|
||||
/// <summary>
|
||||
/// 参数值输入类型 - 选择器(枚举类型)
|
||||
/// </summary>
|
||||
Select,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class FlipflopException: Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发器取消类型
|
||||
/// </summary>
|
||||
public enum CancelClass
|
||||
{
|
||||
/// <summary>
|
||||
@@ -27,6 +30,13 @@ namespace Serein.Library
|
||||
/// 取消类型
|
||||
/// </summary>
|
||||
public CancelClass Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发器异常构造函数
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="isCancel"></param>
|
||||
/// <param name="clsss"></param>
|
||||
public FlipflopException(string message, bool isCancel = true,CancelClass clsss = CancelClass.CancelBranch) :base(message)
|
||||
{
|
||||
IsCancel = isCancel;
|
||||
|
||||
@@ -12,9 +12,22 @@ namespace Serein.Library
|
||||
public static class FlowBaseLibrary
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 对象透传,直接返回入参的值
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[NodeAction(NodeType.Action, "对象透传")]
|
||||
public static object TransmissionObject(object value) => value;
|
||||
|
||||
/// <summary>
|
||||
/// 键值对组装,将入参的值与名称组装成一个字典对象
|
||||
/// </summary>
|
||||
/// <param name="argNames"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
|
||||
[NodeAction(NodeType.Action, "键值对组装")]
|
||||
public static Dictionary<string, object> DictSet(string argNames, params object[] value)
|
||||
{
|
||||
@@ -32,12 +45,22 @@ namespace Serein.Library
|
||||
return dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数组组装,将入参的值组装成一个数组对象
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[NodeAction(NodeType.Action, "数组组装")]
|
||||
public static object[] ArraySet(params object[] value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出到控制台,使用SereinEnv.WriteLine方法输出信息
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[NodeAction(NodeType.Action, "输出")]
|
||||
public static object[] Console(params object[] value)
|
||||
{
|
||||
@@ -48,7 +71,14 @@ namespace Serein.Library
|
||||
return value;
|
||||
}
|
||||
|
||||
[NodeAction(NodeType.Action, "逻辑分支")]
|
||||
/// <summary>
|
||||
/// 逻辑分支,根据布尔值选择返回的值,如果布尔值为true则返回t_value,否则返回f_value
|
||||
/// </summary>
|
||||
/// <param name="bool"></param>
|
||||
/// <param name="t_value"></param>
|
||||
/// <param name="f_value"></param>
|
||||
/// <returns></returns>
|
||||
[NodeAction(NodeType.Action, "逻辑选择")]
|
||||
public static object LogicalBranch([NodeParam(IsExplicit = false)]bool @bool,
|
||||
object t_value,
|
||||
object f_value)
|
||||
@@ -56,6 +86,12 @@ namespace Serein.Library
|
||||
return @bool ? t_value : f_value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文本拼接,将多个文本值拼接成一个字符串,支持换行符和制表符的特殊处理
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[NodeAction(NodeType.Action, "文本拼接")]
|
||||
public static string TextJoin(params object[] value)
|
||||
{
|
||||
@@ -79,6 +115,13 @@ namespace Serein.Library
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动态构建对象,将字典中的键值对转换为一个动态对象,支持指定类名和打印结果
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
/// <param name="classTypeName"></param>
|
||||
/// <param name="IsPrint"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
[NodeAction(NodeType.Action, "键值对动态构建对象")]
|
||||
public static object CreateDynamicObjectOfDict(Dictionary<string, object> dict,
|
||||
@@ -100,13 +143,5 @@ namespace Serein.Library
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
[NodeAction(NodeType.Action, "设置或更新全局数据")]
|
||||
public static object AddOrUpdateFlowGlobalData(string name, object data)
|
||||
{
|
||||
SereinEnv.AddOrUpdateFlowGlobalData(name, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,9 +57,18 @@ namespace Serein.Library
|
||||
CollectionSetter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示方法的类型
|
||||
/// </summary>
|
||||
public enum GSType
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取值
|
||||
/// </summary>
|
||||
Get,
|
||||
/// <summary>
|
||||
/// 设置值
|
||||
/// </summary>
|
||||
Set,
|
||||
}
|
||||
|
||||
@@ -149,7 +158,7 @@ namespace Serein.Library
|
||||
/// 目前提供了创建集合取值/赋值委托
|
||||
/// </summary>
|
||||
/// <param name="type">类型信息</param>
|
||||
/// <param name="gsType">操作类型</param>
|
||||
/// <param name="emitType">操作类型</param>
|
||||
public DelegateDetails(Type type, EmitType emitType)
|
||||
{
|
||||
if (emitType == EmitType.CollectionSetter)
|
||||
|
||||
@@ -5,6 +5,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// FlipflopFunc 类提供了与 Flipflop 相关的功能方法。
|
||||
/// </summary>
|
||||
public static class FlipflopFunc
|
||||
{
|
||||
/// <summary>
|
||||
@@ -72,15 +75,34 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class FlipflopContext<TResult> : IFlipflopContext<TResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发器完成的状态(根据业务场景手动设置)
|
||||
/// </summary>
|
||||
public FlipflopStateType State { get; set; }
|
||||
/// <summary>
|
||||
/// 触发类型
|
||||
/// </summary>
|
||||
|
||||
public TriggerDescription Type { get; set; }
|
||||
/// <summary>
|
||||
/// 触发时传递的数据
|
||||
/// </summary>
|
||||
public TResult Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发器上下文构造函数
|
||||
/// </summary>
|
||||
/// <param name="ffState"></param>
|
||||
public FlipflopContext(FlipflopStateType ffState)
|
||||
{
|
||||
State = ffState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发器上下文构造函数,传入状态和数据值
|
||||
/// </summary>
|
||||
/// <param name="ffState"></param>
|
||||
/// <param name="value"></param>
|
||||
public FlipflopContext(FlipflopStateType ffState, TResult value)
|
||||
{
|
||||
State = ffState;
|
||||
|
||||
@@ -16,81 +16,88 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 流程画布
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node)]
|
||||
public partial class FlowCanvasDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程画布的构造函数
|
||||
/// </summary>
|
||||
/// <param name="env"></param>
|
||||
public FlowCanvasDetails(IFlowEnvironment env)
|
||||
{
|
||||
Env = env;
|
||||
}
|
||||
/// <summary>
|
||||
/// 流程画布的运行环境
|
||||
/// </summary>
|
||||
|
||||
public IFlowEnvironment Env { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 画布拥有的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private List<IFlowNode> _nodes = [];
|
||||
//private System.Collections.ObjectModel.ObservableCollection<IFlowNode> _nodes = [];
|
||||
|
||||
/// <summary>
|
||||
/// 画布公开的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private List<IFlowNode> _publicNodes = [];
|
||||
|
||||
/// <summary>
|
||||
/// 标识画布ID
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = false)]
|
||||
[DataInfo(IsProtection = false)]
|
||||
private string _guid;
|
||||
|
||||
/// <summary>
|
||||
/// 画布名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// 画布宽度
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _width;
|
||||
|
||||
/// <summary>
|
||||
/// 画布高度
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _height;
|
||||
|
||||
/// <summary>
|
||||
/// 预览位置X
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _viewX;
|
||||
|
||||
/// <summary>
|
||||
/// 预览位置Y
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _viewY;
|
||||
|
||||
/// <summary>
|
||||
/// 缩放比例X
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _scaleX = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 缩放比例Y
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private double _scaleY = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 起始节点
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private IFlowNode _startNode;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace Serein.Library
|
||||
/// 动态流程上下文
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment">脚本运行时的IOC</param>
|
||||
/// <param name="ioc">脚本运行时使用的IOC容器</param>
|
||||
public FlowContext(IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
Env = flowEnvironment;
|
||||
@@ -110,6 +109,10 @@ namespace Serein.Library
|
||||
return flowInvokeInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前流程上下文的所有节点调用信息,包含每个节点的执行时间、调用类型、执行状态等。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<FlowInvokeInfo> GetAllInvokeInfos() => [.. flowInvokeInfos.Values];
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,17 +9,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示空数据
|
||||
/// </summary>
|
||||
/*public readonly struct Unit : IEquatable<Unit>
|
||||
{
|
||||
public static readonly Unit Default = default;
|
||||
public bool Equals(Unit _) => true;
|
||||
public override bool Equals(object obj) => obj is Unit;
|
||||
public override int GetHashCode() => 0;
|
||||
}*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程返回值的包装
|
||||
|
||||
@@ -33,6 +33,11 @@ namespace Serein.Library.FlowNode
|
||||
/// </summary>
|
||||
public class JunctionModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 连接点模型构造函数
|
||||
/// </summary>
|
||||
/// <param name="NodeModel"></param>
|
||||
/// <param name="JunctionType"></param>
|
||||
public JunctionModel(IFlowNode NodeModel, JunctionType JunctionType)
|
||||
{
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -8,76 +7,21 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library
|
||||
{
|
||||
/*
|
||||
public class CallNodeLookup : IFlowCallTree
|
||||
{
|
||||
private static readonly string[] _keys = new[]
|
||||
{
|
||||
"Start", // 0
|
||||
"Stop", // 1
|
||||
"Reset", // 2
|
||||
"Pause", // 3
|
||||
"Resume", // 4
|
||||
"Check", // 5
|
||||
"Init", // 6
|
||||
"Load", // 7
|
||||
"Save", // 8
|
||||
"Clear" // 9
|
||||
};
|
||||
|
||||
private static readonly CallNode[] _values = new CallNode[10];
|
||||
|
||||
static CallNodeLookup()
|
||||
{
|
||||
*//*_values[0] = new CallNode("Start");
|
||||
_values[1] = new CallNode("Stop");
|
||||
_values[2] = new CallNode("Reset");
|
||||
_values[3] = new CallNode("Pause");
|
||||
_values[4] = new CallNode("Resume");
|
||||
_values[5] = new CallNode("Check");
|
||||
_values[6] = new CallNode("Init");
|
||||
_values[7] = new CallNode("Load");
|
||||
_values[8] = new CallNode("Save");
|
||||
_values[9] = new CallNode("Clear");*//*
|
||||
}
|
||||
|
||||
// 最小冲突哈希函数(简单示例,固定键集有效)
|
||||
private static int PerfectHash(string key)
|
||||
{
|
||||
return key switch
|
||||
{
|
||||
"Start" => 0,
|
||||
"Stop" => 1,
|
||||
"Reset" => 2,
|
||||
"Pause" => 3,
|
||||
"Resume" => 4,
|
||||
"Check" => 5,
|
||||
"Init" => 6,
|
||||
"Load" => 7,
|
||||
"Save" => 8,
|
||||
"Clear" => 9,
|
||||
_ => -1
|
||||
};
|
||||
}
|
||||
|
||||
public CallNode Get(string key)
|
||||
{
|
||||
int index = PerfectHash(key);
|
||||
if (index >= 0 && _keys[index] == key)
|
||||
return _values[index];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 流程调用树,管理所有的调用节点
|
||||
/// </summary>
|
||||
public class FlowCallTree : IFlowCallTree
|
||||
{
|
||||
|
||||
private readonly SortedDictionary<string, CallNode> _callNodes = new SortedDictionary<string,CallNode>();
|
||||
//private readonly Dictionary<string, CallNode> _callNodes = new Dictionary<string,CallNode>();
|
||||
|
||||
/// <summary>
|
||||
/// 索引器,允许通过字符串索引访问CallNode
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode this[string index]
|
||||
{
|
||||
get
|
||||
@@ -92,17 +36,33 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个调用节点到流程调用树中
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="action"></param>
|
||||
public void AddCallNode(string nodeGuid, Action<IFlowContext> action)
|
||||
{
|
||||
var node = new CallNode(nodeGuid, action);
|
||||
_callNodes[nodeGuid] = node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个调用节点到流程调用树中,使用异步函数
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="func"></param>
|
||||
public void AddCallNode(string nodeGuid, Func<IFlowContext, Task> func)
|
||||
{
|
||||
var node = new CallNode(nodeGuid, func);
|
||||
_callNodes[nodeGuid] = node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定Key的CallNode,如果不存在则返回null
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode Get(string key)
|
||||
{
|
||||
return _callNodes.TryGetValue(key, out CallNode callNode) ? callNode : null;
|
||||
@@ -112,7 +72,9 @@ namespace Serein.Library
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 调用节点,代表一个流程中的调用点,可以是一个Action或一个异步函数。
|
||||
/// </summary>
|
||||
|
||||
public class CallNode
|
||||
{
|
||||
@@ -120,11 +82,21 @@ namespace Serein.Library
|
||||
private Func<IFlowContext, Task> taskFunc;
|
||||
private Action<IFlowContext> action;
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
public CallNode(string nodeGuid)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid和Action。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="action"></param>
|
||||
public CallNode(string nodeGuid, Action<IFlowContext> action)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
@@ -132,6 +104,11 @@ namespace Serein.Library
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的调用节点,使用指定的节点Guid和异步函数。
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid"></param>
|
||||
/// <param name="func"></param>
|
||||
public CallNode(string nodeGuid, Func<IFlowContext, Task> func)
|
||||
{
|
||||
Guid = nodeGuid;
|
||||
@@ -139,7 +116,9 @@ namespace Serein.Library
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化调用节点,设置默认的子节点和后继节点字典。
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
//PreviousNodes = new Dictionary<ConnectionInvokeType, List<CallNode>>();
|
||||
@@ -151,17 +130,28 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum ActionType
|
||||
{
|
||||
Action,
|
||||
Task,
|
||||
}
|
||||
private ActionType actionType = ActionType.Action;
|
||||
|
||||
/// <summary>
|
||||
/// 设置调用节点的Action,表示该节点执行一个同步操作。
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
public void SetAction(Action<IFlowContext> action)
|
||||
{
|
||||
this.action = action;
|
||||
actionType = ActionType.Action;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置调用节点的异步函数,表示该节点执行一个异步操作。
|
||||
/// </summary>
|
||||
/// <param name="taskFunc"></param>
|
||||
public void SetAction(Func<IFlowContext, Task> taskFunc)
|
||||
{
|
||||
this.taskFunc = taskFunc;
|
||||
@@ -173,15 +163,23 @@ namespace Serein.Library
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
public string Guid { get; }
|
||||
|
||||
#if false
|
||||
|
||||
/// <summary>
|
||||
/// 不同分支的父节点(流程调用)
|
||||
/// </summary>
|
||||
//public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
|
||||
public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
|
||||
|
||||
#endif
|
||||
/// <summary>
|
||||
/// 不同分支的子节点(流程调用)
|
||||
/// </summary>
|
||||
public Dictionary<ConnectionInvokeType, List<CallNode>> SuccessorNodes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点数组,分为四个分支:上游、成功、失败、错误,每个分支最多支持16个子节点。
|
||||
/// </summary>
|
||||
public CallNode[][] ChildNodes { get; private set; } = new CallNode[][]
|
||||
{
|
||||
new CallNode[MaxChildNodeCount],
|
||||
@@ -192,6 +190,11 @@ namespace Serein.Library
|
||||
private const int MaxChildNodeCount = 16; // 每个分支最多支持16个子节点
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的子节点数量。
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public int GetCount(ConnectionInvokeType type)
|
||||
{
|
||||
if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount;
|
||||
@@ -201,11 +204,29 @@ namespace Serein.Library
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的子节点数量。
|
||||
/// </summary>
|
||||
public int UpstreamNodeCount { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的成功后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsSuccessorNodeCount { get; private set; } = 0;
|
||||
/// <summary>
|
||||
/// 获取当前节点的失败后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsFailNodeCount { get; private set; } = 0;
|
||||
/// <summary>
|
||||
/// 获取当前节点的错误后继子节点数量。
|
||||
/// </summary>
|
||||
public int IsErrorNodeCount { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个上游子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeUpstream(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.Upstream;
|
||||
@@ -214,6 +235,11 @@ namespace Serein.Library
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个成功后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeSucceed(CallNode callNode)
|
||||
{
|
||||
ChildNodes[0][UpstreamNodeCount++] = callNode;
|
||||
@@ -224,6 +250,11 @@ namespace Serein.Library
|
||||
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 添加一个失败后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeFail(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.IsFail;
|
||||
@@ -232,6 +263,12 @@ namespace Serein.Library
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个错误后继子节点到当前节点。
|
||||
/// </summary>
|
||||
/// <param name="callNode"></param>
|
||||
/// <returns></returns>
|
||||
public CallNode AddChildNodeError(CallNode callNode)
|
||||
{
|
||||
var connectionInvokeType = ConnectionInvokeType.IsError;
|
||||
@@ -268,7 +305,7 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly DefaultObjectPool<Stack<CallNode>> _stackPool = new DefaultObjectPool<Stack<CallNode>>(new DefaultPooledObjectPolicy<Stack<CallNode>>());
|
||||
private static readonly ObjectPool<Stack<CallNode>> _stackPool = new ObjectPool<Stack<CallNode>>(() => new Stack<CallNode>());
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -279,7 +316,7 @@ namespace Serein.Library
|
||||
/// <returns></returns>
|
||||
public async Task<FlowResult> StartFlowAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
var stack = _stackPool.Get();
|
||||
var stack = _stackPool.Allocate();
|
||||
stack.Push(this);
|
||||
while (true)
|
||||
{
|
||||
@@ -331,7 +368,7 @@ namespace Serein.Library
|
||||
|
||||
if (stack.Count == 0)
|
||||
{
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
flowResult = context.GetFlowData(currentNode.Guid);
|
||||
return flowResult; // 说明流程到了终点
|
||||
}
|
||||
@@ -339,7 +376,7 @@ namespace Serein.Library
|
||||
if (context.RunState == RunState.Completion)
|
||||
{
|
||||
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
context.Env.WriteLine(InfoType.INFO, $"流程执行到节点[{currentNode.Guid}]时提前结束,将返回当前执行结果。");
|
||||
flowResult = context.GetFlowData(currentNode.Guid);
|
||||
return flowResult; // 流程执行完成,返回结果
|
||||
@@ -347,7 +384,7 @@ namespace Serein.Library
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
_stackPool.Return(stack);
|
||||
_stackPool.Free(stack);
|
||||
throw new Exception($"流程执行到节点[{currentNode.Guid}]时被取消,未能获取到流程结果。");
|
||||
}
|
||||
|
||||
@@ -359,8 +396,16 @@ namespace Serein.Library
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程调用树接口,提供获取CallNode的方法。
|
||||
/// </summary>
|
||||
public interface IFlowCallTree
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定Key的CallNode,如果不存在则返回null。
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
CallNode Get(string key);
|
||||
}
|
||||
|
||||
@@ -371,10 +416,22 @@ namespace Serein.Library
|
||||
{
|
||||
private readonly IFlowCallTree flowCallTree;
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程上下文池,使用对象池模式来管理流程上下文的创建和回收。
|
||||
/// </summary>
|
||||
public static Serein.Library.Utils.ObjectPool<IFlowContext> FlowContextPool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单例IOC容器,用于依赖注入和服务定位。
|
||||
/// </summary>
|
||||
public ISereinIOC IOC => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程控制器构造函数,接受流程调用树和流程环境作为参数。
|
||||
/// </summary>
|
||||
/// <param name="flowCallTree"></param>
|
||||
/// <param name="flowEnvironment"></param>
|
||||
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
this.flowCallTree = flowCallTree;
|
||||
@@ -385,11 +442,12 @@ namespace Serein.Library
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<object> InvokeAsync(string apiGuid, Dictionary<string, object> dict)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<TResult> InvokeAsync<TResult>(string apiGuid, Dictionary<string, object> dict)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -398,7 +456,7 @@ namespace Serein.Library
|
||||
|
||||
//private readonly DefaultObjectPool<IDynamicContext> _stackPool = new DefaultObjectPool<IDynamicContext>(new DynamicContext(this));
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<TResult> StartFlowAsync<TResult>(string startNodeGuid)
|
||||
{
|
||||
IFlowContext context = Serein.Library.LightweightFlowControl.FlowContextPool.Allocate();
|
||||
@@ -443,45 +501,48 @@ namespace Serein.Library
|
||||
throw new ArgumentNullException($"类型转换失败,流程返回数据与泛型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}]。");
|
||||
}
|
||||
}
|
||||
public async Task<bool> StartFlowAsync(string[] canvasGuids)
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<bool> StartFlowAsync(string[] canvasGuids)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<bool> ExitFlowAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#region 无须实现
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void TerminateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UseExternalIOC(ISereinIOC ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC> setDefultMemberOnReset = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@@ -495,110 +556,128 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class LightweightFlowEnvironmentEvent : IFlowEnvironmentEvent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public event LoadDllHandler DllLoad;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectLoadedHandler ProjectLoaded;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectSavingHandler ProjectSaving;
|
||||
/// <inheritdoc/>
|
||||
public event NodeConnectChangeHandler NodeConnectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasCreateHandler CanvasCreated;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasRemoveHandler CanvasRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodeCreateHandler NodeCreated;
|
||||
/// <inheritdoc/>
|
||||
public event NodeRemoveHandler NodeRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodePlaceHandler NodePlace;
|
||||
/// <inheritdoc/>
|
||||
public event NodeTakeOutHandler NodeTakeOut;
|
||||
/// <inheritdoc/>
|
||||
public event StartNodeChangeHandler StartNodeChanged;
|
||||
/// <inheritdoc/>
|
||||
public event FlowRunCompleteHandler FlowRunComplete;
|
||||
/// <inheritdoc/>
|
||||
public event MonitorObjectChangeHandler MonitorObjectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeInterruptStateChangeHandler NodeInterruptStateChanged;
|
||||
/// <inheritdoc/>
|
||||
public event ExpInterruptTriggerHandler InterruptTriggered;
|
||||
/// <inheritdoc/>
|
||||
public event IOCMembersChangedHandler IOCMembersChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeLocatedHandler NodeLocated;
|
||||
/// <inheritdoc/>
|
||||
public event EnvOutHandler EnvOutput;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnDllLoad(LoadDllEventArgs eventArgs)
|
||||
{
|
||||
DllLoad?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
|
||||
{
|
||||
ProjectLoaded?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectSaving(ProjectSavingEventArgs eventArgs)
|
||||
{
|
||||
ProjectSaving?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeConnectChanged(NodeConnectChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeConnectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasCreated(CanvasCreateEventArgs eventArgs)
|
||||
{
|
||||
CanvasCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasRemoved(CanvasRemoveEventArgs eventArgs)
|
||||
{
|
||||
CanvasRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeCreated(NodeCreateEventArgs eventArgs)
|
||||
{
|
||||
NodeCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeRemoved(NodeRemoveEventArgs eventArgs)
|
||||
{
|
||||
NodeRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodePlace(NodePlaceEventArgs eventArgs)
|
||||
{
|
||||
NodePlace?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeTakeOut(NodeTakeOutEventArgs eventArgs)
|
||||
{
|
||||
NodeTakeOut?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnStartNodeChanged(StartNodeChangeEventArgs eventArgs)
|
||||
{
|
||||
StartNodeChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnFlowRunComplete(FlowEventArgs eventArgs)
|
||||
{
|
||||
FlowRunComplete?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnMonitorObjectChanged(MonitorObjectEventArgs eventArgs)
|
||||
{
|
||||
MonitorObjectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeInterruptStateChanged(NodeInterruptStateChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeInterruptStateChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnInterruptTriggered(InterruptTriggerEventArgs eventArgs)
|
||||
{
|
||||
InterruptTriggered?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs)
|
||||
{
|
||||
IOCMembersChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeLocated(NodeLocatedEventArgs eventArgs)
|
||||
{
|
||||
NodeLocated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnEnvOutput(InfoType type, string value)
|
||||
{
|
||||
EnvOutput?.Invoke(type, value);
|
||||
@@ -611,128 +690,131 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public class LightweightFlowEnvironment : IFlowEnvironment
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 轻量级流程环境构造函数,接受一个流程环境事件接口。
|
||||
/// </summary>
|
||||
/// <param name="lightweightFlowEnvironmentEvent"></param>
|
||||
public LightweightFlowEnvironment(IFlowEnvironmentEvent lightweightFlowEnvironmentEvent)
|
||||
{
|
||||
this.Event = lightweightFlowEnvironmentEvent;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
public void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ISereinIOC IOC => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEdit FlowEdit => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowControl FlowControl => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironmentEvent Event { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string EnvName => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string ProjectFileLocation => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool _IsGlobalInterrupt => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsControlRemoteEnv => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public InfoClass InfoClass { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
/// <inheritdoc/>
|
||||
public RunState FlowState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IFlowEnvironment CurrentEnv => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public UIContextOperation UIContextOperation => throw new NotImplementedException();
|
||||
|
||||
/* public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}*/
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void ExitRemoteEnv()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<SereinProjectData> GetProjectInfoAsync()
|
||||
/// <inheritdoc/>
|
||||
public SereinProjectData GetProjectInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadLibrary(string dllPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool LoadNativeLibraryOfRuning(string file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void LoadProject(string filePath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task LoadProjetAsync(string filePath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SaveProject()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetUIContextOperation(UIContextOperation uiContextOperation)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void StopRemoteServer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryUnloadLibrary(string assemblyFullName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 每个节点有独自的MethodDetails实例
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Method)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Method)]
|
||||
public partial class MethodDetails
|
||||
{
|
||||
// private readonly IFlowEnvironment env;
|
||||
@@ -20,57 +20,51 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的程序集
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _assemblyName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 调用节点方法时需要的实例(多个相同的节点将拥有相同的类型)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _actingInstanceType;
|
||||
|
||||
/// <summary>
|
||||
/// 作用实例(多个相同的节点将会共享同一个实例)
|
||||
/// </summary>
|
||||
// [PropertyInfo]
|
||||
// private object _actingInstance;
|
||||
|
||||
/// <summary>
|
||||
/// 方法名称
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodName;
|
||||
|
||||
/// <summary>
|
||||
/// 节点类型
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private NodeType _methodDynamicType;
|
||||
|
||||
/// <summary>
|
||||
/// 锁名称(暂未实现)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodLockName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 方法别名
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _methodAnotherName;
|
||||
|
||||
/// <summary>
|
||||
/// 参数描述
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private ParameterDetails[] _parameterDetailss;
|
||||
|
||||
/// <summary>
|
||||
@@ -78,19 +72,19 @@ namespace Serein.Library
|
||||
/// <para>-1表示不存在</para>
|
||||
/// <para>0表示第一个参数是可选参数</para>
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private int _paramsArgIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为异步方法(如果为异步方法,则返回值类型为Task或Task<T>)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private bool _isAsync = false;
|
||||
|
||||
/// <summary>
|
||||
/// 出参类型
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _returnType;
|
||||
}
|
||||
|
||||
@@ -133,7 +127,11 @@ namespace Serein.Library
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 新增可变参数
|
||||
/// </summary>
|
||||
/// <param name="parameterDetails"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddParamsArg(ParameterDetails parameterDetails)
|
||||
{
|
||||
if (ParamsArgIndex < 0) // 方法是否包含可变参数
|
||||
@@ -313,6 +311,10 @@ namespace Serein.Library
|
||||
return md;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将方法信息转换为字符串,方便调试和查看
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.MethodName))
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点调试设置,用于中断节点的运行
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.DebugSetting)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.DebugSetting)]
|
||||
public partial class NodeDebugSetting
|
||||
{
|
||||
/// <summary>
|
||||
@@ -24,25 +24,25 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 是否保护参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isProtectionParameter = false;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 是否使能
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isEnable = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否中断节点。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isInterrupt = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public Type ViewModelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 节点类型信息字符串表示
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"$[{NodeType}]类型信息 : ModelType->{ModelType};ControlType->{ControlType};ViewModelType->{ViewModelType}";
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点入参参数详情
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Parameter)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Parameter)]
|
||||
public partial class ParameterDetails
|
||||
{
|
||||
// private readonly IFlowEnvironment env;
|
||||
@@ -22,13 +22,13 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 所在的节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowNode _nodeModel;
|
||||
|
||||
/// <summary>
|
||||
/// 参数索引
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private int _index;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +36,7 @@ namespace Serein.Library
|
||||
/// <para>如果为 true ,则使用输入的文本值作为入参数据。</para>
|
||||
/// <para>如果为 false ,则在当前流程上下文中,根据 ArgDataSourceNodeGuid 查找到对应节点,并根据 ArgDataSourceNodeGuid 判断如何获取其返回的数据,以此作为入参数据。</para>
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true, IsVerify = true)]
|
||||
[DataInfo(IsNotification = true, IsVerify = true)]
|
||||
private bool _isExplicitData ;
|
||||
|
||||
///// <summary>
|
||||
@@ -49,7 +49,7 @@ namespace Serein.Library
|
||||
/// 方法入参若无相关转换器特性标注,则无需关注该变量。该变量用于需要用到枚举BinValue转换器时,指示相应的入参变量需要转为的类型。
|
||||
/// </summary>
|
||||
[Obsolete("转换器特性将在下一个大版本中移除")]
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _explicitType ;
|
||||
|
||||
/// <summary>
|
||||
@@ -58,56 +58,56 @@ namespace Serein.Library
|
||||
/// <para>Bool : 布尔类型</para>
|
||||
/// <para>Value :除以上类型之外的任意参数</para>
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private ParameterValueInputType _inputType ;
|
||||
|
||||
/// <summary>
|
||||
/// 入参数据来源。默认使用上一节点作为入参数据。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private ConnectionArgSourceType _argDataSourceType = ConnectionArgSourceType.GetPreviousNodeData;
|
||||
|
||||
/// <summary>
|
||||
/// 当 ArgDataSourceType 不为 GetPreviousNodeData 时(从运行时上一节点获取数据)。
|
||||
/// 则通过当前上下文,获取该Guid对应的数据作为预处理的入参参数。
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _argDataSourceNodeGuid;
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参需要的类型。
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private Type _dataType ;
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参参数名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _name ;
|
||||
|
||||
/// <summary>
|
||||
/// 入参注释
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _description;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义的方法入参数据
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)] // IsPrint = true
|
||||
[DataInfo(IsNotification = true)] // IsPrint = true
|
||||
private string _dataValue;
|
||||
|
||||
/// <summary>
|
||||
/// 只有当 InputType 为 Select 时,才会需要该成员。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string[] _items ;
|
||||
|
||||
/// <summary>
|
||||
/// 指示该属性是可变参数的其中一员(可变参数为数组类型)
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private bool _isParams;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,11 @@ namespace Serein.Library
|
||||
this.NodeModel = nodeModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过参数数据加载实体,用于加载项目文件、远程连接的场景
|
||||
/// </summary>
|
||||
/// <param name="pdInfo"></param>
|
||||
/// <param name="argIndex"></param>
|
||||
public ParameterDetails(ParameterData pdInfo, int argIndex)
|
||||
{
|
||||
this.Index = argIndex;
|
||||
@@ -163,6 +168,7 @@ namespace Serein.Library
|
||||
IsParams = info.IsParams;
|
||||
}
|
||||
|
||||
|
||||
partial void BeforeTheIsExplicitData(ref bool __isAllow, bool newValue)
|
||||
{
|
||||
if(DataType == typeof(IFlowContext))
|
||||
@@ -214,6 +220,12 @@ namespace Serein.Library
|
||||
return pd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为方法入参数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<object> ToMethodArgData(IFlowContext context)
|
||||
{
|
||||
// 1. 从缓存获取
|
||||
@@ -481,6 +493,10 @@ namespace Serein.Library
|
||||
throw new Exception($"[arg{Index}][{Name}][{DataType}]入参类型不符合,当前预入参类型为{inputParameterType}");
|
||||
}
|
||||
*/
|
||||
/// <summary>
|
||||
/// 转为字符串描述
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{this.Index}] {(string.IsNullOrWhiteSpace(this.Description) ? string.Empty : $"({this.Description})")}{this.Name} : {this.DataType?.FullName}";
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点于画布中的位置(通用类)
|
||||
/// </summary>
|
||||
[NodeProperty]
|
||||
[FlowDataProperty]
|
||||
public partial class PositionOfUI
|
||||
{
|
||||
/// <summary>
|
||||
@@ -285,13 +285,13 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 指示控件在画布的横向向方向上的位置
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private double _x = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 指示控件在画布的纵向方向上的位置
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private double _y = 0;
|
||||
}
|
||||
|
||||
|
||||
8
Library/Properties/launchSettings.json
Normal file
8
Library/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Serein.Library": {
|
||||
"commandName": "Project",
|
||||
"remoteDebugEnabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,35 +8,83 @@ namespace Serein.Library
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 脚本代码中常用的函数
|
||||
/// </summary>
|
||||
public static class ScriptBaseFunc
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前时间
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DateTime now() => DateTime.Now;
|
||||
|
||||
#region 常用的类型转换
|
||||
/// <summary>
|
||||
/// 将值转换为bool类型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool @bool(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<bool>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为字节类型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static byte @byte(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<byte>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为短整型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal @decimal(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<decimal>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为浮点型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float @float(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<float>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为双精度浮点型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double @double(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<double>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为整数类型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int @int(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<int>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将值转换为长整型
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int @long(object value)
|
||||
{
|
||||
return ConvertHelper.ValueParse<int>(value);
|
||||
@@ -44,6 +92,12 @@ namespace Serein.Library
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 获取集合或数组的长度
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static int len(object target)
|
||||
{
|
||||
// 获取数组或集合对象
|
||||
@@ -70,28 +124,50 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为字符串
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string str(object obj)
|
||||
{
|
||||
return obj?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取全局数据
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static object global(string name)
|
||||
{
|
||||
return SereinEnv.GetFlowGlobalData(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象的类型
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static Type type(object type)
|
||||
{
|
||||
return type.GetType();
|
||||
}
|
||||
/// <summary>
|
||||
/// 记录日志信息
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
|
||||
public static void log(object value)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, value?.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待一段时间
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task sleep(object value)
|
||||
{
|
||||
if (value is int @int)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<Title>SereinFow</Title>
|
||||
<Version>1.2.2</Version>
|
||||
<Version>1.2.3</Version>
|
||||
<Description>动态节点流、可视化编辑的基本依赖,支持导入C# DLL生成自定义节点,提供二次开发支持,适合用于可视化编程和流程设计</Description>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
||||
@@ -65,14 +65,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0" />
|
||||
<PackageReference Include="System.IO.Ports" Version="9.0.7" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.3.0" />
|
||||
<!--<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -87,6 +82,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj " OutputItemType="Analyzer" />-->
|
||||
<!-- ReferenceOutputAssembly="false" -->
|
||||
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj " OutputItemType="Analyzer" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 数组操作的工具类
|
||||
/// </summary>
|
||||
public class ArrayHelper
|
||||
{
|
||||
|
||||
|
||||
@@ -270,6 +270,14 @@ namespace Serein.Library.Utils
|
||||
|
||||
return (T)result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串转换为指定类型的值对象。
|
||||
/// </summary>
|
||||
/// <param name="valueStr"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static object ToValueData(this string valueStr, Type type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(valueStr))
|
||||
|
||||
@@ -41,21 +41,40 @@ namespace Serein.Library.Utils
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析字典属性并创建对象实例
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public static object Resolve(IDictionary<string, object> properties, string typeName)
|
||||
{
|
||||
var obj = CreateObjectWithProperties(properties, typeName);
|
||||
//SetPropertyValues(obj, properties);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试解析字典属性并创建对象实例
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryResolve(IDictionary<string, object> properties, string typeName, out object result)
|
||||
{
|
||||
result = CreateObjectWithProperties(properties, typeName);
|
||||
bool success = SetPropertyValuesWithValidation(result, properties);
|
||||
return success;
|
||||
// 打印赋值结果
|
||||
|
||||
}
|
||||
// 递归方法:打印对象属性及类型
|
||||
|
||||
/// <summary>
|
||||
/// 打印对象属性及类型
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="indent"></param>
|
||||
public static void PrintObjectProperties(object obj, string indent = "")
|
||||
{
|
||||
var objType = obj.GetType();
|
||||
@@ -327,7 +346,12 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
#region 动态创建对象并赋值
|
||||
|
||||
// 方法 1: 创建动态类型及其对象实例
|
||||
/// <summary>
|
||||
/// 创建动态类型及其对象实例
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static object CreateObjectWithProperties(IDictionary<string, object> properties, string typeName)
|
||||
{
|
||||
// 如果类型已经缓存,直接返回缓存的类型
|
||||
@@ -410,8 +434,12 @@ namespace Serein.Library.Utils
|
||||
return Activator.CreateInstance(dynamicType);
|
||||
}
|
||||
|
||||
// 方法 2: 递归设置对象的属性值
|
||||
public static void SetPropertyValues(object obj, Dictionary<string, object> properties)
|
||||
/// <summary>
|
||||
/// 递归设置对象的属性值
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="properties"></param>
|
||||
private static void SetPropertyValues(object obj, Dictionary<string, object> properties)
|
||||
{
|
||||
var objType = obj.GetType();
|
||||
|
||||
@@ -439,8 +467,13 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
}
|
||||
}
|
||||
// 方法 2: 递归设置对象的属性值(带验证)
|
||||
|
||||
/// <summary>
|
||||
/// 递归设置对象的属性值(带验证)
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="properties"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SetPropertyValuesWithValidation(object obj, IDictionary<string, object> properties)
|
||||
{
|
||||
var objType = obj.GetType();
|
||||
|
||||
@@ -9,12 +9,15 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Utils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Emit创建委托工具类
|
||||
/// </summary>
|
||||
public class EmitHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 动态方法信息
|
||||
/// </summary>
|
||||
public class EmitMethodInfo
|
||||
{
|
||||
/// <summary>
|
||||
@@ -39,6 +42,9 @@ namespace Serein.Library.Utils
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 方法类型枚举
|
||||
/// </summary>
|
||||
public enum EmitMethodType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -55,12 +61,19 @@ namespace Serein.Library.Utils
|
||||
TaskHasResult,
|
||||
}
|
||||
|
||||
public static bool IsGenericTask(Type returnType, out Type taskResult)
|
||||
/// <summary>
|
||||
/// 判断一个类型是否为泛型 Task<T> 或 Task,并返回泛型参数类型(如果有的话)
|
||||
/// </summary>
|
||||
/// <param name="returnType"></param>
|
||||
/// <param name="taskResult"></param>
|
||||
/// <returns></returns>
|
||||
#nullable enable
|
||||
public static bool IsGenericTask(Type returnType, out Type? taskResult)
|
||||
{
|
||||
// 判断是否为 Task 类型或泛型 Task<T>
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
taskResult = null;
|
||||
taskResult = typeof(void);
|
||||
return true;
|
||||
}
|
||||
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
@@ -78,7 +91,6 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据方法信息创建动态调用的委托,返回方法类型,以及传出一个委托
|
||||
/// </summary>
|
||||
@@ -87,6 +99,10 @@ namespace Serein.Library.Utils
|
||||
/// <returns></returns>
|
||||
public static EmitMethodInfo CreateDynamicMethod(MethodInfo methodInfo,out Delegate @delegate)
|
||||
{
|
||||
if (methodInfo.DeclaringType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(methodInfo.DeclaringType));
|
||||
}
|
||||
EmitMethodInfo emitMethodInfo = new EmitMethodInfo();
|
||||
bool IsTask = IsGenericTask(methodInfo.ReturnType, out var taskGenericsType);
|
||||
bool IsTaskGenerics = taskGenericsType != null;
|
||||
@@ -220,6 +236,10 @@ namespace Serein.Library.Utils
|
||||
if (fieldInfo == null)
|
||||
throw new ArgumentNullException(nameof(fieldInfo));
|
||||
|
||||
if (fieldInfo.DeclaringType == null)
|
||||
throw new ArgumentNullException(nameof(fieldInfo.DeclaringType));
|
||||
|
||||
|
||||
var method = new DynamicMethod(
|
||||
fieldInfo.Name + "_Get",
|
||||
typeof(object),
|
||||
@@ -257,6 +277,8 @@ namespace Serein.Library.Utils
|
||||
{
|
||||
if (fieldInfo == null)
|
||||
throw new ArgumentNullException(nameof(fieldInfo));
|
||||
if (fieldInfo.DeclaringType == null)
|
||||
throw new ArgumentNullException(nameof(fieldInfo.DeclaringType));
|
||||
if (fieldInfo.IsInitOnly)
|
||||
throw new InvalidOperationException($"字段 {fieldInfo.Name} 是只读字段,无法设置值。");
|
||||
|
||||
@@ -299,6 +321,8 @@ namespace Serein.Library.Utils
|
||||
{
|
||||
if (propertyInfo == null)
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
if (propertyInfo.DeclaringType == null)
|
||||
throw new ArgumentNullException(nameof(propertyInfo.DeclaringType));
|
||||
var getMethod = propertyInfo.GetGetMethod(true);
|
||||
if (getMethod == null)
|
||||
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Getter。");
|
||||
@@ -339,6 +363,9 @@ namespace Serein.Library.Utils
|
||||
{
|
||||
if (propertyInfo == null)
|
||||
throw new ArgumentNullException(nameof(propertyInfo));
|
||||
if (propertyInfo.DeclaringType == null)
|
||||
throw new ArgumentNullException(nameof(propertyInfo.DeclaringType));
|
||||
|
||||
var setMethod = propertyInfo.GetSetMethod(true);
|
||||
if (setMethod == null)
|
||||
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Setter。");
|
||||
|
||||
@@ -59,6 +59,13 @@ namespace Serein.Library.Utils
|
||||
return attribute != null ? (TResult)valueSelector(attribute) : default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从枚举值的 BindValueAttribute 特性中 获取绑定的参数(用于绑定了某些内容的枚举值)
|
||||
/// </summary>
|
||||
/// <param name="enumType"></param>
|
||||
/// <param name="enumValue"></param>
|
||||
/// <param name="valueSelector"></param>
|
||||
/// <returns></returns>
|
||||
public static object GetBoundValue(Type enumType,object enumValue, Func<BindValueAttribute, object> valueSelector)
|
||||
{
|
||||
var fieldInfo = enumType.GetField(enumValue.ToString());
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Serein.Library.Utils
|
||||
var parameter = Expression.Parameter(typeof(object), "instance");
|
||||
var methodCall = Expression.Call(Expression.Convert(parameter, type), methodInfo);
|
||||
|
||||
if (IsGenericTask(methodInfo.ReturnType, out var taskResult))
|
||||
if (EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult))
|
||||
{
|
||||
if (taskResult is null)
|
||||
{
|
||||
@@ -278,7 +278,7 @@ namespace Serein.Library.Utils
|
||||
convertedArgs
|
||||
);
|
||||
|
||||
if (IsGenericTask(methodInfo.ReturnType, out var taskResult))
|
||||
if (EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult))
|
||||
{
|
||||
if (taskResult is null)
|
||||
{
|
||||
@@ -305,7 +305,7 @@ namespace Serein.Library.Utils
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 表达式树构建无参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// 表达式树构建无参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// </summary>
|
||||
public static Delegate MethodCallerAsync(Type type, MethodInfo methodInfo)
|
||||
{
|
||||
@@ -314,7 +314,7 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表达式树构建无参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// 表达式树构建无参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="methodInfo"></param>
|
||||
@@ -332,7 +332,7 @@ namespace Serein.Library.Utils
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 表达式树构建多个参数,有返回值(Task-object)的方法(触发器)
|
||||
/// 表达式树构建多个参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// </summary>
|
||||
public static Delegate MethodCallerAsync(Type type, MethodInfo method, params Type[] parameterTypes)
|
||||
{
|
||||
@@ -342,7 +342,7 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表达式树构建多个参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// 表达式树构建多个参数,有返回值(Task<object>)的方法(触发器)
|
||||
/// </summary>
|
||||
private static Delegate CreateMethodCallerDelegateAsync(Type type, MethodInfo methodInfo, Type[] parameterTypes)
|
||||
{
|
||||
@@ -384,31 +384,12 @@ namespace Serein.Library.Utils
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static bool IsGenericTask(Type returnType, out Type taskResult)
|
||||
{
|
||||
// 判断是否为 Task 类型或泛型 Task<T>
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
taskResult = null;
|
||||
return true;
|
||||
}
|
||||
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 获取泛型参数类型
|
||||
Type genericArgument = returnType.GetGenericArguments()[0];
|
||||
taskResult = genericArgument;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult = null;
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// / 自动创建一个委托,根据方法信息和类型
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="methodInfo"></param>
|
||||
/// <returns></returns>
|
||||
public static Delegate AutoCreate(Type type, MethodInfo methodInfo)
|
||||
{
|
||||
Type returnType = methodInfo.ReturnType;
|
||||
|
||||
@@ -9,6 +9,10 @@ using System.Threading.Tasks;
|
||||
namespace Serein.Library.Utils
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 基于 Channel 的触发器实现
|
||||
/// </summary>
|
||||
/// <typeparam name="TSignal"></typeparam>
|
||||
public class ChannelFlowTrigger<TSignal> : IFlowTrigger<TSignal>
|
||||
{
|
||||
// 使用并发字典管理每个枚举信号对应的 Channel
|
||||
@@ -24,6 +28,13 @@ namespace Serein.Library.Utils
|
||||
return _channels.GetOrAdd(signal, _ => Channel.CreateUnbounded<TriggerResult<object>>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待信号触发并指定超时时间
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="signal"></param>
|
||||
/// <param name="outTime"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TriggerResult<TResult>> WaitTriggerWithTimeoutAsync<TResult>(TSignal signal, TimeSpan outTime)
|
||||
{
|
||||
var channel = GetOrCreateChannel(signal);
|
||||
@@ -54,6 +65,12 @@ namespace Serein.Library.Utils
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待信号触发
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="signal"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<TriggerResult<TResult>> WaitTriggerAsync<TResult>(TSignal signal)
|
||||
{
|
||||
var channel = GetOrCreateChannel(signal);
|
||||
@@ -76,6 +93,13 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调用触发器
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="signal"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> InvokeTriggerAsync<TResult>(TSignal signal, TResult value)
|
||||
{
|
||||
if (_channels.TryGetValue(signal, out var channel))
|
||||
@@ -92,6 +116,9 @@ namespace Serein.Library.Utils
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消所有触发器
|
||||
/// </summary>
|
||||
public void CancelAllTrigger()
|
||||
{
|
||||
foreach (var channel in _channels.Values)
|
||||
|
||||
@@ -141,13 +141,30 @@ namespace Serein.Library.Utils
|
||||
{
|
||||
private readonly Action<T> _onNext;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,接受一个 Action 作为回调
|
||||
/// </summary>
|
||||
/// <param name="onNext"></param>
|
||||
public Observer(Action<T> onNext)
|
||||
{
|
||||
_onNext = onNext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知订阅者已完成或发生错误
|
||||
/// </summary>
|
||||
public void OnCompleted() { }
|
||||
|
||||
/// <summary>
|
||||
/// 通知订阅者发生错误
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
public void OnError(Exception error) { }
|
||||
|
||||
/// <summary>
|
||||
/// 通知订阅者有新数据到来
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void OnNext(T value)
|
||||
{
|
||||
_onNext?.Invoke(value);
|
||||
|
||||
@@ -7,9 +7,20 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发器结果类,用于存储触发器的类型和返回值。
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
public class TriggerResult<TResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// 触发类型
|
||||
/// </summary>
|
||||
public TriggerDescription Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发结果值
|
||||
/// </summary>
|
||||
public TResult Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,28 +23,57 @@ namespace Serein.Library.Utils
|
||||
JsonHelper.provider = jsonPortal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化Json文本为指定类型的对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="jsonText"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public static T Deserialize<T>(string jsonText)
|
||||
{
|
||||
return provider.Deserialize<T>(jsonText);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化Json文本为指定类型的对象
|
||||
/// </summary>
|
||||
/// <param name="jsonText"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static object Deserialize(string jsonText, Type type)
|
||||
{
|
||||
return provider.Deserialize(jsonText, type);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析Json文本为IJsonToken对象
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public static IJsonToken Parse(string json)
|
||||
{
|
||||
return provider.Parse(json);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将对象序列化为Json文本
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string Serialize(object obj)
|
||||
{
|
||||
return provider.Serialize(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个Json对象,使用字典初始化
|
||||
/// </summary>
|
||||
/// <param name="init"></param>
|
||||
/// <returns></returns>
|
||||
public static IJsonToken Object(Action<Dictionary<string, object>> init)
|
||||
{
|
||||
var dict = new Dictionary<string, object>();
|
||||
@@ -52,11 +81,21 @@ namespace Serein.Library.Utils
|
||||
return provider.CreateObject(dict);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个Json对象,使用字典初始化
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
public static IJsonToken Array(IEnumerable<object> values)
|
||||
{
|
||||
return provider.CreateArray(values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为JsonToken
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static IJsonToken FromObject(object obj)
|
||||
{
|
||||
if (obj is System.Collections.IEnumerable && !(obj is string))
|
||||
|
||||
@@ -32,6 +32,14 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步选择器,返回一个新的集合,其中每个元素都是通过异步方法转换的结果。
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<IEnumerable<TResult>> SelectAsync<TSource, TResult>(this IEnumerable<TSource> source,
|
||||
Func<TSource, Task<TResult>> method)
|
||||
{
|
||||
@@ -39,6 +47,15 @@ namespace Serein.Library.Utils
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步选择器,返回一个新的集合,其中每个元素都是通过异步方法转换的结果。
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="method"></param>
|
||||
/// <param name="concurrency"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<IEnumerable<TResult>> SelectAsync<TSource, TResult>(this IEnumerable<TSource> source,
|
||||
Func<TSource, Task<TResult>> method,
|
||||
int concurrency = int.MaxValue)
|
||||
|
||||
@@ -28,23 +28,39 @@ namespace Serein.Library.Utils
|
||||
internal T Value;
|
||||
}
|
||||
|
||||
// 不使用System。Func{T},因为. net 2.0没有该类型。
|
||||
/// <summary>
|
||||
/// 不使用System。Func{T},因为. net 2.0没有该类型。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public delegate T Factory();
|
||||
|
||||
// 池对象的存储。第一个项存储在专用字段中,因为我们希望能够满足来自它的大多数请求。
|
||||
/// <summary>
|
||||
/// 池对象的存储。第一个项存储在专用字段中,因为我们希望能够满足来自它的大多数请求。
|
||||
/// </summary>
|
||||
private T _firstItem;
|
||||
|
||||
private readonly Element[] _items;
|
||||
|
||||
// 工厂在池的生命周期内被存储。只有当池需要扩展时,我们才调用它。
|
||||
// 与“new T()”相比,Func为实现者提供了更多的灵活性,并且比“new T()”更快。
|
||||
/// <summary>
|
||||
/// 工厂在池的生命周期内被存储。只有当池需要扩展时,我们才调用它。
|
||||
/// 与“new T()”相比,Func为实现者提供了更多的灵活性,并且比“new T()”更快。
|
||||
/// </summary>
|
||||
private readonly Factory _factory;
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的对象池实例,使用指定的工厂函数和默认大小(处理器核心数的两倍)。
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
public ObjectPool(Factory factory)
|
||||
: this(factory, Environment.ProcessorCount * 2)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的对象池实例,使用指定的工厂函数和指定的大小。
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="size"></param>
|
||||
public ObjectPool(Factory factory, int size)
|
||||
{
|
||||
Debug.Assert(size >= 1);
|
||||
@@ -52,6 +68,10 @@ namespace Serein.Library.Utils
|
||||
_items = new Element[size - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的实例。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private T CreateInstance()
|
||||
{
|
||||
T inst = _factory();
|
||||
@@ -82,6 +102,10 @@ namespace Serein.Library.Utils
|
||||
return inst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 慢速分配方法,当第一个元素不可用时调用。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private T AllocateSlow()
|
||||
{
|
||||
Element[] items = _items;
|
||||
|
||||
@@ -669,6 +669,12 @@ namespace Serein.Library.Utils
|
||||
|
||||
#region 运行
|
||||
|
||||
/// <summary>
|
||||
/// 运行一个方法,方法的参数类型由IOC容器提供
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public ISereinIOC Run<T>(Action<T> action)
|
||||
{
|
||||
var service = Get<T>();
|
||||
@@ -676,6 +682,13 @@ namespace Serein.Library.Utils
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行一个方法,方法的参数类型由IOC容器提供
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public ISereinIOC Run<T1, T2>(Action<T1, T2> action)
|
||||
{
|
||||
var service1 = Get<T1>();
|
||||
@@ -685,6 +698,14 @@ namespace Serein.Library.Utils
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行一个方法,方法的参数类型由IOC容器提供
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <typeparam name="T3"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public ISereinIOC Run<T1, T2, T3>(Action<T1, T2, T3> action)
|
||||
{
|
||||
var service1 = Get<T1>();
|
||||
@@ -694,6 +715,15 @@ namespace Serein.Library.Utils
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行一个方法,方法的参数类型由IOC容器提供
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <typeparam name="T3"></typeparam>
|
||||
/// <typeparam name="T4"></typeparam>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public ISereinIOC Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
|
||||
{
|
||||
var service1 = Get<T1>();
|
||||
|
||||
@@ -54,11 +54,12 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
|
||||
|
||||
private FlowWorkManagement flowWorkManagement;
|
||||
private ISereinIOC externalIOC;
|
||||
private Action<ISereinIOC> setDefultMemberOnReset;
|
||||
private FlowWorkManagement? flowWorkManagement;
|
||||
private ISereinIOC? externalIOC;
|
||||
private Action<ISereinIOC>? setDefultMemberOnReset;
|
||||
private bool IsUseExternalIOC = false;
|
||||
private object lockObj = new object();
|
||||
private readonly object lockObj = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 如果全局触发器还在运行,则为 Running 。
|
||||
/// </summary>
|
||||
@@ -313,7 +314,7 @@ namespace Serein.NodeFlow.Env
|
||||
}*/
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC> setDefultMemberOnReset = null)
|
||||
public void UseExternalIOC(ISereinIOC ioc, Action<ISereinIOC>? setDefultMemberOnReset = null)
|
||||
{
|
||||
IOC = ioc; // 设置IOC容器
|
||||
this.setDefultMemberOnReset = setDefultMemberOnReset;
|
||||
|
||||
@@ -4,12 +4,13 @@ using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Model.Nodes;
|
||||
using Serein.NodeFlow.Model.Operation;
|
||||
using Serein.NodeFlow.Model.Operations;
|
||||
using Serein.NodeFlow.Services;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using static Serein.Library.Api.IFlowEnvironment;
|
||||
using IOperation = Serein.NodeFlow.Model.Operation.IOperation;
|
||||
using IOperation = Serein.NodeFlow.Model.Operations.IOperation;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
{
|
||||
@@ -47,7 +48,7 @@ namespace Serein.NodeFlow.Env
|
||||
private readonly FlowLibraryService flowLibraryManagement;
|
||||
private readonly FlowOperationService flowOperationService;
|
||||
private readonly FlowModelService flowModelService;
|
||||
private readonly NodeMVVMService nodeMVVMService;
|
||||
//private readonly NodeMVVMService nodeMVVMService;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -74,17 +75,23 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 从Guid获取画布
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
public bool TryGetCanvasModel(string nodeGuid, out FlowCanvasDetails canvasDetails)
|
||||
/// <param name="nodeGuid">画布Guid</param>
|
||||
/// <param name="canvasDetails">画布model</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public bool TryGetCanvasModel(string nodeGuid, [NotNullWhen(true)] out FlowCanvasDetails? canvasDetails)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
canvasDetails = null;
|
||||
canvasDetails = default;
|
||||
return false;
|
||||
}
|
||||
return flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails);
|
||||
if(flowModelService.TryGetCanvasModel(nodeGuid, out var flowCanvas))
|
||||
{
|
||||
canvasDetails = flowCanvas;
|
||||
return true;
|
||||
}
|
||||
canvasDetails = default;
|
||||
return false ;
|
||||
|
||||
}
|
||||
|
||||
@@ -92,9 +99,9 @@ namespace Serein.NodeFlow.Env
|
||||
/// 从Guid获取节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel)
|
||||
/// <param name="nodeModel">节点Model</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public bool TryGetNodeModel(string nodeGuid, [NotNullWhen(true)]out IFlowNode? nodeModel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
@@ -176,7 +183,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 创建节点
|
||||
/// </summary>
|
||||
/// <param name="nodeBase"></param>
|
||||
/// <param name="nodeModel"></param>
|
||||
private bool TryAddNode(IFlowNode nodeModel)
|
||||
{
|
||||
nodeModel.Guid ??= Guid.NewGuid().ToString();
|
||||
@@ -218,7 +225,7 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
};
|
||||
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void RemoveCanvas(string canvasGuid)
|
||||
@@ -227,7 +234,7 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
CanvasGuid = canvasGuid
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void ConnectInvokeNode(string canvasGuid, string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionInvokeType invokeType)
|
||||
@@ -244,7 +251,7 @@ namespace Serein.NodeFlow.Env
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Invoke,
|
||||
};
|
||||
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void ConnectArgSourceNode(string canvasGuid, string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionArgSourceType argSourceType, int argIndex)
|
||||
@@ -261,7 +268,7 @@ namespace Serein.NodeFlow.Env
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create,
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Arg,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void RemoveInvokeConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||
@@ -275,7 +282,7 @@ namespace Serein.NodeFlow.Env
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove,
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Invoke,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void RemoveArgSourceConnect(string canvasGuid, string fromNodeGuid, string toNodeGuid, int argIndex)
|
||||
@@ -289,10 +296,10 @@ namespace Serein.NodeFlow.Env
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Remove,
|
||||
JunctionOfConnectionType = JunctionOfConnectionType.Arg,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void CreateNode(string canvasGuid, NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null)
|
||||
public void CreateNode(string canvasGuid, NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo? methodDetailsInfo = null)
|
||||
{
|
||||
IOperation operation = new CreateNodeOperation
|
||||
{
|
||||
@@ -301,7 +308,7 @@ namespace Serein.NodeFlow.Env
|
||||
Position = position,
|
||||
MethodDetailsInfo = methodDetailsInfo
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void RemoveNode(string canvasGuid, string nodeGuid)
|
||||
@@ -311,7 +318,7 @@ namespace Serein.NodeFlow.Env
|
||||
CanvasGuid = canvasGuid,
|
||||
NodeGuid = nodeGuid
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void PlaceNodeToContainer(string canvasGuid, string nodeGuid, string containerNodeGuid)
|
||||
@@ -322,7 +329,7 @@ namespace Serein.NodeFlow.Env
|
||||
NodeGuid = nodeGuid,
|
||||
ContainerNodeGuid = containerNodeGuid
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void TakeOutNodeToContainer(string canvasGuid, string nodeGuid)
|
||||
@@ -332,36 +339,17 @@ namespace Serein.NodeFlow.Env
|
||||
CanvasGuid = canvasGuid,
|
||||
NodeGuid = nodeGuid,
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void SetStartNode(string canvasGuid, string nodeGuid)
|
||||
{
|
||||
|
||||
IOperation operation = new SetStartNodeOperation
|
||||
{
|
||||
CanvasGuid = canvasGuid,
|
||||
NewNodeGuid = nodeGuid,
|
||||
};
|
||||
_ = flowOperationService.Execute(operation);
|
||||
|
||||
return;
|
||||
if (!TryGetCanvasModel(canvasGuid, out var canvasModel) || !TryGetNodeModel(nodeGuid, out var newStartNodeModel))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var oldNodeGuid = canvasModel.StartNode?.Guid;
|
||||
/*if(TryGetNodeModel(oldNodeGuid, out var newStartNodeModel))
|
||||
{
|
||||
newStartNode.IsStart = false;
|
||||
}*/
|
||||
canvasModel.StartNode = newStartNodeModel;
|
||||
//newStartNode.IsStart = true;
|
||||
|
||||
_ = SereinEnv.TriggerEvent(() =>
|
||||
flowEnvironmentEvent.OnStartNodeChanged(
|
||||
new StartNodeChangeEventArgs(canvasGuid, oldNodeGuid, newStartNodeModel.Guid)
|
||||
));
|
||||
return;
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
@@ -376,7 +364,7 @@ namespace Serein.NodeFlow.Env
|
||||
ConnectionInvokeType = connectionType,
|
||||
ChangeType = NodeConnectChangeEventArgs.ConnectChangeType.Create
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public void ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
|
||||
@@ -387,7 +375,7 @@ namespace Serein.NodeFlow.Env
|
||||
IsAdd = isAdd,
|
||||
ParamIndex = paramIndex
|
||||
};
|
||||
flowOperationService.Execute(operation);
|
||||
_ = flowOperationService.Execute(operation);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -170,7 +170,6 @@ namespace Serein.NodeFlow.Env
|
||||
return (isConnect, remoteMsgUtil);
|
||||
}*/
|
||||
|
||||
/// <inheritdoc/>
|
||||
/* public async Task<bool> ExitFlowAsync()
|
||||
{
|
||||
return await currentFlowEnvironment.FlowControl.ExitFlowAsync();
|
||||
@@ -190,9 +189,9 @@ namespace Serein.NodeFlow.Env
|
||||
}*/
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SereinProjectData> GetProjectInfoAsync()
|
||||
public SereinProjectData GetProjectInfoAsync()
|
||||
{
|
||||
return await currentFlowEnvironment.GetProjectInfoAsync();
|
||||
return currentFlowEnvironment.GetProjectInfoAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -3,112 +3,150 @@ using Serein.Library.Api;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程环境事件类
|
||||
/// </summary>
|
||||
public class FlowEnvironmentEvent : IFlowEnvironmentEvent
|
||||
{
|
||||
public event LoadDllHandler DllLoad;
|
||||
public event ProjectLoadedHandler ProjectLoaded;
|
||||
public event ProjectSavingHandler ProjectSaving;
|
||||
public event NodeConnectChangeHandler NodeConnectChanged;
|
||||
public event CanvasCreateHandler CanvasCreated;
|
||||
public event CanvasRemoveHandler CanvasRemoved;
|
||||
public event NodeCreateHandler NodeCreated;
|
||||
public event NodeRemoveHandler NodeRemoved;
|
||||
public event NodePlaceHandler NodePlace;
|
||||
public event NodeTakeOutHandler NodeTakeOut;
|
||||
public event StartNodeChangeHandler StartNodeChanged;
|
||||
public event FlowRunCompleteHandler FlowRunComplete;
|
||||
public event MonitorObjectChangeHandler MonitorObjectChanged;
|
||||
public event NodeInterruptStateChangeHandler NodeInterruptStateChanged;
|
||||
public event ExpInterruptTriggerHandler InterruptTriggered;
|
||||
public event IOCMembersChangedHandler IOCMembersChanged;
|
||||
public event NodeLocatedHandler NodeLocated;
|
||||
public event EnvOutHandler EnvOutput;
|
||||
/// <inheritdoc/>
|
||||
public event LoadDllHandler? DllLoad;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectLoadedHandler? ProjectLoaded;
|
||||
/// <inheritdoc/>
|
||||
public event ProjectSavingHandler? ProjectSaving;
|
||||
/// <inheritdoc/>
|
||||
public event NodeConnectChangeHandler? NodeConnectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasCreateHandler? CanvasCreated;
|
||||
/// <inheritdoc/>
|
||||
public event CanvasRemoveHandler? CanvasRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodeCreateHandler? NodeCreated;
|
||||
/// <inheritdoc/>
|
||||
public event NodeRemoveHandler? NodeRemoved;
|
||||
/// <inheritdoc/>
|
||||
public event NodePlaceHandler? NodePlace;
|
||||
/// <inheritdoc/>
|
||||
public event NodeTakeOutHandler? NodeTakeOut;
|
||||
/// <inheritdoc/>
|
||||
public event StartNodeChangeHandler? StartNodeChanged;
|
||||
/// <inheritdoc/>
|
||||
public event FlowRunCompleteHandler? FlowRunComplete;
|
||||
/// <inheritdoc/>
|
||||
public event MonitorObjectChangeHandler? MonitorObjectChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeInterruptStateChangeHandler? NodeInterruptStateChanged;
|
||||
/// <inheritdoc/>
|
||||
public event ExpInterruptTriggerHandler? InterruptTriggered;
|
||||
/// <inheritdoc/>
|
||||
public event IOCMembersChangedHandler? IOCMembersChanged;
|
||||
/// <inheritdoc/>
|
||||
public event NodeLocatedHandler? NodeLocated;
|
||||
/// <inheritdoc/>
|
||||
public event EnvOutHandler? EnvOutput;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnDllLoad(LoadDllEventArgs eventArgs)
|
||||
{
|
||||
DllLoad?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
|
||||
{
|
||||
ProjectLoaded?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnProjectSaving(ProjectSavingEventArgs eventArgs)
|
||||
{
|
||||
ProjectSaving?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeConnectChanged(NodeConnectChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeConnectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasCreated(CanvasCreateEventArgs eventArgs)
|
||||
{
|
||||
CanvasCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCanvasRemoved(CanvasRemoveEventArgs eventArgs)
|
||||
{
|
||||
CanvasRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeCreated(NodeCreateEventArgs eventArgs)
|
||||
{
|
||||
NodeCreated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeRemoved(NodeRemoveEventArgs eventArgs)
|
||||
{
|
||||
NodeRemoved?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodePlace(NodePlaceEventArgs eventArgs)
|
||||
{
|
||||
NodePlace?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeTakeOut(NodeTakeOutEventArgs eventArgs)
|
||||
{
|
||||
NodeTakeOut?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnStartNodeChanged(StartNodeChangeEventArgs eventArgs)
|
||||
{
|
||||
StartNodeChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnFlowRunComplete(FlowEventArgs eventArgs)
|
||||
{
|
||||
FlowRunComplete?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnMonitorObjectChanged(MonitorObjectEventArgs eventArgs)
|
||||
{
|
||||
MonitorObjectChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeInterruptStateChanged(NodeInterruptStateChangeEventArgs eventArgs)
|
||||
{
|
||||
NodeInterruptStateChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnInterruptTriggered(InterruptTriggerEventArgs eventArgs)
|
||||
{
|
||||
InterruptTriggered?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs)
|
||||
{
|
||||
IOCMembersChanged?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnNodeLocated(NodeLocatedEventArgs eventArgs)
|
||||
{
|
||||
NodeLocated?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnEnvOutput(InfoType type, string value)
|
||||
{
|
||||
EnvOutput?.Invoke(type, value);
|
||||
|
||||
@@ -5,6 +5,7 @@ using Serein.NodeFlow.Model.Nodes;
|
||||
using Serein.NodeFlow.Services;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
@@ -64,7 +65,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// 打开远程管理
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
public async Task StartRemoteServerAsync(int port = 7525)
|
||||
public void StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
/*if (clientMsgManage is null)
|
||||
{
|
||||
@@ -116,7 +117,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// UI线程操作类
|
||||
/// </summary>
|
||||
public UIContextOperation UIContextOperation { get; private set; }
|
||||
public UIContextOperation? UIContextOperation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 节点MVVM管理服务
|
||||
@@ -173,15 +174,10 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
#region 私有变量
|
||||
|
||||
/// <summary>
|
||||
/// 装饰器运行环境类
|
||||
/// </summary>
|
||||
private readonly IFlowEnvironment mainFlowEnvironment;
|
||||
|
||||
/// <summary>
|
||||
/// 流程运行时的IOC容器
|
||||
/// </summary>
|
||||
private ISereinIOC flowRunIOC;
|
||||
private ISereinIOC? flowRunIOC;
|
||||
|
||||
/// <summary>
|
||||
/// local环境的IOC容器,主要用于注册本地环境的服务
|
||||
@@ -203,28 +199,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
private readonly FlowModelService _flowModelService;
|
||||
|
||||
/* /// <summary>
|
||||
/// 环境加载的节点集合
|
||||
/// Node Guid - Node Model
|
||||
/// </summary>
|
||||
private Dictionary<string, IFlowNode> NodeModels { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境加载的画布集合
|
||||
/// </summary>
|
||||
private Dictionary<string, FlowCanvasDetails> FlowCanvass { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 存放触发器节点(运行时全部调用)
|
||||
/// </summary>
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程任务管理
|
||||
/// </summary>
|
||||
private FlowWorkManagement? flowTaskManagement;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -247,34 +222,15 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前环境信息(远程连接)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
// 获取所有的程序集对应的方法信息(程序集相关的数据)
|
||||
var libraryMdss = this._flowLibraryService.GetAllLibraryMds().ToArray();
|
||||
// 获取当前项目的信息(节点相关的数据)
|
||||
var project = await GetProjectInfoAsync(); // 远程连接获取远程环境项目信息
|
||||
SereinEnv.WriteLine(InfoType.INFO, "已将当前环境信息发送到远程客户端");
|
||||
return new FlowEnvInfo
|
||||
{
|
||||
Project = project, // 项目信息
|
||||
LibraryMds = libraryMdss, // 环境方法
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 保存项目
|
||||
/// </summary>
|
||||
public void SaveProject()
|
||||
{
|
||||
var project = GetProjectInfoAsync();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var project = await GetProjectInfoAsync();
|
||||
|
||||
await SereinEnv.TriggerEvent(() =>
|
||||
{
|
||||
Event.OnProjectSaving(new ProjectSavingEventArgs(project));
|
||||
@@ -316,8 +272,6 @@ namespace Serein.NodeFlow.Env
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
// 加载画布
|
||||
try
|
||||
{
|
||||
foreach (var canvasInfo in projectData.Canvass)
|
||||
{
|
||||
await LoadCanvasAsync(canvasInfo);
|
||||
@@ -331,12 +285,6 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
|
||||
Event.OnProjectLoaded(new ProjectLoadedEventArgs());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -382,56 +330,11 @@ namespace Serein.NodeFlow.Env
|
||||
Event.OnProjectLoaded(new ProjectLoadedEventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载远程环境
|
||||
/// </summary>
|
||||
/// <param name="addres">远程环境地址</param>
|
||||
/// <param name="port">远程环境端口</param>
|
||||
/// <param name="token">密码</param>
|
||||
/*public async Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
|
||||
{
|
||||
throw new NotImplementedException("远程环境未实现的方法 ConnectRemoteEnv");
|
||||
*//*if (IsControlRemoteEnv)
|
||||
{
|
||||
await Console.Out.WriteLineAsync($"当前已经连接远程环境");
|
||||
return (false, null);
|
||||
}
|
||||
// 没有连接远程环境,可以重新连接
|
||||
|
||||
var controlConfiguration = new RemoteMsgUtil.ControlConfiguration
|
||||
{
|
||||
Addres = addres,
|
||||
Port = port,
|
||||
Token = token,
|
||||
*//*ThemeJsonKey = LocalFlowEnvironment.ThemeKey,
|
||||
MsgIdJsonKey = LocalFlowEnvironment.MsgIdKey,
|
||||
DataJsonKey = LocalFlowEnvironment.DataKey,*//*
|
||||
};
|
||||
var remoteMsgUtil = new RemoteMsgUtil(controlConfiguration);
|
||||
var result = await remoteMsgUtil.ConnectAsync();
|
||||
if (!result)
|
||||
{
|
||||
await Console.Out.WriteLineAsync("连接失败,请检查地址与端口是否正确");
|
||||
return (false, null);
|
||||
}
|
||||
await Console.Out.WriteLineAsync("连接成功,开始验证Token");
|
||||
IsControlRemoteEnv = true;
|
||||
return (true, remoteMsgUtil);*//*
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// 退出远程环境
|
||||
/// </summary>
|
||||
public void ExitRemoteEnv()
|
||||
{
|
||||
IsControlRemoteEnv = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化当前项目的依赖信息、节点信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<SereinProjectData> GetProjectInfoAsync()
|
||||
public SereinProjectData GetProjectInfoAsync()
|
||||
{
|
||||
var projectData = new SereinProjectData()
|
||||
{
|
||||
@@ -466,28 +369,6 @@ namespace Serein.NodeFlow.Env
|
||||
}
|
||||
}
|
||||
|
||||
/* /// <summary>
|
||||
/// 加载本地程序集
|
||||
/// </summary>
|
||||
/// <param name="flowLibrary"></param>
|
||||
public void LoadLibrary(FlowLibraryCache flowLibrary)
|
||||
{
|
||||
try
|
||||
{
|
||||
libraryInfo = FlowLibraryService.LoadFlowLibrary(flowLibrary);
|
||||
if (mdInfos.Count > 0)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"无法加载DLL文件:{ex.Message}");
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 移除DLL
|
||||
/// </summary>
|
||||
@@ -572,9 +453,6 @@ namespace Serein.NodeFlow.Env
|
||||
//}
|
||||
}
|
||||
|
||||
private int _addCanvasCount = 0;
|
||||
|
||||
|
||||
private async Task<FlowCanvasDetails> LoadCanvasAsync(FlowCanvasDetailsInfo info)
|
||||
{
|
||||
var model = new FlowCanvasDetails(this);
|
||||
@@ -623,6 +501,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <para>异步方法:Func<object,object[],Task></para>
|
||||
/// <para>异步有返回值方法:Func<object,object[],Task<object>></para>
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="delegateDetails"></param>
|
||||
/// <returns></returns>
|
||||
@@ -711,10 +590,11 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 从Guid获取画布
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <param name="nodeGuid">画布Guid</param>
|
||||
/// <param name="canvasDetails">画布实体</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
public bool TryGetCanvasModel(string nodeGuid, out FlowCanvasDetails canvasDetails)
|
||||
public bool TryGetCanvasModel(string nodeGuid,[NotNullWhen(true)] out FlowCanvasDetails? canvasDetails)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
@@ -729,9 +609,10 @@ namespace Serein.NodeFlow.Env
|
||||
/// 从Guid获取节点
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点Guid</param>
|
||||
/// <param name="nodeModel">节点Guid</param>
|
||||
/// <returns>节点Model</returns>
|
||||
/// <exception cref="ArgumentNullException">无法获取节点、Guid/节点为null时报错</exception>
|
||||
public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel)
|
||||
public bool TryGetNodeModel(string nodeGuid, [NotNullWhen(true)] out IFlowNode? nodeModel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(nodeGuid))
|
||||
{
|
||||
|
||||
@@ -158,10 +158,11 @@ namespace Serein.NodeFlow
|
||||
/// <param name="sb">字符串构建器</param>
|
||||
/// <param name="retractCount">缩进次数(4个空格)</param>
|
||||
/// <param name="code">要添加的代码</param>
|
||||
/// <param name="isWrapping">是否换行</param>
|
||||
/// <returns>字符串构建器本身</returns>
|
||||
public static StringBuilder AppendCode(this StringBuilder sb,
|
||||
int retractCount = 0,
|
||||
string code = null,
|
||||
string? code = null,
|
||||
bool isWrapping = true)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(code))
|
||||
|
||||
@@ -4,6 +4,9 @@ using Serein.Library.Api;
|
||||
namespace Serein.NodeFlow
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 流程任务类,包含流程的起始节点和所有节点信息。
|
||||
/// </summary>
|
||||
public class FlowTask
|
||||
{
|
||||
/// <summary>
|
||||
@@ -14,12 +17,12 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 流程起始节点
|
||||
/// </summary>
|
||||
public Func<IFlowNode> GetStartNode { get; set; }
|
||||
public Func<IFlowNode>? GetStartNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前画布流程的所有节点
|
||||
/// </summary>
|
||||
public Func<List<IFlowNode>> GetNodes { get; set; }
|
||||
public Func<List<IFlowNode>>? GetNodes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -30,11 +33,11 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 流程IOC容器
|
||||
/// </summary>
|
||||
public ISereinIOC FlowIOC { get; set; }
|
||||
public required ISereinIOC FlowIOC { get; set; }
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
/// </summary>
|
||||
public IFlowEnvironment Environment { get; set; }// = environment;
|
||||
public required IFlowEnvironment Environment { get; set; }// = environment;
|
||||
|
||||
/// <summary>
|
||||
/// 表示运行环境状态
|
||||
@@ -44,35 +47,30 @@ namespace Serein.NodeFlow
|
||||
/// <summary>
|
||||
/// 上下文线程池
|
||||
/// </summary>
|
||||
public Serein.Library.Utils.ObjectPool<IFlowContext> FlowContextPool { get; set; }
|
||||
public required Serein.Library.Utils.ObjectPool<IFlowContext> FlowContextPool { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个画布需要启用的节点
|
||||
/// </summary>
|
||||
public Dictionary<string, FlowTask> Flows { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务加载的所有节点
|
||||
/// </summary>
|
||||
//public List<NodeModelBase> Nodes { get; set; }// = nodes;
|
||||
public Dictionary<string, FlowTask> Flows { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 需要注册的类型
|
||||
/// </summary>
|
||||
public Dictionary<RegisterSequence, List<Type>> AutoRegisterTypes { get; set; } //= autoRegisterTypes;
|
||||
public Dictionary<RegisterSequence, List<Type>> AutoRegisterTypes { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 初始化时需要的方法
|
||||
/// </summary>
|
||||
public List<MethodDetails> InitMds { get; set; }// = initMds;
|
||||
public List<MethodDetails> InitMds { get; set; } = [];
|
||||
/// <summary>
|
||||
/// 加载时需要的方法
|
||||
/// </summary>
|
||||
public List<MethodDetails> LoadMds { get; set; }// = loadMds;
|
||||
public List<MethodDetails> LoadMds { get; set; } = [];
|
||||
/// <summary>
|
||||
/// 退出时需要调用的方法
|
||||
/// </summary>
|
||||
public List<MethodDetails> ExitMds { get; set; } //= exitMds;
|
||||
public List<MethodDetails> ExitMds { get; set; } = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Serein.NodeFlow.Model.Library
|
||||
// 从 scanTypes.Type 创建的方法信息
|
||||
// Md : 方法描述
|
||||
// Dd :方法对应的Emit委托
|
||||
List<LibraryMdDd> detailss = new List<LibraryMdDd>();
|
||||
List<LibraryMthodInfo> detailss = new List<LibraryMthodInfo>();
|
||||
|
||||
// 遍历扫描的类型
|
||||
foreach ((var type, var flowName) in scanTypes)
|
||||
@@ -159,7 +159,7 @@ namespace Serein.NodeFlow.Model.Library
|
||||
continue;
|
||||
}
|
||||
md.MethodAnotherName = flowName + md.MethodAnotherName; // 方法别名
|
||||
detailss.Add(new LibraryMdDd(mi, md, dd));
|
||||
detailss.Add(new LibraryMthodInfo(mi, md, dd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using Serein.Library;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Library
|
||||
{
|
||||
public class LibraryMdDd
|
||||
{
|
||||
public MethodDetails MethodDetails { get; }
|
||||
public MethodInfo MethodInfo { get; }
|
||||
public DelegateDetails DelegateDetails { get; }
|
||||
|
||||
public LibraryMdDd(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails)
|
||||
{
|
||||
MethodDetails = methodDetails;
|
||||
MethodInfo = methodInfo;
|
||||
DelegateDetails = delegateDetails;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
39
NodeFlow/Model/Librarys/LibraryMthodInfo.cs
Normal file
39
NodeFlow/Model/Librarys/LibraryMthodInfo.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Serein.Library;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// 库方法信息类,包含方法的详细信息、反射信息和委托信息。
|
||||
/// </summary>
|
||||
public class LibraryMthodInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 方法的详细信息。
|
||||
/// </summary>
|
||||
public MethodDetails MethodDetails { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 方法的反射信息,包含方法名称、参数类型等。
|
||||
/// </summary>
|
||||
public MethodInfo MethodInfo { get; }
|
||||
/// <summary>
|
||||
/// Emit构造委托
|
||||
/// </summary>
|
||||
public DelegateDetails DelegateDetails { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的库方法信息实例。
|
||||
/// </summary>
|
||||
/// <param name="methodInfo"></param>
|
||||
/// <param name="methodDetails"></param>
|
||||
/// <param name="delegateDetails"></param>
|
||||
public LibraryMthodInfo(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails)
|
||||
{
|
||||
MethodDetails = methodDetails;
|
||||
MethodInfo = methodInfo;
|
||||
DelegateDetails = delegateDetails;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -140,7 +140,6 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// 从节点信息加载节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
/// <param name="canvas"></param>
|
||||
/// <param name="nodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
public static void LoadInfo(this IFlowNode nodeModel, NodeInfo nodeInfo)
|
||||
@@ -243,97 +242,6 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查监视表达式是否生效
|
||||
/// </summary>
|
||||
/// <param name="nodeModel">节点Moel</param>
|
||||
/// <param name="context">上下文</param>
|
||||
/// <param name="newData">新的数据</param>
|
||||
/// <returns></returns>
|
||||
/*public static async Task CheckExpInterrupt(this NodeModelBase nodeModel, IDynamicContext context, object newData = null)
|
||||
{
|
||||
string guid = nodeModel.Guid;
|
||||
context.AddOrUpdate(guid, newData); // 上下文中更新数据
|
||||
if (newData is null)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
await nodeModel.MonitorObjExpInterrupt(context, newData, 0); // 首先监视对象
|
||||
await nodeModel.MonitorObjExpInterrupt(context, newData, 1); // 然后监视节点
|
||||
//nodeModel.FlowData = newData; // 替换数据
|
||||
}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// 监视对象表达式中断
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="monitorType"></param>
|
||||
/// <returns></returns>
|
||||
/*private static async Task MonitorObjExpInterrupt(this NodeModelBase nodeModel, IDynamicContext context, object data, int monitorType)
|
||||
{
|
||||
MonitorObjectEventArgs.ObjSourceType sourceType;
|
||||
string key;
|
||||
if (monitorType == 0)
|
||||
{
|
||||
key = data?.GetType()?.FullName;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = nodeModel.Guid;
|
||||
sourceType = MonitorObjectEventArgs.ObjSourceType.IOCObj;
|
||||
}
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
return;
|
||||
}
|
||||
//(var isMonitor, var exps) = await context.Env.CheckObjMonitorStateAsync(key);
|
||||
//if (isMonitor) // 如果新的数据处于查看状态,通知UI进行更新?交给运行环境判断?
|
||||
//{
|
||||
// context.Env.MonitorObjectNotification(nodeModel.Guid, data, sourceType); // 对象处于监视状态,通知UI更新数据显示
|
||||
// if (exps.Length > 0)
|
||||
// {
|
||||
// // 表达式环境下判断是否需要执行中断
|
||||
// bool isExpInterrupt = false;
|
||||
// string exp = "";
|
||||
// // 判断执行监视表达式,直到为 true 时退出
|
||||
// for (int i = 0; i < exps.Length && !isExpInterrupt; i++)
|
||||
// {
|
||||
// exp = exps[i];
|
||||
// if (string.IsNullOrEmpty(exp)) continue;
|
||||
// // isExpInterrupt = SereinConditionParser.To(data, exp);
|
||||
// }
|
||||
|
||||
// if (isExpInterrupt) // 触发中断
|
||||
// {
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
}*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 不再中断
|
||||
/// </summary>
|
||||
public static void CancelInterrupt(IFlowNode nodeModel)
|
||||
{
|
||||
nodeModel.DebugSetting.IsInterrupt = false;
|
||||
nodeModel.DebugSetting.CancelInterrupt?.Invoke();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// 程序集更新,更新节点方法描述、以及所有入参描述的类型
|
||||
@@ -13,49 +13,49 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <summary>
|
||||
/// 节点基类(数据)
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node)]
|
||||
public abstract partial class NodeModelBase : IFlowNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点运行环境
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private IFlowEnvironment _env;
|
||||
|
||||
/// <summary>
|
||||
/// 标识节点对象全局唯一
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private string _guid;
|
||||
|
||||
/// <summary>
|
||||
/// 描述节点对应的控件类型
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private NodeControlType _controlType;
|
||||
|
||||
/// <summary>
|
||||
/// 所属画布
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private FlowCanvasDetails _canvasDetails ;
|
||||
|
||||
/// <summary>
|
||||
/// 在画布中的位置
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private PositionOfUI _position ;
|
||||
|
||||
/// <summary>
|
||||
/// 显示名称
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private string _displayName;
|
||||
|
||||
/// <summary>
|
||||
/// 是否公开
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isPublic;
|
||||
|
||||
/* /// <summary>
|
||||
@@ -67,13 +67,13 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <summary>
|
||||
/// 附加的调试功能
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[DataInfo(IsProtection = true)]
|
||||
private NodeDebugSetting _debugSetting ;
|
||||
|
||||
/// <summary>
|
||||
/// 方法描述。包含参数信息。不包含Method与委托,如若需要调用对应的方法,需要通过MethodName从环境中获取委托进行调用。
|
||||
/// </summary>
|
||||
[PropertyInfo]
|
||||
[DataInfo]
|
||||
private MethodDetails _methodDetails ;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public virtual int MaxChildrenCount { get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个节点模型的基类实例
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public NodeModelBase(IFlowEnvironment environment)
|
||||
{
|
||||
PreviousNodes = new Dictionary<ConnectionInvokeType, List<IFlowNode>>();
|
||||
@@ -47,7 +47,6 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
/// <param name="context">流程上下文</param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="args">自定义参数</param>
|
||||
/// <returns>节点传回数据对象</returns>
|
||||
public virtual async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
@@ -9,6 +9,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public class SingleActionNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的单动作节点实例。
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleActionNode(IFlowEnvironment environment):base(environment)
|
||||
{
|
||||
|
||||
@@ -9,25 +9,25 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <summary>
|
||||
/// 条件节点(用于条件控件)
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleConditionNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否为自定义参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isExplicitData;
|
||||
|
||||
/// <summary>
|
||||
/// 自定义参数值
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string? _explicitData;
|
||||
|
||||
/// <summary>
|
||||
/// 条件表达式
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _expression;
|
||||
|
||||
}
|
||||
@@ -44,7 +44,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
private const int INDEX_EXPRESSION = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 条件节点构造函数
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleConditionNode(IFlowEnvironment environment):base(environment)
|
||||
{
|
||||
this.IsExplicitData = false;
|
||||
@@ -52,6 +55,9 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
this.Expression = "PASS";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建节点时调用的方法
|
||||
/// </summary>
|
||||
public override void OnCreating()
|
||||
{
|
||||
// 这里的这个参数是为了方便使用入参控制点,参数无意义
|
||||
@@ -106,6 +112,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// 重写节点的方法执行
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
@@ -8,19 +8,21 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <summary>
|
||||
/// Expression Operation - 表达式操作
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleExpOpNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 表达式
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _expression;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 表达式节点模型基类
|
||||
/// </summary>
|
||||
public partial class SingleExpOpNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,6 +35,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
private const int INDEX_EXPRESSION = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 表达式节点构造函数
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleExpOpNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
|
||||
@@ -87,7 +93,12 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
this.Expression = nodeInfo.CustomData?.Expression ?? "";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 执行节点操作
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
if(token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");
|
||||
@@ -10,7 +10,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public class SingleFlipflopNode : NodeModelBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的单触发器节点实例。
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleFlipflopNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
|
||||
@@ -21,6 +24,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// 执行触发器进行等待触发
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
@@ -7,26 +7,26 @@ using System.Reflection;
|
||||
namespace Serein.NodeFlow.Model.Nodes
|
||||
{
|
||||
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleFlowCallNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标公开节点
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string targetNodeGuid;
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string targetNodeGuid = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 使用目标节点的参数(如果为true,则使用目标节点的入参,如果为false,则使用节点自定义入参)
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private bool _isShareParam ;
|
||||
|
||||
/// <summary>
|
||||
/// 接口全局名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _apiGlobalName;
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _apiGlobalName = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public MethodDetails CacheMethodDetails { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 流程接口节点
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleFlowCallNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
|
||||
@@ -207,7 +211,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
}
|
||||
|
||||
private static Dictionary<string, int> ApiInvokeNameCache = new Dictionary<string, int>();
|
||||
public static int getApiInvokeNameCount = 0;
|
||||
private static int getApiInvokeNameCount = 0;
|
||||
private static string GetApiInvokeName(SingleFlowCallNode node, string apiName)
|
||||
{
|
||||
if (ApiInvokeNameCache.ContainsKey(apiName))
|
||||
@@ -223,6 +227,12 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
return $"{apiName}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取流程接口节点的名称
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetApiInvokeName(SingleFlowCallNode node)
|
||||
{
|
||||
if(node.TargetNode is null)
|
||||
@@ -9,13 +9,13 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <summary>
|
||||
/// Expression Operation - 表达式操作
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleGlobalDataNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局数据的Key名称
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _keyName;
|
||||
|
||||
}
|
||||
@@ -36,6 +36,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public override int MaxChildrenCount => 1;
|
||||
|
||||
/// <summary>
|
||||
/// 全局数据节点,允许放置一个数据源节点,通常是[Action]或[Script]节点,用于获取全局数据。
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleGlobalDataNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
}
|
||||
@@ -85,7 +89,11 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从容器中取出节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
/// <returns></returns>
|
||||
public bool TakeOutNode(IFlowNode nodeModel)
|
||||
{
|
||||
if (ChildrenNode.Contains(nodeModel))
|
||||
@@ -102,7 +110,10 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
|
||||
}
|
||||
|
||||
public async void TakeOutAll()
|
||||
/// <summary>
|
||||
/// 从容器中取出所有节点
|
||||
/// </summary>
|
||||
public void TakeOutAll()
|
||||
{
|
||||
foreach (var nodeModel in ChildrenNode)
|
||||
{
|
||||
@@ -117,6 +128,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// 设置全局数据
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
@@ -10,27 +10,30 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// 单脚本节点(用于脚本控件)
|
||||
/// </summary>
|
||||
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleNetScriptNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 脚本代码
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _script;
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _script = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 功能提示
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _tips = "写一下提示吧";
|
||||
|
||||
/// <summary>
|
||||
/// 依赖路径
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private List<string> _libraryFilePaths;
|
||||
[DataInfo(IsNotification = true)]
|
||||
private List<string> _libraryFilePaths = [];
|
||||
|
||||
}
|
||||
|
||||
@@ -41,46 +44,16 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// </summary>
|
||||
public override bool IsBase => true;
|
||||
|
||||
/// <summary>
|
||||
/// 脚本代码
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleNetScriptNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
this.Env = environment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public override void OnCreating()
|
||||
{
|
||||
//MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi));
|
||||
//if (method != null)
|
||||
//{
|
||||
// ScriptInterpreter.AddFunction(nameof(GetFlowApi), method, () => this); // 挂载获取流程接口
|
||||
//}
|
||||
|
||||
//var md = MethodDetails;
|
||||
//var pd = md.ParameterDetailss ??= new ParameterDetails[1];
|
||||
//md.ParamsArgIndex = 0;
|
||||
//pd[0] = new ParameterDetails
|
||||
//{
|
||||
// Index = 0,
|
||||
// Name = "object",
|
||||
// IsExplicitData = true,
|
||||
// DataValue = string.Empty,
|
||||
// DataType = typeof(object),
|
||||
// ExplicitType = typeof(object),
|
||||
// ArgDataSourceNodeGuid = string.Empty,
|
||||
// ArgDataSourceType = ConnectionArgSourceType.GetPreviousNodeData,
|
||||
// NodeModel = this,
|
||||
// InputType = ParameterValueInputType.Input,
|
||||
// Items = null,
|
||||
// IsParams = true,
|
||||
// Description = "脚本节点入参"
|
||||
|
||||
//};
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出脚本代码
|
||||
/// </summary>
|
||||
@@ -18,11 +18,11 @@ using System.Xml.Linq;
|
||||
namespace Serein.NodeFlow.Model.Nodes
|
||||
{
|
||||
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
[FlowDataProperty(ValuePath = NodeValuePath.Node, IsNodeImp = true)]
|
||||
public partial class SingleScriptNode : NodeModelBase
|
||||
{
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _script;
|
||||
[DataInfo(IsNotification = true)]
|
||||
private string _script = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -293,6 +293,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// 执行脚本
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
@@ -8,13 +8,30 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Nodes
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个UI节点,适用于需要在流程中嵌入用户自定义控件的场景。
|
||||
/// </summary>
|
||||
public class SingleUINode : NodeModelBase
|
||||
{
|
||||
public IEmbeddedContent Adapter { get; private set; }
|
||||
/// <summary>
|
||||
/// 适配的UI控件,必须实现IEmbeddedContent接口。
|
||||
/// </summary>
|
||||
public IEmbeddedContent? Adapter { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单个UI节点构造函数,初始化流程环境。
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
public SingleUINode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行节点逻辑,适用于嵌入式UI控件的流程节点。
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");
|
||||
@@ -11,7 +11,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Serein.Library.Api.NodeConnectChangeEventArgs;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点连接状态发生改变
|
||||
@@ -45,6 +45,7 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// </summary>
|
||||
public JunctionType ToNodeJunctionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连接类型
|
||||
/// </summary>
|
||||
public ConnectionInvokeType ConnectionInvokeType { get; set; }
|
||||
@@ -69,9 +70,9 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
public override bool IsCanUndo => false;
|
||||
|
||||
#region 私有参数
|
||||
private FlowCanvasDetails FlowCanvas;
|
||||
private IFlowNode FromNode;
|
||||
private IFlowNode ToNode;
|
||||
private FlowCanvasDetails? FlowCanvas;
|
||||
private IFlowNode? FromNode;
|
||||
private IFlowNode? ToNode;
|
||||
#endregion
|
||||
|
||||
public override bool ValidationParameter()
|
||||
@@ -155,6 +156,9 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// </summary>
|
||||
private async Task<bool> CreateInvokeConnection()
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(FlowCanvas);
|
||||
ArgumentNullException.ThrowIfNull(FromNode);
|
||||
ArgumentNullException.ThrowIfNull(ToNode);
|
||||
IFlowNode fromNode = FromNode;
|
||||
IFlowNode toNode = ToNode;
|
||||
ConnectionInvokeType invokeType = ConnectionInvokeType;
|
||||
@@ -340,6 +344,10 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// </summary>
|
||||
private async Task<bool> RemoveInvokeConnection()
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(FlowCanvas);
|
||||
ArgumentNullException.ThrowIfNull(FromNode);
|
||||
ArgumentNullException.ThrowIfNull(ToNode);
|
||||
|
||||
FromNode.SuccessorNodes[ConnectionInvokeType].Remove(ToNode);
|
||||
ToNode.PreviousNodes[ConnectionInvokeType].Remove(FromNode);
|
||||
|
||||
@@ -383,7 +391,12 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// </summary>
|
||||
/// <exception cref="Exception"></exception>
|
||||
private async Task<bool> CreateArgConnection()
|
||||
{/*
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(FlowCanvas);
|
||||
ArgumentNullException.ThrowIfNull(FromNode);
|
||||
ArgumentNullException.ThrowIfNull(ToNode);
|
||||
|
||||
/*
|
||||
IFlowNode fromNodeControl = ToNode;
|
||||
IFlowNode toNodeControl = ToNode;*/
|
||||
ConnectionArgSourceType type = ConnectionArgSourceType;
|
||||
@@ -520,11 +533,12 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// <summary>
|
||||
/// 移除参数连接关系
|
||||
/// </summary>
|
||||
/// <param name="fromNodeControl"></param>
|
||||
/// <param name="toNodeControl"></param>
|
||||
/// <param name="index"></param>
|
||||
private async Task<bool> RemoveArgConnection()
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(FlowCanvas);
|
||||
ArgumentNullException.ThrowIfNull(FromNode);
|
||||
ArgumentNullException.ThrowIfNull(ToNode);
|
||||
|
||||
if (ToNode.MethodDetails.ParameterDetailss is null) return false;
|
||||
var type = ToNode.MethodDetails.ParameterDetailss[ArgIndex].ArgDataSourceType;
|
||||
FromNode.NeedResultNodes[type].Remove(ToNode);
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal class ChangeParameterOperation : OperationBase
|
||||
{
|
||||
@@ -9,7 +9,7 @@ using System.Net.Mime;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
/// <summary>
|
||||
/// 放置节点操作
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal class CreateCanvasOperation : OperationBase
|
||||
{
|
||||
@@ -9,7 +9,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal class CreateNodeOperation : OperationBase
|
||||
{
|
||||
@@ -9,7 +9,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal interface IOperation
|
||||
{
|
||||
@@ -64,6 +64,7 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
[AutoInjection]
|
||||
protected IFlowEnvironmentEvent flowEnvironmentEvent;
|
||||
|
||||
|
||||
public abstract string Theme { get;}
|
||||
|
||||
/// <summary>
|
||||
@@ -7,7 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal class RemoveCanvasOperation : OperationBase
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
using Serein.Library.Api;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
internal class RemoveNodeOperation : OperationBase
|
||||
{
|
||||
@@ -15,6 +15,7 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
/// 节点所在画布
|
||||
/// </summary>
|
||||
private FlowCanvasDetails flowCanvasDetails;
|
||||
|
||||
/// <summary>
|
||||
/// 被删除的节点
|
||||
/// </summary>
|
||||
@@ -46,9 +47,19 @@ namespace Serein.NodeFlow.Model.Operation
|
||||
{
|
||||
if (!ValidationParameter()) return false;
|
||||
|
||||
// 需要移除对应的方法调用、以及参数获取调用
|
||||
// 需要移除对应的方法调用、参数获取调用以及子节点信息
|
||||
// 还需要记录移除的事件参数,用以撤销恢复
|
||||
|
||||
if (flowNode.ChildrenNode.Count > 0)
|
||||
{
|
||||
// 如果该节点存在子节点,则删除所有子节点
|
||||
foreach(var child in flowNode.ChildrenNode)
|
||||
{
|
||||
flowEnvironment.FlowEdit.RemoveNode(CanvasGuid, child.Guid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region 移除方法调用关系
|
||||
|
||||
// 检查该节点的前继节点,然后从这些前继节点中移除与该节点的连接关系
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model.Operation
|
||||
namespace Serein.NodeFlow.Model.Operations
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置起始节点
|
||||
@@ -42,22 +42,11 @@ namespace Serein.NodeFlow
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
//public object? GetArgData(IDynamicContext context, int index)
|
||||
//{
|
||||
// var _paramsKey = $"{context?.Guid}_{NodeModel.Guid}_Params";
|
||||
// var obj = context?.GetFlowData(_paramsKey);
|
||||
// if (obj is object[] @params && index < @params.Length)
|
||||
// {
|
||||
// return @params[index];
|
||||
// }
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public object? GetFlowData(IDynamicContext context)
|
||||
//{
|
||||
// return context?.GetFlowData(NodeModel.Guid);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 获取全局数据
|
||||
/// </summary>
|
||||
/// <param name="keyName"></param>
|
||||
/// <returns></returns>
|
||||
public object? GetGlobalData(string keyName)
|
||||
{
|
||||
return SereinEnv.GetFlowGlobalData(keyName);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.2.2</Version>
|
||||
<Version>1.2.3</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -54,6 +54,7 @@
|
||||
<Compile Remove="Tool\ExpressionHelper.cs" />
|
||||
<Compile Remove="Tool\FlowLibraryAssemblyContext2.cs" />
|
||||
<Compile Remove="Tool\NodeModelBaseFunc.cs" />
|
||||
<Compile Remove="Tool\ObjDynamicCreateHelper.cs" />
|
||||
<Compile Remove="Tool\TcsSignal.cs" />
|
||||
<Compile Remove="Tool\ToCSharpCodeHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace Serein.NodeFlow.Services
|
||||
/// 生成完全的xml注释
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="retractCount"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToXmlComments(this string context, int retractCount = 0)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Serein.NodeFlow.Services
|
||||
/// <summary>
|
||||
/// 流程API服务,用于外部调用流程接口
|
||||
/// </summary>
|
||||
public class FlowApiService
|
||||
internal class FlowApiService
|
||||
{
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
private readonly FlowModelService flowModelService;
|
||||
|
||||
@@ -20,6 +20,11 @@ namespace Serein.NodeFlow.Services
|
||||
private readonly FlowModelService flowModelService;
|
||||
private readonly FlowLibraryService flowLibraryService;
|
||||
|
||||
/// <summary>
|
||||
/// 流程代码生成服务
|
||||
/// </summary>
|
||||
/// <param name="flowModelService"></param>
|
||||
/// <param name="flowLibraryService"></param>
|
||||
public FlowCoreGenerateService(FlowModelService flowModelService ,FlowLibraryService flowLibraryService )
|
||||
{
|
||||
this.flowModelService = flowModelService;
|
||||
@@ -429,7 +434,6 @@ namespace Serein.NodeFlow.Services
|
||||
if (param is null) return;
|
||||
if (pds is null) return;
|
||||
|
||||
bool isGetPreviousNode = false;
|
||||
for (int index = 0; index < pds.Length; index++)
|
||||
{
|
||||
ParameterDetails? pd = pds[index];
|
||||
@@ -798,7 +802,6 @@ namespace Serein.NodeFlow.Services
|
||||
if (param is null) return;
|
||||
if (pds is null) return;
|
||||
|
||||
bool isGetPreviousNode = false;
|
||||
for (int index = 0; index < pds.Length; index++)
|
||||
{
|
||||
ParameterDetails? pd = pds[index];
|
||||
@@ -998,17 +1001,18 @@ namespace Serein.NodeFlow.Services
|
||||
sb.AppendCode(1, $"}}");
|
||||
}
|
||||
|
||||
public class SereinGlobalDataInfo
|
||||
|
||||
private class SereinGlobalDataInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局数据节点
|
||||
/// </summary>
|
||||
public SingleGlobalDataNode Node { get; set; }
|
||||
public required SingleGlobalDataNode Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 全局数据的来源节点
|
||||
/// </summary>
|
||||
public IFlowNode DataSourceNode { get; set; }
|
||||
public required IFlowNode DataSourceNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 全局数据的键名
|
||||
|
||||
@@ -14,6 +14,10 @@ namespace Serein.NodeFlow.Services
|
||||
/// </summary>
|
||||
public class FlowLibraryService
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数,初始化流程依赖
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment"></param>
|
||||
public FlowLibraryService(IFlowEnvironment flowEnvironment)
|
||||
{
|
||||
this.flowEnvironment = flowEnvironment;
|
||||
@@ -35,10 +39,12 @@ namespace Serein.NodeFlow.Services
|
||||
/// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
/// </summary>
|
||||
/// <param name="libraryfilePath"></param>
|
||||
/// <param name="baseLibraryPath"></param>
|
||||
/// <returns></returns>
|
||||
private bool CheckBaseLibrary(string libraryfilePath, out string baseLibraryPath)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径
|
||||
ArgumentNullException.ThrowIfNullOrWhiteSpace(dir);
|
||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);
|
||||
if (!Path.Exists(sereinFlowBaseLibraryPath))
|
||||
{
|
||||
@@ -146,7 +152,7 @@ namespace Serein.NodeFlow.Services
|
||||
/// </summary>
|
||||
/// <param name="assemblyName">程序集名称</param>
|
||||
/// <param name="methodName">方法名称</param>
|
||||
/// <param name="md">返回的方法描述</param>
|
||||
/// <param name="methodInfo">返回的方法描述</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public bool TryGetMethodInfo(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodInfo methodInfo)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Model.Nodes;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Serein.NodeFlow.Services
|
||||
{
|
||||
@@ -13,6 +14,11 @@ namespace Serein.NodeFlow.Services
|
||||
private readonly IFlowEnvironment environment;
|
||||
private readonly FlowLibraryService flowLibraryService;
|
||||
|
||||
/// <summary>
|
||||
/// 流程模型服务构造函数
|
||||
/// </summary>
|
||||
/// <param name="environment"></param>
|
||||
/// <param name="flowLibraryService"></param>
|
||||
public FlowModelService(IFlowEnvironment environment, FlowLibraryService flowLibraryService)
|
||||
{
|
||||
this.environment = environment;
|
||||
@@ -35,72 +41,156 @@ namespace Serein.NodeFlow.Services
|
||||
/// </summary>
|
||||
private List<SingleFlipflopNode> FlipflopNodes { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public IFlowNode? GetNodeModel(string guid)
|
||||
{
|
||||
NodeModels.TryGetValue(guid, out var nodeModel);
|
||||
return nodeModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取画布模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public FlowCanvasDetails? GetCanvasModel(string guid)
|
||||
{
|
||||
FlowCanvass.TryGetValue(guid, out var nodeModel);
|
||||
return nodeModel;
|
||||
}
|
||||
|
||||
public bool TryGetNodeModel(string guid, out IFlowNode flowNode)
|
||||
/// <summary>
|
||||
/// 尝试获取节点模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetNodeModel(string guid, [NotNullWhen(true)] out IFlowNode? flowNode)
|
||||
{
|
||||
return NodeModels.TryGetValue(guid, out flowNode!);
|
||||
}
|
||||
|
||||
public bool TryGetCanvasModel(string guid, out FlowCanvasDetails flowCanvas)
|
||||
/// <summary>
|
||||
/// 尝试获取画布模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <param name="flowCanvas"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetCanvasModel(string guid, [NotNullWhen(true)] out FlowCanvasDetails? flowCanvas)
|
||||
{
|
||||
return FlowCanvass.TryGetValue(guid, out flowCanvas!); ;
|
||||
if(FlowCanvass.TryGetValue(guid, out var details))
|
||||
{
|
||||
flowCanvas = details;
|
||||
return true;
|
||||
}
|
||||
flowCanvas = details;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含节点模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public bool ContainsNodeModel(string guid)
|
||||
{
|
||||
return NodeModels.ContainsKey(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否包含画布模型
|
||||
/// </summary>
|
||||
/// <param name="guid"></param>
|
||||
/// <returns></returns>
|
||||
public bool ContainsCanvasModel(string guid)
|
||||
{
|
||||
return FlowCanvass.ContainsKey(guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加节点模型
|
||||
/// </summary>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddNodeModel(IFlowNode flowNode)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(flowNode);
|
||||
ArgumentNullException.ThrowIfNull(flowNode.Guid);
|
||||
return NodeModels.TryAdd(flowNode.Guid, flowNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加画布模型
|
||||
/// </summary>
|
||||
/// <param name="flowCanvasDetails"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddCanvasModel(FlowCanvasDetails flowCanvasDetails)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(flowCanvasDetails);
|
||||
ArgumentNullException.ThrowIfNull(flowCanvasDetails.Guid);
|
||||
return FlowCanvass.TryAdd(flowCanvasDetails.Guid, flowCanvasDetails);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除节点模型
|
||||
/// </summary>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveNodeModel(IFlowNode flowNode)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(flowNode.Guid);
|
||||
return NodeModels.Remove(flowNode.Guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除画布模型
|
||||
/// </summary>
|
||||
/// <param name="flowCanvasDetails"></param>
|
||||
/// <returns></returns>
|
||||
public bool RemoveCanvasModel(FlowCanvasDetails flowCanvasDetails)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(flowCanvasDetails.Guid);
|
||||
return FlowCanvass.Remove(flowCanvasDetails.Guid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有节点模型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<IFlowNode> GetAllNodeModel() => [.. NodeModels.Values];
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定画布上的所有节点模型
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <returns></returns>
|
||||
public List<IFlowNode> GetAllNodeModel(string canvasGuid) =>
|
||||
NodeModels.Values.Where(x => x.CanvasDetails.Guid == canvasGuid).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有画布模型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<FlowCanvasDetails> GetAllCanvasModel() => [.. FlowCanvass.Values];
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在画布模型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsExsitCanvas()
|
||||
{
|
||||
return FlowCanvass.Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定画布上是否存在节点模型
|
||||
/// </summary>
|
||||
/// <param name="canvasGuid"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsExsitNodeOnCanvas(string canvasGuid)
|
||||
{
|
||||
if (!FlowCanvass.TryGetValue(canvasGuid, out var flowCanvasDetails))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model.Operation;
|
||||
using Serein.NodeFlow.Model.Operations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -17,11 +17,22 @@ namespace Serein.NodeFlow.Tool
|
||||
private AssemblyLoadContext context;
|
||||
private Dictionary<string, Type> dicTypes = new Dictionary<string, Type>();
|
||||
|
||||
/// <summary>
|
||||
/// 程序集加载器构造函数
|
||||
/// </summary>
|
||||
/// <param name="basePath"></param>
|
||||
public AssemblyLoader(string basePath)
|
||||
{
|
||||
_basePath = basePath;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 加载指定的类型
|
||||
/// </summary>
|
||||
/// <param name="dllFileName"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public Type Load(string dllFileName, string typeName)
|
||||
{
|
||||
context = new AssemblyLoadContext(dllFileName);
|
||||
|
||||
@@ -12,6 +12,9 @@ namespace Serein.NodeFlow.Tool
|
||||
{
|
||||
private readonly HashSet<MetadataReference> _references = new HashSet<MetadataReference>();
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的动态编译器实例。
|
||||
/// </summary>
|
||||
public DynamicCompiler()
|
||||
{
|
||||
// 默认添加当前 AppDomain 加载的所有程序集
|
||||
@@ -110,10 +113,6 @@ namespace Serein.NodeFlow.Tool
|
||||
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ namespace Serein.NodeFlow.Tool
|
||||
public override Encoding Encoding => Encoding.UTF8;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重写Write方法,处理单个字符的写入
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void Write(char value)
|
||||
{
|
||||
stringWriter.Write(value);
|
||||
@@ -43,6 +47,10 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写Write方法,处理字符串的写入
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void Write(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value)) return;
|
||||
@@ -53,6 +61,10 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写WriteLine方法,处理字符串的换行写入
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void WriteLine(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value)) return;
|
||||
|
||||
@@ -103,8 +103,7 @@ namespace Serein.NodeFlow.Tool
|
||||
/// <summary>
|
||||
/// 加载Windows类库
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="isRecurrence">是否递归加载</param>
|
||||
/// <param name="file"></param>
|
||||
private static bool LoadWindowsLibrarie(string file)
|
||||
{
|
||||
IntPtr hModule = IntPtr.Zero;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
@@ -7,6 +8,9 @@ using System.Reflection;
|
||||
|
||||
namespace Serein.NodeFlow.Tool;
|
||||
|
||||
/// <summary>
|
||||
/// 节点方法描述帮助类
|
||||
/// </summary>
|
||||
public static class NodeMethodDetailsHelper
|
||||
{
|
||||
|
||||
@@ -25,15 +29,16 @@ public static class NodeMethodDetailsHelper
|
||||
/// <param name="type">方法所属的类型</param>
|
||||
/// <param name="methodInfo">方法信息</param>
|
||||
/// <param name="assemblyName">方法所属的程序集名称</param>
|
||||
/// <param name="outMethodInfo">传出的方法信息</param>
|
||||
/// <param name="methodDetails">创建的方法描述,用来生成节点信息</param>
|
||||
/// <param name="delegateDetails">方法对应的Emit动态委托</param>
|
||||
/// <returns>指示是否创建成功</returns>
|
||||
public static bool TryCreateDetails(Type type,
|
||||
MethodInfo methodInfo,
|
||||
string assemblyName,
|
||||
[MaybeNullWhen(false)] out MethodInfo outMethodInfo,
|
||||
[MaybeNullWhen(false)] out MethodDetails methodDetails,
|
||||
[MaybeNullWhen(false)] out DelegateDetails delegateDetails)
|
||||
[NotNullWhen(true)] out MethodInfo? outMethodInfo,
|
||||
[NotNullWhen(true)] out MethodDetails? methodDetails,
|
||||
[NotNullWhen(true)] out DelegateDetails? delegateDetails)
|
||||
{
|
||||
|
||||
|
||||
@@ -60,7 +65,7 @@ public static class NodeMethodDetailsHelper
|
||||
|
||||
|
||||
Type? returnType;
|
||||
bool isAsync = IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
bool isAsync = EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
bool isStatic = methodInfo.IsStatic;
|
||||
|
||||
|
||||
@@ -172,6 +177,12 @@ public static class NodeMethodDetailsHelper
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取方法签名
|
||||
/// </summary>
|
||||
/// <param name="method"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetMethodSignature(MethodInfo method)
|
||||
{
|
||||
if (method == null) return string.Empty;
|
||||
@@ -184,28 +195,8 @@ public static class NodeMethodDetailsHelper
|
||||
return $"{methodName}({parameters})";
|
||||
//return $"{methodName}({parameters}) : {returnType}";
|
||||
}
|
||||
public static bool IsGenericTask(Type returnType, out Type? taskResult)
|
||||
{
|
||||
// 判断是否为 Task 类型或泛型 Task<T>
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
taskResult = null;
|
||||
return true;
|
||||
}
|
||||
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 获取泛型参数类型
|
||||
Type genericArgument = returnType.GetGenericArguments()[0];
|
||||
taskResult = genericArgument;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult = null;
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static ConcurrentDictionary<string, (object, MethodInfo)> ConvertorInstance =[];
|
||||
@@ -231,6 +222,7 @@ public static class NodeMethodDetailsHelper
|
||||
}
|
||||
#endregion
|
||||
#region 存在自定义的转换器
|
||||
#if false
|
||||
else if (it.GetCustomAttribute<BindConvertorAttribute>() is BindConvertorAttribute attribute2 && attribute2 is not null)
|
||||
{
|
||||
paremType = attribute2.EnumType;
|
||||
@@ -262,6 +254,8 @@ public static class NodeMethodDetailsHelper
|
||||
|
||||
return ed;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endregion
|
||||
#region 常规方法的获取参数
|
||||
else
|
||||
|
||||
@@ -7,11 +7,20 @@ using System.Reflection.Emit;
|
||||
namespace Serein.NodeFlow.Tool
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 动态创建对象的帮助类,支持根据属性字典创建对象并设置属性值。
|
||||
/// </summary>
|
||||
public class ObjDynamicCreateHelper
|
||||
{
|
||||
// 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式)
|
||||
static Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
|
||||
|
||||
/// <summary>
|
||||
/// 根据属性字典和类型名称创建对象实例,并设置属性值。
|
||||
/// </summary>
|
||||
/// <param name="properties"></param>
|
||||
/// <param name="typeName"></param>
|
||||
/// <returns></returns>
|
||||
public static object Resolve(Dictionary<string, object> properties, string typeName)
|
||||
{
|
||||
var obj = CreateObjectWithProperties(properties, typeName);
|
||||
|
||||
@@ -16,13 +16,20 @@ namespace Serein.Extend.NewtonsoftJson
|
||||
/// </summary>
|
||||
public sealed class NewtonsoftJsonProvider : IJsonProvider
|
||||
{
|
||||
private JsonSerializerSettings settings;
|
||||
private JsonSerializerSettings? settings;
|
||||
|
||||
/// <summary>
|
||||
/// 基于Newtonsoft.Json的JSON门户实现
|
||||
/// </summary>
|
||||
public NewtonsoftJsonProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于Newtonsoft.Json的JSON门户实现
|
||||
/// </summary>
|
||||
/// <param name="jsonType"></param>
|
||||
public NewtonsoftJsonProvider(JsonType jsonType)
|
||||
{
|
||||
settings = jsonType switch
|
||||
@@ -48,39 +55,78 @@ namespace Serein.Extend.NewtonsoftJson
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化JSON文本为指定类型的对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="jsonText"></param>
|
||||
/// <returns></returns>
|
||||
public T? Deserialize<T>(string jsonText)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(jsonText, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化JSON文本为指定类型的对象。
|
||||
/// </summary>
|
||||
/// <param name="jsonText"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public object? Deserialize(string jsonText, Type type)
|
||||
{
|
||||
return JsonConvert.DeserializeObject(jsonText, type, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化对象为JSON文本。
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public string Serialize(object obj)
|
||||
{
|
||||
return JsonConvert.SerializeObject(obj, settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将JSON文本解析为IJsonToken对象。
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public IJsonToken Parse(string json)
|
||||
{
|
||||
var token = JToken.Parse(json);
|
||||
return new NewtonsoftJsonToken(token);
|
||||
}
|
||||
|
||||
public IJsonToken CreateObject(IDictionary<string, object> values = null)
|
||||
/// <summary>
|
||||
/// 创建一个新的JSON对象。
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
public IJsonToken CreateObject(IDictionary<string, object>? values = null)
|
||||
{
|
||||
var jobj = values != null ? JObject.FromObject(values) : new JObject();
|
||||
return new NewtonsoftJsonToken(jobj);
|
||||
}
|
||||
|
||||
public IJsonToken CreateArray(IEnumerable<object> values = null)
|
||||
/// <summary>
|
||||
/// 创建一个新的JSON数组。
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public IJsonToken CreateArray(IEnumerable<object>? values = null)
|
||||
{
|
||||
var jarr = values != null ? JArray.FromObject(values) : new JArray();
|
||||
return new NewtonsoftJsonToken(jarr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将对象转换为IJsonToken。
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public IJsonToken FromObject(object obj)
|
||||
{
|
||||
var token = JToken.FromObject(obj);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serein.Library.Api;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Serein.Extend.NewtonsoftJson
|
||||
{
|
||||
@@ -10,14 +11,25 @@ namespace Serein.Extend.NewtonsoftJson
|
||||
{
|
||||
private readonly JToken _token;
|
||||
|
||||
/// <summary>
|
||||
/// 使用JToken初始化一个新的NewtonsoftJsonToken实例。
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public NewtonsoftJsonToken(JToken token)
|
||||
{
|
||||
_token = token ?? throw new ArgumentNullException(nameof(token));
|
||||
}
|
||||
|
||||
public bool TryGetValue(string name, out IJsonToken token)
|
||||
/// <summary>
|
||||
/// 尝试获取指定名称的属性值。
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetValue(string name, [NotNullWhen(true)] out IJsonToken? token)
|
||||
{
|
||||
if (_token is JObject obj && obj.TryGetValue(name, out JToken value))
|
||||
if (_token is JObject obj && obj.TryGetValue(name, out JToken? value))
|
||||
{
|
||||
token = new NewtonsoftJsonToken(value);
|
||||
return true;
|
||||
@@ -28,14 +40,14 @@ namespace Serein.Extend.NewtonsoftJson
|
||||
|
||||
public IJsonToken? GetValue(string name)
|
||||
{
|
||||
if (_token is JObject obj && obj.TryGetValue(name, out JToken value))
|
||||
if (_token is JObject obj && obj.TryGetValue(name, out JToken? value))
|
||||
{
|
||||
return new NewtonsoftJsonToken(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetString() => _token.Type == JTokenType.Null ? null : _token.ToString();
|
||||
public string GetString() => (_token.Type == JTokenType.Null ? null : _token.ToString()) ?? string.Empty;
|
||||
|
||||
public int GetInt32() => _token.Value<int>();
|
||||
|
||||
@@ -50,10 +62,28 @@ namespace Serein.Extend.NewtonsoftJson
|
||||
throw new InvalidOperationException("当前Token不是数组类型。");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将当前JSON Token转换为指定类型的对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
#pragma warning disable CS8603 // 可能返回 null 引用。
|
||||
public T ToObject<T>() => _token.ToObject<T>();
|
||||
#pragma warning restore CS8603 // 可能返回 null 引用。
|
||||
|
||||
/// <summary>
|
||||
/// 将当前JSON Token转换为指定类型的对象。
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
#pragma warning disable CS8603 // 可能返回 null 引用。
|
||||
public object ToObject(Type type) => _token.ToObject(type);
|
||||
#pragma warning restore CS8603 // 可能返回 null 引用。
|
||||
|
||||
/// <summary>
|
||||
/// 返回当前JSON Token的字符串表示形式。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString() => _token.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -16,6 +16,22 @@
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
|
||||
<NoWarn>1701;1702;CS8766</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net462|AnyCPU'">
|
||||
<NoWarn>1701;1702;CS8766</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
|
||||
<NoWarn>1701;1702;CS8766</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net462|AnyCPU'">
|
||||
<NoWarn>1701;1702;CS8766</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -40,20 +40,25 @@ namespace Serein.Library
|
||||
/// 标识一个类中的某些字段需要生成相应代码
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
|
||||
public sealed class NodePropertyAttribute : Attribute
|
||||
public sealed class FlowDataPropertyAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>属性路径</para>
|
||||
/// <para>CustomNode : 自定义节点</para>
|
||||
/// </summary>
|
||||
public NodeValuePath ValuePath = NodeValuePath.None;
|
||||
|
||||
/// <summary>
|
||||
/// 表示该类是否为节点实现类
|
||||
/// </summary>
|
||||
public bool IsNodeImp = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自动生成环境的属性
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field, Inherited = true)]
|
||||
public sealed class PropertyInfoAttribute : Attribute
|
||||
public sealed class DataInfoAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否通知远程环境(如果在远程环境下)
|
||||
|
||||
@@ -4,24 +4,25 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
|
||||
namespace Serein.Library.NodeGenerator
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 一个增量源生成器,用于为带有自定义 MyClassAttribute 特性的类中的字段生成带有自定义 set 行为的属性。
|
||||
/// 增量源生成器
|
||||
/// </summary>
|
||||
[Generator]
|
||||
public class MyPropertyGenerator : IIncrementalGenerator
|
||||
public class FlowDataPropertyGenerator : IIncrementalGenerator
|
||||
{
|
||||
internal static NodePropertyAttribute NodeProperty = new NodePropertyAttribute();
|
||||
internal static PropertyInfoAttribute PropertyInfo = new PropertyInfoAttribute();
|
||||
internal static FlowDataPropertyAttribute FlowDataProperty = new FlowDataPropertyAttribute();
|
||||
internal static DataInfoAttribute DataInfo = new DataInfoAttribute();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化生成器,定义需要执行的生成逻辑。
|
||||
@@ -29,12 +30,16 @@ namespace Serein.Library.NodeGenerator
|
||||
/// <param name="context">增量生成器的上下文,用于注册生成逻辑。</param>
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
|
||||
/*
|
||||
* //Debugger.Launch();
|
||||
CreateSyntaxProvider : 第一个参数用于筛选特定语法节点,第二个参数则用于转换筛选出来的节点。
|
||||
SemanticModel : 通过 语义模型 (SemanticModel) 来解析代码中的符号信息,获取类、方法、属性等更具体的类型和特性信息。例如某个特性属于哪个类型。
|
||||
AddSource : 生成器的最终目标是生成代码。使用 AddSource 将生成的代码以字符串形式注入到编译过程当中。
|
||||
*/
|
||||
// 通过 SyntaxProvider 查找所有带有任意特性修饰的类声明语法节点
|
||||
|
||||
|
||||
var classDeclarations = context.SyntaxProvider
|
||||
.CreateSyntaxProvider(
|
||||
// 定义要查找的语法节点类型,这里我们只关心类声明 (ClassDeclarationSyntax) 并且它们有至少一个特性 (Attribute)
|
||||
@@ -50,7 +55,7 @@ namespace Serein.Library.NodeGenerator
|
||||
// 检查类的特性列表,看看是否存在 MyClassAttribute
|
||||
if (classDeclaration.AttributeLists
|
||||
.SelectMany(attrList => attrList.Attributes)
|
||||
.Any(attr => semanticModel.GetSymbolInfo(attr).Symbol?.ContainingType.Name == nameof(NodePropertyAttribute)))
|
||||
.Any(attr => semanticModel.GetSymbolInfo(attr).Symbol?.ContainingType.Name == nameof(FlowDataPropertyAttribute)))
|
||||
{
|
||||
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration); // 获取类的符号
|
||||
var classInfo = classSymbol.BuildCacheOfClass();
|
||||
@@ -77,7 +82,7 @@ namespace Serein.Library.NodeGenerator
|
||||
// 获取类的命名空间和类名
|
||||
var namespaceName = GetNamespace(classSyntax);
|
||||
var className = classSyntax.Identifier.Text;
|
||||
|
||||
Debug.WriteLine($"Generator Class Name : {className}");
|
||||
// 生成属性代码
|
||||
var generatedCode = GenerateProperties(classSyntax, result.classInfo, namespaceName, className);
|
||||
|
||||
@@ -93,6 +98,7 @@ namespace Serein.Library.NodeGenerator
|
||||
/// </summary>
|
||||
/// <param name="classSyntax">类的语法树节点。</param>
|
||||
/// <param name="namespaceName">类所在的命名空间。</param>
|
||||
/// <param name="classInfo">。</param>
|
||||
/// <param name="className">类的名称。</param>
|
||||
/// <returns>生成的 C# 属性代码。</returns>
|
||||
private string GenerateProperties(ClassDeclarationSyntax classSyntax,
|
||||
@@ -144,9 +150,8 @@ namespace Serein.Library.NodeGenerator
|
||||
var fieldType = field.Declaration.Type.ToString(); // 获取字段类型
|
||||
var propertyName = field.ToPropertyName(); // 转为合适的属性名称
|
||||
var attributeInfo = fieldKV.Value; // 缓存的特性信息
|
||||
|
||||
var isProtection = attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsProtection), value => bool.Parse(value)); // 是否为保护字段
|
||||
var isVerify = attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsVerify), value => bool.Parse(value)); // 是否为保护字段
|
||||
var isProtection = attributeInfo.Search(nameof(DataInfo), nameof(DataInfo.IsProtection), value => bool.Parse(value)); // 是否为保护字段
|
||||
var isVerify = attributeInfo.Search(nameof(DataInfo), nameof(DataInfo.IsVerify), value => bool.Parse(value)); // 是否为保护字段
|
||||
|
||||
//sb.AppendLine(leadingTrivia);
|
||||
sb.AppendLine($" partial void On{propertyName}Changed({fieldType} oldValue, {fieldType} newValue);");
|
||||
@@ -194,7 +199,7 @@ namespace Serein.Library.NodeGenerator
|
||||
//sb.AppendLine($" SetProperty<{fieldType}>(ref {fieldName}, value); ");
|
||||
sb.AppendLine($" On{propertyName}Changed(value);");
|
||||
sb.AppendLine($" On{propertyName}Changed(__oldValue, value);");
|
||||
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsPrint), value => bool.Parse(value)))
|
||||
if (attributeInfo.Search(nameof(DataInfo), nameof(DataInfo.IsPrint), value => bool.Parse(value)))
|
||||
{
|
||||
sb.AddCode(5, $"Console.WriteLine({fieldName});");
|
||||
} // 是否打印
|
||||
@@ -206,7 +211,7 @@ namespace Serein.Library.NodeGenerator
|
||||
// NodeValuePath.Method : 节点 → 方法描述
|
||||
// NodeValuePath.Parameter : 节点 → 方法描述 → 参数描述
|
||||
|
||||
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsNotification), value => bool.Parse(value))) // 是否通知
|
||||
if (attributeInfo.Search(nameof(DataInfo), nameof(DataInfo.IsNotification), value => bool.Parse(value))) // 是否通知
|
||||
{
|
||||
|
||||
if (classInfo.ExitsPath(nameof(NodeValuePath.Node))) // 节点 or 自定义节点
|
||||
@@ -250,6 +255,18 @@ namespace Serein.Library.NodeGenerator
|
||||
}
|
||||
|
||||
|
||||
var isNodeImp = false;
|
||||
|
||||
if (classInfo.TryGetValue(nameof(FlowDataPropertyAttribute), out var values)
|
||||
&& values.TryGetValue(nameof(FlowDataPropertyAttribute.IsNodeImp), out object data)
|
||||
&& bool.TryParse(data.ToString(), out var isNodeImpTemp)
|
||||
&& isNodeImpTemp)
|
||||
{
|
||||
isNodeImp = true;
|
||||
}
|
||||
|
||||
if (!isNodeImp)
|
||||
{
|
||||
sb.AppendLine(" /// <summary>");
|
||||
sb.AppendLine(" /// 略");
|
||||
sb.AppendLine(" /// <para>此事件为自动生成</para>");
|
||||
@@ -274,7 +291,8 @@ namespace Serein.Library.NodeGenerator
|
||||
sb.AppendLine(" ");
|
||||
sb.AppendLine(" ");
|
||||
|
||||
// 生成变量修改
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -302,38 +320,6 @@ namespace Serein.Library.NodeGenerator
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*private void ModifyValue(string path, string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (path.Equals(nameof(MaxChildrenCount), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (typeof(int) == typeof(string))
|
||||
{
|
||||
this.MaxChildrenCount = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.MaxChildrenCount = ConvertHelper.ValueParse<int>(value);
|
||||
}
|
||||
}
|
||||
else if (path.Equals(nameof(Guid), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (typeof(string) == typeof(string))
|
||||
{
|
||||
this.Guid = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Guid = ConvertHelper.ValueParse<string>(value);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取类所在的命名空间。
|
||||
/// </summary>
|
||||
@@ -348,20 +334,15 @@ namespace Serein.Library.NodeGenerator
|
||||
|
||||
|
||||
|
||||
private void SetterIsProtection()
|
||||
{
|
||||
|
||||
}
|
||||
private void SetterNotIsProtection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 扩展方法,用于处理 XML 文档注释中的 summary 标签
|
||||
/// </summary>
|
||||
public static class DocumentationCommentExtensions
|
||||
{
|
||||
|
||||
@@ -432,9 +413,17 @@ namespace Serein.Library.NodeGenerator
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// MyAttributeResolver
|
||||
/// </summary>
|
||||
|
||||
public static class MyAttributeResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建类的特性缓存信息
|
||||
/// </summary>
|
||||
/// <param name="classSymbol"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<string, Dictionary<string, object>> BuildCacheOfClass(this INamedTypeSymbol classSymbol)
|
||||
{
|
||||
Dictionary<string, Dictionary<string, object>> attributesOfClass = new Dictionary<string, Dictionary<string, object>>();
|
||||
@@ -452,19 +441,28 @@ namespace Serein.Library.NodeGenerator
|
||||
{
|
||||
var key = cata.Key;
|
||||
var value = cata.Value.Value;
|
||||
if (nameof(NodePropertyAttribute).Equals(attributeName))
|
||||
if (nameof(FlowDataPropertyAttribute).Equals(attributeName))
|
||||
{
|
||||
if(cata.Key == nameof(FlowDataPropertyAttribute.ValuePath))
|
||||
{
|
||||
string literal = Enum.GetName(typeof(NodeValuePath), cata.Value.Value);
|
||||
attributeInfo.Add(key, literal);
|
||||
}
|
||||
else if (cata.Key == nameof(FlowDataPropertyAttribute.IsNodeImp))
|
||||
{
|
||||
string literal = cata.Value.Value.ToString();
|
||||
attributeInfo.Add(key, literal);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeInfo.Add(key, value);
|
||||
}
|
||||
|
||||
|
||||
//Console.WriteLine("key:" + cata.Key);// 类特性的属性名
|
||||
//Console.WriteLine("value:" + cata.Value.Value); // 类特性的属性值
|
||||
Debug.WriteLine("key : " + cata.Key);// 类特性的属性名
|
||||
Debug.WriteLine("value : " + cata.Value.Value); // 类特性的属性值
|
||||
}
|
||||
}
|
||||
return attributesOfClass;
|
||||
@@ -632,15 +630,21 @@ namespace Serein.Library.NodeGenerator
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查类信息中是否存在指定的路径
|
||||
/// </summary>
|
||||
/// <param name="classInfo"></param>
|
||||
/// <param name="valuePath"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ExitsPath(this Dictionary<string, Dictionary<string, object>> classInfo, string valuePath)
|
||||
{
|
||||
|
||||
if (!classInfo.TryGetValue(nameof(NodePropertyAttribute), out var keyValuePairs))
|
||||
if (!classInfo.TryGetValue(nameof(FlowDataPropertyAttribute), out var keyValuePairs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!keyValuePairs.TryGetValue(nameof(MyPropertyGenerator.NodeProperty.ValuePath), out var value))
|
||||
if (!keyValuePairs.TryGetValue(nameof(FlowDataPropertyGenerator.FlowDataProperty.ValuePath), out var value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user