实现了远程属性更改、数据交互。

This commit is contained in:
fengjiayi
2024-10-20 21:59:42 +08:00
parent e38833a58c
commit 838158f446
28 changed files with 961 additions and 637 deletions

View File

@@ -1,4 +1,5 @@
using Serein.Library.Utils;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Threading;
@@ -228,10 +229,10 @@ namespace Serein.Library.Api
/// </summary>
/// <param name="eventArgs"></param>
public delegate void NodeRemoteHandler(NodeRemoteEventArgs eventArgs);
public class NodeRemoteEventArgs : FlowEventArgs
public delegate void NodeRemoveHandler(NodeRemoveEventArgs eventArgs);
public class NodeRemoveEventArgs : FlowEventArgs
{
public NodeRemoteEventArgs(string nodeGuid)
public NodeRemoveEventArgs(string nodeGuid)
{
this.NodeGuid = nodeGuid;
}
@@ -478,10 +479,15 @@ namespace Serein.Library.Api
RunState FlipFlopState { get; set; }
/// <summary>
/// 拓展功能时,如需订阅事件,则需要使用该属性
/// 表示当前环境
/// </summary>
IFlowEnvironment CurrentEnv { get; }
/// <summary>
/// 由运行环境提供的UI线程上下文操作用于类库中需要在UI线程中操作视觉元素的场景
/// </summary>
UIContextOperation UIContextOperation { get; }
#endregion
#region
@@ -509,7 +515,7 @@ namespace Serein.Library.Api
/// <summary>
/// 移除节点事件
/// </summary>
event NodeRemoteHandler OnNodeRemote;
event NodeRemoveHandler OnNodeRemove;
/// <summary>
/// 起始节点变化事件
@@ -674,13 +680,13 @@ namespace Serein.Library.Api
/// <param name="fromNodeGuid">起始节点</param>
/// <param name="toNodeGuid">目标节点</param>
/// <param name="connectionType">连接类型</param>
void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
Task<bool> RemoveConnectAsync(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
/// <summary>
/// 移除节点/区域/基础控件
/// </summary>
/// <param name="nodeGuid">待移除的节点Guid</param>
void RemoveNode(string nodeGuid);
Task<bool> RemoveNodeAsync(string nodeGuid);
/// <summary>
/// 激活未启动的全局触发器

View File

@@ -20,6 +20,7 @@ namespace Serein.Library
{
public bool IsNotification = false;
public bool IsPrint = false;
public bool IsProtection = false;
}
}

View File

@@ -9,27 +9,41 @@ namespace Serein.Library
/// <summary>
/// 节点调试设置,用于中断节点的运行
/// </summary>
public class NodeDebugSetting
[AutoProperty(ValuePath = nameof(NodeDebugSetting))]
public partial class NodeDebugSetting
{
private readonly NodeModelBase nodeModel;
/// <summary>
/// 创建属于某个节点的调试设置
/// </summary>
/// <param name="nodeModel"></param>
public NodeDebugSetting(NodeModelBase nodeModel)
{
this.nodeModel = nodeModel;
}
/// <summary>
/// 是否使能
/// </summary>
public bool IsEnable { get; set; } = true;
[PropertyInfo(IsNotification = true)]
private bool _isEnable = true;
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
public InterruptClass InterruptClass { get; set; } = InterruptClass.None;
[PropertyInfo]
private InterruptClass _interruptClass = InterruptClass.None;
/// <summary>
/// 取消中断的回调函数
/// </summary>
public Action CancelInterruptCallback { get; set; }
[PropertyInfo]
private Action _cancelInterruptCallback;
/// <summary>
/// 中断Task用来取消中断)
/// 中断Task用来中断
/// </summary>
public Func<Task<CancelType>> GetInterruptTask { get; set; }
[PropertyInfo]
private Func<Task<CancelType>> _getInterruptTask;
}
@@ -53,3 +67,6 @@ namespace Serein.Library
Global,
}
}

View File

@@ -1,17 +1,93 @@
using Serein.Library.Api;
using Serein.Library;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
namespace Serein.Library
{
/// <summary>
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
/// </summary>
[AutoProperty(ValuePath = nameof(NodeModelBase))] // 是否更名为 NodeProperty?
public abstract partial class NodeModelBase : IDynamicFlowNode
{
[PropertyInfo(IsProtection = true)]
private IFlowEnvironment _env;
/// <summary>
/// 在画布中的位置
/// </summary>
[PropertyInfo(IsProtection = true)]
private PositionOfUI _position ;
/// <summary>
/// 附加的调试功能
/// </summary>
[PropertyInfo(IsProtection = true)]
private NodeDebugSetting _debugSetting ;
/// <summary>
/// 描述节点对应的控件类型
/// </summary>
[PropertyInfo(IsProtection = true)]
private NodeControlType _controlType ;
/// <summary>
/// 方法描述。不包含Method与委托需要通过MethodName从环境中获取委托进行调用。
/// </summary>
[PropertyInfo(IsProtection = true)]
private MethodDetails _methodDetails ;
/// <summary>
/// 标识节点对象全局唯一
/// </summary>
[PropertyInfo(IsProtection = true)]
private string _guid ;
/// <summary>
/// 显示名称
/// </summary>
[PropertyInfo]
private string _displayName ;
/// <summary>
/// 是否为起点控件
/// </summary>
[PropertyInfo]
private bool _isStart ;
/// <summary>
/// 运行时的上一节点
/// </summary>
[PropertyInfo]
private NodeModelBase _previousNode ;
/// <summary>
/// 当前节点执行完毕后需要执行的下一个分支的类别
/// </summary>
[PropertyInfo]
private ConnectionType _nextOrientation = ConnectionType.None;
/// <summary>
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
/// </summary>
[PropertyInfo]
private Exception _runingException ;
}
public abstract partial class NodeModelBase : IDynamicFlowNode
{
public NodeModelBase(IFlowEnvironment environment)
{
PreviousNodes = new Dictionary<ConnectionType, List<NodeModelBase>>();
@@ -21,75 +97,19 @@ namespace Serein.Library
PreviousNodes[ctType] = new List<NodeModelBase>();
SuccessorNodes[ctType] = new List<NodeModelBase>();
}
DebugSetting = new NodeDebugSetting();
DebugSetting = new NodeDebugSetting(this);
this.Env = environment;
}
/// <summary>
/// 节点保留对环境的引用,因为需要在属性更改时通知
/// </summary>
public IFlowEnvironment Env { get; }
/// <summary>
/// 在画布中的位置
/// </summary>
public PositionOfUI Position { get; set; }
/// <summary>
/// 附加的调试功能
/// </summary>
public NodeDebugSetting DebugSetting { get; set; }
/// <summary>
/// 描述节点对应的控件类型
/// </summary>
public NodeControlType ControlType { get; set; }
/// <summary>
/// 方法描述但不包含Method与委托需要通过MethodName从环境中获取委托进行调用。
/// </summary>
public MethodDetails MethodDetails { get; set; }
/// <summary>
/// 标识节点对象全局唯一
/// </summary>
public string Guid { get; set; }
/// <summary>
/// 显示名称
/// </summary>
public string DisplayName { get; set; } = string.Empty;
/// <summary>
/// 是否为起点控件
/// </summary>
public bool IsStart { get; set; }
/// <summary>
/// 运行时的上一节点
/// </summary>
public NodeModelBase PreviousNode { get; set; }
/// <summary>
/// 不同分支的父节点
/// </summary>
public Dictionary<ConnectionType,List<NodeModelBase>> PreviousNodes { get; }
public Dictionary<ConnectionType, List<NodeModelBase>> PreviousNodes { get; }
/// <summary>
/// 不同分支的子节点
/// </summary>
public Dictionary<ConnectionType,List<NodeModelBase>> SuccessorNodes { get; }
/// <summary>
/// 当前节点执行完毕后需要执行的下一个分支的类别
/// </summary>
public ConnectionType NextOrientation { get; set; } = ConnectionType.None;
/// <summary>
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
/// </summary>
public Exception RuningException { get; set; } = null;
public Dictionary<ConnectionType, List<NodeModelBase>> SuccessorNodes { get; }
/// <summary>
/// 控制FlowData在同一时间只会被同一个线程更改。
@@ -126,11 +146,75 @@ namespace Serein.Library
}
}
}
}
/*
/// <summary>
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
/// </summary>
public abstract partial class NodeModelBase : IDynamicFlowNode
{
/// <summary>
/// 节点保留对环境的引用,因为需要在属性更改时通知
/// </summary>
public IFlowEnvironment Env { get; }
/// <summary>
/// 在画布中的位置
/// </summary>
public PositionOfUI Position { get; set; }
/// <summary>
/// 附加的调试功能
/// </summary>
public NodeDebugSetting DebugSetting { get; set; }
/// <summary>
/// 描述节点对应的控件类型
/// </summary>
public NodeControlType ControlType { get; set; }
/// <summary>
/// 方法描述。不包含Method与委托需要通过MethodName从环境中获取委托进行调用。
/// </summary>
public MethodDetails MethodDetails { get; set; }
/// <summary>
/// 标识节点对象全局唯一
/// </summary>
public string Guid { get; set; }
/// <summary>
/// 显示名称
/// </summary>
public string DisplayName { get; set; } = string.Empty;
/// <summary>
/// 是否为起点控件
/// </summary>
public bool IsStart { get; set; }
/// <summary>
/// 运行时的上一节点
/// </summary>
public NodeModelBase PreviousNode { get; set; }
/// <summary>
/// 当前节点执行完毕后需要执行的下一个分支的类别
/// </summary>
public ConnectionType NextOrientation { get; set; } = ConnectionType.None;
/// <summary>
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
/// </summary>
public Exception RuningException { get; set; } = null;
}*/
/// <summary>
@@ -156,7 +240,7 @@ namespace Serein.Library
// this.FlowData = builder.FlowData;
// }
// /// <summary>
// /// 节点对应的控件类型

View File

@@ -1,6 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using Serein.Library.Utils.SereinExpression;

View File

@@ -212,6 +212,8 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
if (EmitMethodType == EmitHelper.EmitMethodType.HasResultTask && EmitDelegate is Func<object, object[], Task<object>> hasResultTask)
{
result = await hasResultTask(Instance, args);
//Console.WriteLine(result);
// why not data?
}
else if (EmitMethodType == EmitHelper.EmitMethodType.Task && EmitDelegate is Func<object, object[], Task> task)
{
@@ -241,12 +243,23 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
//sw.Stop();
//Console.WriteLine($"Emit Invoke{sw.ElapsedTicks * 1000000F / Stopwatch.Frequency:n3}μs");
if(Module.IsReturnValue && result != null && result.GetType().IsClass)
if(result is null)
{
//var reusltJsonText = JsonConvert.SerializeObject(result);
_ = SendAsync.Invoke(result);
//_ = SendAsync.Invoke($"{reusltJsonText}");
return;
}
else
{
if (Module.IsReturnValue)
{
_ = SendAsync.Invoke(result);
}
}
//if( && result != null && result.GetType().IsClass)
//{
// //var reusltJsonText = JsonConvert.SerializeObject(result);
// //_ = SendAsync.Invoke($"{reusltJsonText}");
//}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.15</Version>
<Version>1.0.17</Version>
<TargetFrameworks>net8.0;net462</TargetFrameworks>
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
@@ -32,7 +32,7 @@
<ItemGroup>
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.MyGenerator.csproj" OutputItemType="Analyzer"/>
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj" OutputItemType="Analyzer" />
<!--ReferenceOutputAssembly="false"-->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Reactive" Version="6.0.1" />

View File

@@ -75,7 +75,6 @@ namespace Serein.Library.Utils
/// 创建信号,直到手动触发(异步方法)
/// </summary>
/// <param name="signal">信号标识符</param>
/// <param name="outTime">超时时间</param>
/// <returns>等待任务</returns>
public async Task<CancelType> GetOrCreateChannelAsync(string signal)
{

View File

@@ -48,8 +48,6 @@ namespace Serein.Library.Utils.SereinExpression
/// <exception cref="NotSupportedException"></exception>
public static object Evaluate(string expression, object targetObJ, out bool isChange)
{
//var parts = expression.Split([' '], 2);
var parts = expression.Split(new[] { ' ' }, 2, StringSplitOptions.None);
if (parts.Length != 2)
{

View File

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace Serein.Library.Utils
{
/// <summary>
/// 为类库提供了在UI线程上下文操作的方法
/// 为类库提供了在UI线程上下文操作的方法如果你在Windows平台上运行不必手动实例化该类
/// </summary>
public class UIContextOperation
{