修改了无法添加基础节点的bug,增加WebSocket JSON ID字段,远程环境交互使用消息ID作为响应key。

This commit is contained in:
fengjiayi
2024-10-22 00:13:13 +08:00
parent 838158f446
commit 0a7e24d318
48 changed files with 1209 additions and 500 deletions

View File

@@ -0,0 +1,10 @@
{
"profiles": {
"Serein.FlowStartTool": {
"commandName": "Project"
},
"配置文件 1": {
"commandName": "DebugRoslynComponent"
}
}
}

View File

@@ -9,6 +9,9 @@
<Nullable>enable</Nullable>
<ErrorReport>prompt</ErrorReport>
<AssemblyName>starter</AssemblyName>
<!--<IsRoslynComponent>true</IsRoslynComponent>-->
<!--<GenerateDocumentationFile>true</GenerateDocumentationFile>-->
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
@@ -23,8 +26,16 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup><!--<ProjectReference Include="..\Library\Serein.Library.csproj" />
<ProjectReference Include="..\NodeFlow\Serein.NodeFlow.csproj" />-->
<PackageReference Include="Serein.Library" Version="1.0.17" />
<PackageReference Include="Serein.Library.NodeGenerator" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Library\Serein.Library.csproj" />
<!--<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj" OutputItemType="Analyzer" />-->
<ProjectReference Include="..\NodeFlow\Serein.NodeFlow.csproj" />
</ItemGroup>

View File

@@ -6,9 +6,16 @@ using System.Threading.Tasks;
namespace Serein.Library
{
/// <summary>
/// 标识一个类中的某些字段需要生成相应代码
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
internal sealed class AutoPropertyAttribute : Attribute
public sealed class AutoPropertyAttribute : Attribute
{
/// <summary>
/// <para>属性路径</para>
/// <para>CustomNode : 自定义节点</para>
/// </summary>
public string ValuePath = string.Empty;
}
@@ -16,10 +23,19 @@ namespace Serein.Library
/// 自动生成环境的属性
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = true)]
internal sealed class PropertyInfoAttribute : Attribute
public sealed class PropertyInfoAttribute : Attribute
{
/// <summary>
/// 是否通知UI
/// </summary>
public bool IsNotification = false;
/// <summary>
/// 是否使用Console.WriteLine打印
/// </summary>
public bool IsPrint = false;
/// <summary>
/// 是否禁止参数进行修改初始化后不能再通过setter修改
/// </summary>
public bool IsProtection = false;
}

View File

@@ -9,7 +9,7 @@ namespace Serein.Library
/// <summary>
/// 每个节点有独自的MethodDetails实例
/// </summary>
[AutoProperty(ValuePath = nameof(MethodDetails))]
[NodeProperty(ValuePath = NodeValuePath.Method)]
public partial class MethodDetails
{
private readonly IFlowEnvironment env;
@@ -142,7 +142,7 @@ namespace Serein.Library
MethodLockName = this.MethodLockName,
IsProtectionParameter = this.IsProtectionParameter,
};
md.ParameterDetailss = this.ParameterDetailss.Select(p => p.CloneOfClone(env, nodeModel)).ToArray(); // 拷贝属于节点方法的新入参描述
md.ParameterDetailss = this.ParameterDetailss?.Select(p => p?.CloneOfClone(env, nodeModel)).ToArray(); // 拷贝属于节点方法的新入参描述
return md;
}

View File

@@ -9,7 +9,7 @@ namespace Serein.Library
/// <summary>
/// 节点调试设置,用于中断节点的运行
/// </summary>
[AutoProperty(ValuePath = nameof(NodeDebugSetting))]
[NodeProperty(ValuePath = NodeValuePath.DebugSetting)]
public partial class NodeDebugSetting
{
private readonly NodeModelBase nodeModel;
@@ -33,6 +33,13 @@ namespace Serein.Library
[PropertyInfo]
private InterruptClass _interruptClass = InterruptClass.None;
/// <summary>
/// 中断级别,暂时停止继续执行后继分支。
/// </summary>
[PropertyInfo(IsNotification = true)]
private bool _isInterrupt = false;
/// <summary>
/// 取消中断的回调函数
/// </summary>

View File

@@ -1,4 +1,5 @@
using Serein.Library.Api;
using Serein.Library.NodeGenerator;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -10,7 +11,7 @@ namespace Serein.Library
/// <summary>
/// 节点基类(数据):条件控件,动作控件,条件区域,动作区域
/// </summary>
[AutoProperty(ValuePath = nameof(NodeModelBase))] // 是否更名为 NodeProperty?
[NodeProperty(ValuePath = NodeValuePath.None)]
public abstract partial class NodeModelBase : IDynamicFlowNode
{

View File

@@ -86,7 +86,13 @@ namespace Serein.Library
/// <returns></returns>
public virtual NodeModelBase LoadInfo(NodeInfo nodeInfo)
{
this.Guid = nodeInfo.Guid;
this.Guid = nodeInfo.Guid;
if (nodeInfo.Position is null)
{
nodeInfo.Position = new PositionOfUI(0, 0);
}
this.Position = nodeInfo.Position;// 加载位置信息
if (this.MethodDetails != null)
{
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
@@ -96,7 +102,6 @@ namespace Serein.Library
this.MethodDetails.ParameterDetailss[i].DataValue = pd.Value;
}
}
this.Position = nodeInfo.Position;// 加载位置信息
return this;
}

View File

@@ -11,7 +11,7 @@ namespace Serein.Library
/// <summary>
/// 节点入参参数详情
/// </summary>
[AutoProperty(ValuePath = nameof(ParameterDetails))]
[NodeProperty(ValuePath = NodeValuePath.Parameter)]
public partial class ParameterDetails
{
private readonly IFlowEnvironment env;

View File

@@ -11,7 +11,7 @@ namespace Serein.Library
{
/// <summary>
/// 环境信息(远程控制用)
/// 环境信息
/// </summary>
public class FlowEnvInfo
{
@@ -27,10 +27,18 @@ namespace Serein.Library
// IOC节点对象信息
}
/// <summary>
/// 程序集相关的方法信息
/// </summary>
public class LibraryMds
{
/// <summary>
/// 程序集FullName
/// </summary>
public string LibraryName { get; set; }
/// <summary>
/// 相关的方法详情
/// </summary>
public MethodDetailsInfo[] Mds { get; set; }
}
@@ -70,7 +78,7 @@ namespace Serein.Library
}
/// <summary>
/// 基础
/// 基础,项目文件相关
/// </summary>
public class Basic
{
@@ -87,7 +95,7 @@ namespace Serein.Library
public string Versions { get; set; }
}
/// <summary>
/// 画布
/// 画布信息,项目文件相关
/// </summary>
public class FlowCanvas
{
@@ -122,7 +130,7 @@ namespace Serein.Library
}
/// <summary>
/// DLL
/// 项目依赖的程序集,项目文件相关
/// </summary>
public class Library
{
@@ -144,7 +152,7 @@ namespace Serein.Library
}
/// <summary>
/// 节点
/// 节点信息,项目文件相关
/// </summary>
public class NodeInfo
{
@@ -215,7 +223,7 @@ namespace Serein.Library
}
/// <summary>
/// 显示参数
/// 显示参数,项目文件相关
/// </summary>
public class Parameterdata
{

View File

@@ -27,6 +27,7 @@ namespace Serein.Library.Network.WebSocketCommunication
{
public string ThemeKey;
public string DataKey;
public string MsgIdKey;
}
@@ -71,13 +72,19 @@ namespace Serein.Library.Network.WebSocketCommunication
}
/// <summary>
/// 使用消息DataKey整体数据
/// 使用 DataKey 整体数据
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class UseMsgDataAttribute : Attribute
public sealed class UseDataAttribute : Attribute
{
}
/// <summary>
/// 使用 MsgIdKey 整体数据
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class UseMsgIdAttribute : Attribute
{
}
internal class SocketHandleModule
{

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Serein.Library.Network.WebSocketCommunication.Handle
@@ -12,4 +13,55 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
public sealed class NeedfulAttribute : Attribute
{
}
/// <summary>
/// 消息ID生成器
/// </summary>
public class MsgIdHelper
{
private static readonly long _epoch = new DateTime(2023, 1, 1).Ticks; // 自定义起始时间
private static long _lastTimestamp = -1L; // 上一次生成 ID 的时间戳
private static long _sequence = 0L; // 序列号
/// <summary>
/// 获取新的ID
/// </summary>
public static long NewId => GenerateId();
/// <summary>
/// 生成消息ID
/// </summary>
/// <returns></returns>
public static long GenerateId()
{
long timestamp = DateTime.UtcNow.Ticks;
// 如果时间戳是一样的,递增序列号
if (timestamp == _lastTimestamp)
{
// 使用原子操作增加序列号
_sequence = Interlocked.Increment(ref _sequence);
if (_sequence > 999999) // 序列号最大值6位
{
// 等待下一毫秒
while (timestamp <= _lastTimestamp)
{
timestamp = DateTime.UtcNow.Ticks;
}
}
}
else
{
_sequence = 0; // 重置序列号
}
_lastTimestamp = timestamp;
// 生成 ID时间戳和序列号拼接
return (timestamp - _epoch) * 1000 + _sequence; // 返回 ID
}
}
}

View File

@@ -41,7 +41,8 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
this.OnExceptionTracking = onExceptionTracking;
this.ArgNotNull = ArgNotNull;
this.useMsgData = parameterInfos.Select(p => p.GetCustomAttribute<UseMsgDataAttribute>() != null).ToArray();
this.useData = parameterInfos.Select(p => p.GetCustomAttribute<UseDataAttribute>() != null).ToArray();
this.useMsgId = parameterInfos.Select(p => p.GetCustomAttribute<UseMsgIdAttribute>() != null).ToArray();
#if NET5_0_OR_GREATER
this.IsCheckArgNotNull = parameterInfos.Select(p => p.GetCustomAttribute<NotNullAttribute>() != null).ToArray();
#endif
@@ -101,17 +102,24 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
/// </summary>
private readonly Type[] ParameterType;
/// <summary>
/// 是否使用整体data参数
/// 是否使Data整体内容作为入参参数
/// </summary>
private readonly bool[] useMsgData;
private readonly bool[] useData;
/// <summary>
/// 是否使用消息ID作为入参参数
/// </summary>
private readonly bool[] useMsgId;
/// <summary>
/// 是否检查变量为空
/// </summary>
private readonly bool[] IsCheckArgNotNull;
//private object ConvertArg(Type type, string argName )
//{
//}
public async void Handle(Func<object, Task> SendAsync, JObject jsonObject)
public async void Handle(Func<object, Task> SendAsync,string msgId, JObject jsonObject)
{
object[] args = new object[ParameterType.Length];
bool isCanInvoke = true;; // 表示是否可以调用方法
@@ -119,10 +127,17 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
{
var type = ParameterType[i];
var argName = ParameterName[i];
if (useMsgData[i])
#region DATA JSON数据
if (useData[i])
{
args[i] = jsonObject.ToObject(type);
}
#endregion
else if (useMsgId[i])
{
args[i] = msgId;
}
#region
else if (type.IsValueType)
{
var jsonValue = jsonObject.GetValue(argName);
@@ -143,7 +158,9 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
break;
}
}
}
}
#endregion
#region
else if (type.IsClass)
{
var jsonValue = jsonObject.GetValue(argName);
@@ -164,7 +181,9 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
break;
}
}
}
}
#endregion
#region
else if (type.IsGenericType) // 传递SendAsync委托
{
if (type.IsAssignableFrom(typeof(Func<object, Task>)))
@@ -198,7 +217,8 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
await SendAsync.Invoke(jsonText);
});
}
}
}
#endregion
}
if (!isCanInvoke)
@@ -212,8 +232,6 @@ 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)
{
@@ -233,34 +251,30 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
{
result = null;
await Console.Out.WriteLineAsync(ex.Message);
this.OnExceptionTracking.Invoke(ex, (async data =>
this.OnExceptionTracking.Invoke(ex, (async exData =>
{
var jsonText = JsonConvert.SerializeObject(data);
await SendAsync.Invoke(jsonText);
await SendAsync.Invoke(exData);
}));
}
//sw.Stop();
//Console.WriteLine($"Emit Invoke{sw.ElapsedTicks * 1000000F / Stopwatch.Frequency:n3}μs");
if(result is null)
if (Module.IsReturnValue)
{
return;
}
else
{
if (Module.IsReturnValue)
if (result is null)
{
_ = SendAsync.Invoke(result);
result = "null";
}
_ = SendAsync.Invoke(result);
}
//if( && result != null && result.GetType().IsClass)
//{
// //var reusltJsonText = JsonConvert.SerializeObject(result);
// //_ = SendAsync.Invoke($"{reusltJsonText}");
//}
}

View File

@@ -19,21 +19,27 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
/// <summary>
/// Json消息处理模块
/// </summary>
public WebSocketHandleModule(string ThemeJsonKey, string DataJsonKey)
public WebSocketHandleModule(string themeJsonKey, string dataJsonKey, string msgIdJsonKey)
{
this.ThemeJsonKey = ThemeJsonKey;
this.DataJsonKey = DataJsonKey;
this.ThemeJsonKey = themeJsonKey;
this.DataJsonKey = dataJsonKey;
this.MsgIdJsonKey = msgIdJsonKey;
}
/// <summary>
/// 指示处理模块该使用json中的哪个key作为业务区别字段
/// 指示处理模块该使用 Json 中的哪个 Key 作为业务区别字段
/// </summary>
public string ThemeJsonKey { get; }
/// <summary>
/// 指示处理模块该使用json中的哪个key作为业务数据字段
/// 指示处理模块该使用 Json 中的哪个 Key 作为业务数据字段
/// </summary>
public string DataJsonKey { get; }
/// <summary>
/// 指示处理模块该使用 Json 中的哪个 Key 作为业务消息ID字段
/// </summary>
public string MsgIdJsonKey { get; }
/// <summary>
/// 存储处理数据的配置
@@ -88,34 +94,28 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
/// <summary>
/// 处理JSON数据
/// </summary>
/// <param name="tSendAsync"></param>
/// <param name="sendAsync"></param>
/// <param name="jsonObject"></param>
public void HandleSocketMsg(Func<string, Task> tSendAsync, JObject jsonObject)
public void HandleSocketMsg(Func<string, Task> sendAsync, JObject jsonObject)
{
// 获取到消息
string themeKeyName = jsonObject.GetValue(ThemeJsonKey)?.ToString();
if (!MyHandleConfigs.TryGetValue(themeKeyName, out var handldConfig))
string theme = jsonObject.GetValue(ThemeJsonKey)?.ToString();
if (!MyHandleConfigs.TryGetValue(theme, out var handldConfig))
{
// 没有主题
return;
}
string msgId = jsonObject.GetValue(MsgIdJsonKey)?.ToString();
Func<object, Task> SendAsync = async (data) =>
{
var sendMsg = new
{
theme = themeKeyName,
token = "",
data = data,
};
var msg = JsonConvert.SerializeObject(sendMsg);
await tSendAsync(msg);
};
try
{
JObject dataObj = jsonObject.GetValue(DataJsonKey).ToObject<JObject>();
handldConfig.Handle(SendAsync, dataObj);
JObject dataObj = jsonObject.GetValue(DataJsonKey)?.ToObject<JObject>();
handldConfig.Handle(async (data) =>
{
await this.SendAsync(sendAsync, msgId, theme, data);
}, msgId, dataObj);
}
catch (Exception ex)
@@ -123,12 +123,64 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
Console.WriteLine($"error in ws : {ex.Message}{Environment.NewLine}json value:{jsonObject}");
return;
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="sendAsync"></param>
/// <param name="msgId"></param>
/// <param name="theme"></param>
/// <param name="data"></param>
/// <returns></returns>
public async Task SendAsync(Func<string, Task> sendAsync,string msgId, string theme, object data)
{
JObject jsonData;
if (data is null)
{
jsonData = new JObject()
{
[MsgIdJsonKey] = msgId,
[ThemeJsonKey] = theme,
};
}
else
{
JToken dataToken;
if ((data is System.Collections.IEnumerable || data is Array))
{
dataToken = JArray.FromObject(data);
}
else
{
dataToken = JObject.FromObject(data);
}
jsonData = new JObject()
{
[MsgIdJsonKey] = msgId,
[ThemeJsonKey] = theme,
[DataJsonKey] = dataToken
};
}
var msg = jsonData.ToString();
//Console.WriteLine(msg);
//Console.WriteLine();
await sendAsync.Invoke(msg);
}
}
}

View File

@@ -41,13 +41,14 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
/// </summary>
/// <param name="themeKeyName"></param>
/// <param name="dataKeyName"></param>
/// <param name="msgIdKeyName"></param>
/// <returns></returns>
private WebSocketHandleModule AddMyHandleModule(string themeKeyName, string dataKeyName)
private WebSocketHandleModule AddMyHandleModule(string themeKeyName, string dataKeyName, string msgIdKeyName)
{
var key = (themeKeyName, dataKeyName);
if (!MyHandleModuleDict.TryGetValue(key, out var myHandleModule))
{
myHandleModule = new WebSocketHandleModule(themeKeyName, dataKeyName);
myHandleModule = new WebSocketHandleModule(themeKeyName, dataKeyName, msgIdKeyName);
MyHandleModuleDict[key] = myHandleModule;
}
return myHandleModule;
@@ -93,8 +94,9 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
var themeKey = moduleAttribute.ThemeKey;
var dataKey = moduleAttribute.DataKey;
var msgIdKey = moduleAttribute.MsgIdKey;
var handlemodule = AddMyHandleModule(themeKey, dataKey);
var handleModule = AddMyHandleModule(themeKey, dataKey, msgIdKey);
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Select(method =>
{
@@ -135,7 +137,7 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
try
{
var jsonMsgHandleConfig = new JsonMsgHandleConfig(module, socketControlBase, method, onExceptionTracking, argNotNull);
var result = handlemodule.AddHandleConfigs(module,jsonMsgHandleConfig);
var result = handleModule.AddHandleConfigs(module,jsonMsgHandleConfig);
if (!result)
{
throw new Exception("添加失败,已经添加过相同的配置");
@@ -158,6 +160,7 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
/// <returns></returns>
public async Task HandleMsgAsync(Func<string, Task> SendAsync, string message)
{
//Console.WriteLine(message);
JObject json = JObject.Parse(message);
await Task.Run(() =>
{

View File

@@ -96,7 +96,7 @@ namespace Serein.Library.Network.WebSocketCommunication
{
var completeMessage = receivedMessage.ToString();
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, completeMessage); // 处理消息
Debug.WriteLine($"Received: {completeMessage}");
//Debug.WriteLine($"Received: {completeMessage}");
}
// 清空 StringBuilder 为下一条消息做准备

View File

@@ -180,10 +180,10 @@ namespace Serein.Library.Network.WebSocketCommunication
return;
}
Func<string, Task> SendAsync = async (text) =>
{
await WebSocketServer.SendAsync(webSocket, text);
};
//Func<string, Task> SendAsync = async (text) =>
//{
// await WebSocketServer.SendAsync(webSocket, text);
//};
var buffer = new byte[1024];
var receivedMessage = new StringBuilder(); // 用于拼接长消息
@@ -209,7 +209,7 @@ namespace Serein.Library.Network.WebSocketCommunication
if (result.MessageType == WebSocketMessageType.Close)
{
SendAsync = null;
//SendAsync = null;
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
if (IsCheckToken)
{
@@ -233,7 +233,10 @@ namespace Serein.Library.Network.WebSocketCommunication
}
// 消息处理
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, message); // 处理消息
_ = MsgHandleHelper.HandleMsgAsync(async (text) =>
{
await WebSocketServer.SendAsync(webSocket, text);
}, message); // 处理消息
}
// 清空 StringBuilder 为下一条消息做准备

View File

@@ -12,8 +12,8 @@
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>.\obj\g</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
@@ -30,6 +30,10 @@
<None Remove="Utils\SerinExpression\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="FlowNode\Attribute.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj" OutputItemType="Analyzer" />

View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Serein.Library.Network.WebSocketCommunication;
using System;
using System.Collections.Generic;
@@ -15,29 +16,52 @@ namespace Serein.Library.Utils
public class RemoteEnvControl
{
/// <summary>
/// 配置远程连接IP端口
/// 远程环境配置
/// </summary>
public RemoteEnvControl(string addres, int port, object token)
public class ControlConfiguration
{
this.Addres = addres;
this.Port = port;
this.Token = token;
/// <summary>
/// 远程环境的网络地址
/// </summary>
public string Addres { get; set; }
/// <summary>
/// 远程环境的对外端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 登录远程环境必须携带的token(可以为可序列化的JSON对象)
/// </summary>
public object Token { get; set; }
/// <summary>
/// 有关消息ID的 Json Key
/// </summary>
public string MsgIdJsonKey { get; set; }
/// <summary>
/// 有关消息主题的 Json Key
/// </summary>
public string ThemeJsonKey { get; set; }
/// <summary>
/// 有关数据的 Json Key
/// </summary>
public string DataJsonKey { get; set; }
}
/// <summary>
/// 远程环境的网络地址
/// 配置远程连接IP端口
/// </summary>
public string Addres { get; }
public RemoteEnvControl(ControlConfiguration controlConfiguration)
{
Config = controlConfiguration;
}
/// <summary>
/// 远程环境的对外端口
/// 配置信息
/// </summary>
public int Port { get; }
public ControlConfiguration Config { get; }
/// <summary>
/// 登录远程环境必须携带的token(可以为可序列化的JSON对象)
/// </summary>
public object Token { get; }
@@ -49,8 +73,8 @@ namespace Serein.Library.Utils
/// <summary>
/// 是否连接到了远程环境
/// </summary>
public bool IsConnectdRemoteEnv { get => isConnectdRemoteEnv; }
private bool isConnectdRemoteEnv = false;
//public bool IsConnectdRemoteEnv { get => isConnectdRemoteEnv; }
//private bool isConnectdRemoteEnv = false;
/// <summary>
/// 尝试连接到远程环境
@@ -59,12 +83,12 @@ namespace Serein.Library.Utils
public async Task<bool> ConnectAsync()
{
// 第2种WebSocket连接到远程环境实时接收远程环境的响应
Console.WriteLine($"准备连接:{Addres}:{Port},{Token}");
Console.WriteLine($"准备连接:{Config.Addres}:{Config.Port},{Config.Token}");
bool success = false;
try
{
var tcpClient = new TcpClient();
var result = tcpClient.BeginConnect(Addres, Port, null, null);
var result = tcpClient.BeginConnect(Config.Addres, Config.Port, null, null);
success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
}
finally
@@ -73,14 +97,14 @@ namespace Serein.Library.Utils
}
if (!success)
{
Console.WriteLine($"无法连通远程端口 {Addres}:{Port}");
Console.WriteLine($"无法连通远程端口 {Config.Addres}:{Config.Port}");
return false;
}
else
{
var url = $"ws://{Addres}:{Port}/";
var url = $"ws://{Config.Addres}:{Config.Port}/";
var result = await EnvClient.ConnectAsync(url); // 尝试连接远程环境
this.isConnectdRemoteEnv = result;
//this.isConnectdRemoteEnv = result;
return result;
}
}
@@ -90,18 +114,53 @@ namespace Serein.Library.Utils
/// <summary>
/// 发送消息
/// </summary>
/// <param name="msgId"></param>
/// <param name="theme"></param>
/// <param name="data"></param>
/// <returns></returns>
public async Task SendAsync(string theme, object data)
public async Task SendAsync(string msgId , string theme, object data)
{
var sendMsg = new
//var sendMsg = new
//{
// theme = theme,
// token = this.Token,
// data = data,
//};
//var msg = JsonConvert.SerializeObject(sendMsg);
JObject jsonData;
if (data is null)
{
theme = theme,
token = this.Token,
data = data,
};
var msg = JsonConvert.SerializeObject(sendMsg);
jsonData = new JObject()
{
[Config.MsgIdJsonKey] = msgId,
[Config.ThemeJsonKey] = theme,
};
}
else
{
JToken dataToken;
if (data is System.Collections.IEnumerable || data is Array)
{
dataToken = JArray.FromObject(data);
}
else
{
dataToken = JObject.FromObject(data);
}
jsonData = new JObject()
{
[Config.MsgIdJsonKey] = msgId,
[Config.ThemeJsonKey] = theme,
[Config.DataJsonKey] = dataToken
};
}
var msg = jsonData.ToString();
//Console.WriteLine(msg);
//Console.WriteLine();
await EnvClient.SendAsync(msg);
}
@@ -113,8 +172,6 @@ namespace Serein.Library.Utils
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Env
namespace Serein.NodeFlow.Env
{
/// <summary>
/// 消息主题

View File

@@ -1,28 +1,15 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Linq;
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Network.WebSocketCommunication;
using Serein.Library.Utils;
using Serein.Library.Utils.SereinExpression;
using Serein.NodeFlow.Model;
using Serein.NodeFlow.Tool;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Sockets;
using System.Numerics;
using System.Reflection;
using System.Security.Cryptography;
using System.Threading;
using System.Xml.Linq;
using static Serein.Library.Utils.ChannelFlowInterrupt;
using static Serein.NodeFlow.FlowStarter;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Serein.NodeFlow.Env
{
@@ -41,6 +28,7 @@ namespace Serein.NodeFlow.Env
public const string SpaceName = $"{nameof(Serein)}.{nameof(NodeFlow)}.{nameof(Model)}";
public const string ThemeKey = "theme";
public const string DataKey = "data";
public const string MsgIdKey = "msgid";
/// <summary>
/// 流程运行环境
@@ -80,10 +68,6 @@ namespace Serein.NodeFlow.Env
/// <summary>
/// 打开远程管理
/// </summary>
@@ -112,6 +96,7 @@ namespace Serein.NodeFlow.Env
Console.WriteLine("结束远程管理异常:" + ex);
}
}
#endregion
#region
@@ -347,7 +332,6 @@ namespace Serein.NodeFlow.Env
}
/// <summary>
/// 异步运行
/// </summary>
@@ -566,8 +550,17 @@ namespace Serein.NodeFlow.Env
}
else
{
MethodDetails? methodDetails = null;
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
{
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载项目时尝试获取方法信息
}
else
{
MethodDetailss.TryGetValue(nodeInfo.MethodName, out var methodDetails);// 加载项目时尝试获取方法信息
}
var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点
nodeModel.LoadInfo(nodeInfo); // 创建节点model
if (nodeModel is null)
@@ -575,6 +568,8 @@ namespace Serein.NodeFlow.Env
nodeInfo.Guid = string.Empty;
continue;
}
TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
if (nodeInfo.ChildNodeGuids?.Length > 0)
{
@@ -662,9 +657,6 @@ namespace Serein.NodeFlow.Env
}
/// <summary>
/// 加载远程环境
/// </summary>
@@ -679,7 +671,17 @@ namespace Serein.NodeFlow.Env
return (false, null);
}
// 没有连接远程环境,可以重新连接
var remoteEnvControl = new RemoteEnvControl(addres, port, token);
var controlConfiguration = new RemoteEnvControl.ControlConfiguration
{
Addres = addres,
Port = port,
Token = token,
ThemeJsonKey = FlowEnvironment.ThemeKey,
MsgIdJsonKey = FlowEnvironment.MsgIdKey,
DataJsonKey = FlowEnvironment.DataKey,
};
var remoteEnvControl = new RemoteEnvControl(controlConfiguration);
var result = await remoteEnvControl.ConnectAsync();
if (!result)
{
@@ -805,7 +807,6 @@ namespace Serein.NodeFlow.Env
}
}
TryAddNode(nodeModel);
nodeModel.Position = position;
@@ -1199,30 +1200,11 @@ namespace Serein.NodeFlow.Env
}
NodeValueChangeLogger.Add((nodeGuid, path, value));
var setExp = $"@Set .{path} = {value}"; // 生成 set 表达式
SerinExpressionEvaluator.Evaluate(setExp, nodeModel, out _); // 更改对应的数据
//Console.WriteLine($"本地环境收到数据更改通知:{value}");
//var getExp = $"@Get .{path}";
////Console.WriteLine($"取值表达式:{getExp}");
SerinExpressionEvaluator.Evaluate(setExp, nodeModel, out _); // 更改对应的数据
//var getResult = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _);
////Console.WriteLine($"原数据 :{getResult}");
//if (getResult.Equals(value))
//{
// Console.WriteLine("无须修改");
// return;
//}
//NodeValueChangeLogger.Add((nodeGuid, path, value));
//var setExp = $"@Set .{path} = {value}";
////Console.WriteLine($"设值表达式:{setExp}");
//SerinExpressionEvaluator.Evaluate(setExp, nodeModel, out _);
//getResult = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _);
//Console.WriteLine($"新数据 :{getResult}");
//Console.WriteLine($"Set表达式{setExp},result : {getResult}");
}

View File

@@ -1,14 +1,6 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using Serein.Library.Web;
using Serein.NodeFlow.Tool;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Env
{

View File

@@ -1,12 +1,6 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.NodeFlow.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Env
{

View File

@@ -1,12 +1,7 @@
using Newtonsoft.Json;
using Serein.Library;
using Serein.Library;
using Serein.Library.Network.WebSocketCommunication;
using Serein.Library.Network.WebSocketCommunication.Handle;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Env
{
@@ -17,33 +12,43 @@ namespace Serein.NodeFlow.Env
/// 客户端的消息管理(用于处理服务端的响应)
/// </summary>
[AutoSocketModule(ThemeKey = FlowEnvironment.ThemeKey, DataKey = FlowEnvironment.DataKey)]
[AutoSocketModule(ThemeKey = FlowEnvironment.ThemeKey,
DataKey = FlowEnvironment.DataKey,
MsgIdKey = FlowEnvironment.MsgIdKey)]
public class MsgControllerOfClient : ISocketHandleModule
{
public Guid HandleGuid => new Guid();
private readonly Func<string, object?, Task> SendCommandAsync;
// 消息主题data - task等待
private readonly Func<string, string, object?, Task> SendCommandFunc;
private readonly RemoteFlowEnvironment remoteFlowEnvironment;
public MsgControllerOfClient(RemoteFlowEnvironment remoteFlowEnvironment, Func<string, object?, Task> func)
public MsgControllerOfClient(RemoteFlowEnvironment remoteFlowEnvironment, Func<string, string, object?, Task> func)
{
this.remoteFlowEnvironment = remoteFlowEnvironment;
SendCommandAsync = func;
SendCommandFunc = func;
}
private async Task SendCommandAsync(string msgId, string theme, object? data)
{
await SendCommandFunc.Invoke(msgId, theme, data);
}
/// <summary>
/// 发送请求并等待远程环境响应
/// 发送请求
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException">超时触发</exception>
public async Task SendAsync(string signal, object? sendData = null, int overtimeInMs = 100)
public async Task SendAsync(string signal, object? data = null, int overtimeInMs = 100)
{
//Console.WriteLine($"指令[{signal}]value{JsonConvert.SerializeObject(sendData)}");
if (!DebounceHelper.CanExecute(signal, overtimeInMs))
{
return;
}
await SendCommandAsync.Invoke(signal, sendData);
var msgId = MsgIdHelper.GenerateId().ToString();
await SendCommandAsync(msgId, signal, data);
}
/// <summary>
@@ -51,11 +56,13 @@ namespace Serein.NodeFlow.Env
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException">超时触发</exception>
public async Task<TResult> SendAndWaitDataAsync<TResult>(string signal, object? sendData = null, int overtimeInMs = 50)
public async Task<TResult> SendAndWaitDataAsync<TResult>(string theme, object? data = null, int overtimeInMs = 50)
{
//Console.WriteLine($"指令[{signal}]value{JsonConvert.SerializeObject(sendData)}");
_ = SendCommandAsync.Invoke(signal, sendData);
return await remoteFlowEnvironment.WaitData<TResult>(signal);
var msgId = MsgIdHelper.GenerateId().ToString();
_ = SendCommandAsync(msgId, theme, data);
return await remoteFlowEnvironment.WaitData<TResult>(msgId);
//if (DebounceHelper.CanExecute(signal, overtimeInMs))
//{
@@ -86,63 +93,63 @@ namespace Serein.NodeFlow.Env
/// <summary>
/// 远程环境发来项目信息
/// </summary>
/// <param name="msgId"></param>
/// <param name="flowEnvInfo"></param>
[AutoSocketHandle(ThemeValue = EnvMsgTheme.GetEnvInfo)]
public void GetEnvInfo([UseMsgData] FlowEnvInfo flowEnvInfo)
public void GetEnvInfo([UseMsgId] string msgId, [UseData] FlowEnvInfo flowEnvInfo)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.GetEnvInfo, flowEnvInfo);
remoteFlowEnvironment.TriggerSignal(msgId, flowEnvInfo);
}
/// <summary>
/// 远程环境发来项目信息
/// </summary>
/// <param name="msgId"></param>
/// <param name="sereinProjectData"></param>
[AutoSocketHandle(ThemeValue = EnvMsgTheme.GetProjectInfo)]
public void GetProjectInfo([UseMsgData] SereinProjectData sereinProjectData)
public void GetProjectInfo([UseMsgId] string msgId, [UseData] SereinProjectData sereinProjectData)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.GetProjectInfo, sereinProjectData);
remoteFlowEnvironment.TriggerSignal(msgId, sereinProjectData);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.SetNodeInterrupt)]
public void SetNodeInterrupt()
public void SetNodeInterrupt([UseMsgId] string msgId)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.GetProjectInfo, null);
remoteFlowEnvironment.TriggerSignal(msgId, null);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.AddInterruptExpression)]
public void AddInterruptExpression()
public void AddInterruptExpression([UseMsgId] string msgId)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.AddInterruptExpression, null);
remoteFlowEnvironment.TriggerSignal(msgId, null);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.CreateNode)]
public void CreateNode([UseMsgData] NodeInfo nodeInfo)
public void CreateNode([UseMsgId] string msgId, [UseData] NodeInfo nodeInfo)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.CreateNode, nodeInfo);
remoteFlowEnvironment.TriggerSignal(msgId, nodeInfo);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveNode)]
public void RemoveNode(bool state)
public void RemoveNode([UseMsgId] string msgId, bool state)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.RemoveNode, state);
remoteFlowEnvironment.TriggerSignal(msgId, state);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.ConnectNode)]
public void ConnectNode(bool state)
public void ConnectNode([UseMsgId] string msgId, bool state)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.ConnectNode, state);
remoteFlowEnvironment.TriggerSignal(msgId, state);
}
[AutoSocketHandle(ThemeValue = EnvMsgTheme.RemoveConnect)]
public void RemoveConnect(bool state)
public void RemoveConnect([UseMsgId] string msgId, bool state)
{
remoteFlowEnvironment.TriggerSignal(EnvMsgTheme.RemoveConnect, state);
remoteFlowEnvironment.TriggerSignal(msgId, state);
}

View File

@@ -1,22 +1,18 @@
using Newtonsoft.Json.Linq;
using Serein.Library.Api;
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Network.WebSocketCommunication;
using Serein.Library.Network.WebSocketCommunication.Handle;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Env
{
/// <summary>
/// 服务端的消息管理(用于处理客户端的请求)
/// </summary>
[AutoSocketModule(ThemeKey = FlowEnvironment.ThemeKey, DataKey = FlowEnvironment.DataKey)]
[AutoSocketModule(ThemeKey = FlowEnvironment.ThemeKey,
DataKey = FlowEnvironment.DataKey,
MsgIdKey = FlowEnvironment.MsgIdKey)]
public class MsgControllerOfServer : ISocketHandleModule
{
/// <summary>
@@ -225,7 +221,7 @@ namespace Serein.NodeFlow.Env
/// <summary>
/// 获取当前环境信息(远程连接)
/// 获取当前环境信息
/// </summary>
/// <returns></returns>
[AutoSocketHandle(ThemeValue = EnvMsgTheme.GetEnvInfo)]
@@ -316,6 +312,7 @@ namespace Serein.NodeFlow.Env
var nodeInfo = await environment.CreateNodeAsync(nodeControlType, position, mdInfo); // 监听到客户端创建节点的请求
return nodeInfo;
}
/// <summary>
/// 从远程环境移除节点
/// </summary>
@@ -464,10 +461,6 @@ namespace Serein.NodeFlow.Env
}
}

View File

@@ -3,8 +3,6 @@ using Serein.Library.Api;
using Serein.Library.Utils;
using Serein.NodeFlow.Tool;
using System.Collections.Concurrent;
using System.Threading;
using System.Xml.Linq;
namespace Serein.NodeFlow.Env
{
@@ -104,9 +102,8 @@ namespace Serein.NodeFlow.Env
public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath)
{
Console.WriteLine("远程环境尚未实现的接口LoadProject");
//Console.WriteLine("远程环境尚未实现的接口LoadProject");
// dll面板
var libmds = flowEnvInfo.LibraryMds;
foreach (var lib in libmds)
@@ -143,8 +140,11 @@ namespace Serein.NodeFlow.Env
else
{
MethodDetails? methodDetails;
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 尝试获取方法信息
MethodDetails? methodDetails = null;
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
{
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载远程环境时尝试获取方法信息
}
var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载远程项目时创建节点
nodeModel.LoadInfo(nodeInfo); // 创建节点model
@@ -160,7 +160,6 @@ namespace Serein.NodeFlow.Env
{
regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids));
UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position)));
//OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position));
}
else
{
@@ -181,7 +180,6 @@ namespace Serein.NodeFlow.Env
continue;
}
// 存在节点
//OnNodeCreate?.Invoke(new NodeCreateEventArgs(childNode, true, item.region.Guid));
UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(childNode, true, item.region.Guid)));
}
}
@@ -252,7 +250,10 @@ namespace Serein.NodeFlow.Env
});
SetStartNode(projectData.StartNode);
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
UIContextOperation?.Invoke(() =>
{
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
});
}
private bool TryAddNode(NodeModelBase nodeModel)
@@ -394,7 +395,10 @@ namespace Serein.NodeFlow.Env
public void MoveNode(string nodeGuid, double x, double y)
{
OnNodeMoved.Invoke(new NodeMovedEventArgs(nodeGuid, x, y));
UIContextOperation.Invoke(() =>
{
OnNodeMoved.Invoke(new NodeMovedEventArgs(nodeGuid, x, y));
});
_ = msgClient.SendAsync(EnvMsgTheme.MoveNode,
new
{
@@ -404,13 +408,14 @@ namespace Serein.NodeFlow.Env
});
}
public void SetStartNode(string nodeGuid)
{
_ = msgClient.SendAsync(EnvMsgTheme.SetStartNode, new
{
nodeGuid
});
// UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(oldNodeGuid, StartNode.Guid)));
//UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(nodeGuid,nodeGuid)));
}
public async Task<bool> ConnectNodeAsync(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
@@ -440,13 +445,22 @@ namespace Serein.NodeFlow.Env
mdInfo = methodDetailsInfo,
});
MethodDetailss.TryGetValue(methodDetailsInfo.MethodName, out var methodDetails);// 加载项目时尝试获取方法信息
MethodDetails? methodDetails = null;
if (!string.IsNullOrEmpty(nodeInfo.MethodName))
{
MethodDetailss.TryGetValue(nodeInfo.MethodName, out methodDetails);// 加载远程环境时尝试获取方法信息
}
//MethodDetailss.TryGetValue(methodDetailsInfo.MethodName, out var methodDetails);// 加载项目时尝试获取方法信息
var nodeModel = FlowFunc.CreateNode(this, nodeControlType, methodDetails); // 远程环境下加载节点
nodeModel.LoadInfo(nodeInfo);
TryAddNode(nodeModel);
// 通知UI更改
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
UIContextOperation.Invoke(() =>
{
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
});
return nodeInfo;
}
@@ -460,10 +474,13 @@ namespace Serein.NodeFlow.Env
});
if (result)
{
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
UIContextOperation.Invoke(() =>
{
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
toNodeGuid,
connectionType,
NodeConnectChangeEventArgs.ConnectChangeType.Remote));
});
}
return result;
}
@@ -476,7 +493,10 @@ namespace Serein.NodeFlow.Env
});
if (result)
{
OnNodeRemove?.Invoke(new NodeRemoveEventArgs(nodeGuid));
UIContextOperation.Invoke(() =>
{
OnNodeRemove?.Invoke(new NodeRemoveEventArgs(nodeGuid));
});
}
else
{

View File

@@ -4,20 +4,38 @@ using Serein.Library.Api;
namespace Serein.NodeFlow.Model
{
/// <summary>
/// 组合条件节点(用于条件区域)
/// </summary>
public class CompositeConditionNode : NodeModelBase
[NodeProperty(ValuePath = NodeValuePath.Node)]
public partial class CompositeConditionNode : NodeModelBase
{
/// <summary>
/// 条件节点集合
/// </summary>
[PropertyInfo]
private List<SingleConditionNode> _conditionNodes;
}
/// <summary>
/// 组合条件节点(用于条件区域)
/// </summary>
public partial class CompositeConditionNode : NodeModelBase
{
public CompositeConditionNode(IFlowEnvironment environment):base(environment)
{
}
public List<SingleConditionNode> ConditionNodes { get; } = [];
public void AddNode(SingleConditionNode node)
{
if(ConditionNodes is null)
{
ConditionNodes = new List<SingleConditionNode>();
}
ConditionNodes.Add(node);
MethodDetails ??= node.MethodDetails;
}
@@ -93,6 +111,7 @@ namespace Serein.NodeFlow.Model
ParameterData = parameterData.ToArray(),
ErrorNodes = errorNodes.ToArray(),
ChildNodeGuids = ConditionNodes.Select(node => node.Guid).ToArray(),
Position = Position,
};
}

View File

@@ -1,35 +1,51 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils.SereinExpression;
using System.ComponentModel;
namespace Serein.NodeFlow.Model
{
/// <summary>
/// 条件节点(用于条件控件)
/// </summary>
public class SingleConditionNode : NodeModelBase
[NodeProperty(ValuePath = NodeValuePath.Node)]
public partial class SingleConditionNode : NodeModelBase
{
public SingleConditionNode(IFlowEnvironment environment):base(environment)
{
}
/// <summary>
/// 是否为自定义参数
/// </summary>
public bool IsCustomData { get; set; }
[PropertyInfo(IsNotification = true)]
private bool _isCustomData;
/// <summary>
/// 自定义参数值
/// </summary>
public object? CustomData { get; set; }
[PropertyInfo(IsNotification = true)]
private object? _customData;
/// <summary>
/// 条件表达式
/// </summary>
[PropertyInfo(IsNotification = true)]
private string _expression;
public string Expression { get; set; }
}
public partial class SingleConditionNode : NodeModelBase
{
public SingleConditionNode(IFlowEnvironment environment):base(environment)
{
this.IsCustomData = false;
this.CustomData = null;
this.Expression = "PASS";
}
//public override object? Executing(IDynamicContext context)
/// <summary>
/// 重写节点的方法执行
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public override Task<object?> ExecutingAsync(IDynamicContext context)
{
// 接收上一节点参数or自定义参数内容
@@ -94,46 +110,20 @@ namespace Serein.NodeFlow.Model
public override NodeModelBase LoadInfo(NodeInfo nodeInfo)
{
var node = this;
if (node != null)
node.Guid = nodeInfo.Guid;
this.Position = nodeInfo.Position;// 加载位置信息
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
{
node.Guid = nodeInfo.Guid;
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
{
Parameterdata? pd = nodeInfo.ParameterData[i];
node.IsCustomData = pd.State;
node.CustomData = pd.Value;
node.Expression = pd.Expression;
Parameterdata? pd = nodeInfo.ParameterData[i];
node.IsCustomData = pd.State;
node.CustomData = pd.Value;
node.Expression = pd.Expression;
}
}
return this;
}
//public override void Execute(DynamicContext context)
//{
// CurrentState = Judge(context, base.MethodDetails);
//}
//private bool Judge(DynamicContext context, MethodDetails md)
//{
// try
// {
// if (DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del))
// {
// object[] parameters = GetParameters(context, md);
// var temp = del.DynamicInvoke(parameters);
// //context.GetData(GetDyPreviousKey());
// return (bool)temp;
// }
// }
// catch (Exception ex)
// {
// Debug.Write(ex.Message);
// }
// return false;
//}
}

View File

@@ -1,23 +1,32 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils.SereinExpression;
using System.Reactive;
namespace Serein.NodeFlow.Model
{
/// <summary>
/// Expression Operation - 表达式操作
/// </summary>
public class SingleExpOpNode : NodeModelBase
[NodeProperty(ValuePath = NodeValuePath.Node)]
public partial class SingleExpOpNode : NodeModelBase
{
public SingleExpOpNode(IFlowEnvironment environment) : base(environment)
{
}
/// <summary>
/// 表达式
/// </summary>
public string Expression { get; set; }
[PropertyInfo(IsNotification = true)]
private string _expression;
}
public partial class SingleExpOpNode : NodeModelBase
{
public SingleExpOpNode(IFlowEnvironment environment) : base(environment)
{
}
//public override async Task<object?> Executing(IDynamicContext context)
public override Task<object?> ExecutingAsync(IDynamicContext context)
@@ -31,7 +40,7 @@ namespace Serein.NodeFlow.Model
object? result = null;
if (isChange)
{
result = newData;
result = newData;
}
else
{
@@ -52,7 +61,7 @@ namespace Serein.NodeFlow.Model
public override Parameterdata[] GetParameterdatas()
{
return [new Parameterdata{ Expression = Expression}];
return [new Parameterdata { Expression = Expression }];
}
@@ -60,13 +69,11 @@ namespace Serein.NodeFlow.Model
public override NodeModelBase LoadInfo(NodeInfo nodeInfo)
{
var node = this;
if (node != null)
this.Position = nodeInfo.Position;// 加载位置信息
node.Guid = nodeInfo.Guid;
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
{
node.Guid = nodeInfo.Guid;
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
{
node.Expression = nodeInfo.ParameterData[i].Expression;
}
node.Expression = nodeInfo.ParameterData[i].Expression;
}
return this;
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.16</Version>
<Version>1.0.17</Version>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
@@ -16,7 +16,10 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>.\obj\g</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
@@ -63,6 +66,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Serein.Library.MyGenerator\Serein.Library.NodeGenerator.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\Library.Core\Serein.Library.Core.csproj" />
<ProjectReference Include="..\Library.Framework\Serein.Library.Framework.csproj" />
<ProjectReference Include="..\Library\Serein.Library.csproj" />

View File

@@ -6,7 +6,8 @@ namespace Serein.NodeFlow.Tool
{
public class ObjDynamicCreateHelper
{// 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式)
{
// 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式)
static Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
public static object Resolve(Dictionary<string, object> properties, string typeName)

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Library
{
/// <summary>
/// 通过枚举来区分该怎么生成代码
/// </summary>
public enum NodeValuePath
{
/// <summary>
/// 默认值
/// </summary>
None,
/// <summary>
/// 节点本身
/// </summary>
Node,
/// <summary>
/// 节点对应的方法
/// </summary>
Method,
/// <summary>
/// 节点方法对应的入参
/// </summary>
Parameter,
/// <summary>
/// 节点的调试设置
/// </summary>
DebugSetting,
}
/// <summary>
/// 标识一个类中的某些字段需要生成相应代码
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public sealed class NodePropertyAttribute : Attribute
{
/// <summary>
/// <para>属性路径</para>
/// <para>CustomNode : 自定义节点</para>
/// </summary>
public NodeValuePath ValuePath = NodeValuePath.None;
}
/// <summary>
/// 自动生成环境的属性
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = true)]
public sealed class PropertyInfoAttribute : Attribute
{
/// <summary>
/// 是否通知UI
/// </summary>
public bool IsNotification = false;
/// <summary>
/// 是否使用Console.WriteLine打印
/// </summary>
public bool IsPrint = false;
/// <summary>
/// 是否禁止参数进行修改(初始化后不能再通过 Setter 修改)
/// </summary>
public bool IsProtection = false;
}
}

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
@@ -20,6 +21,8 @@ namespace Serein.Library.NodeGenerator
[Generator]
public class MyPropertyGenerator : IIncrementalGenerator
{
internal static NodePropertyAttribute NodeProperty = new NodePropertyAttribute();
internal static PropertyInfoAttribute PropertyInfo = new PropertyInfoAttribute();
/// <summary>
/// 初始化生成器,定义需要执行的生成逻辑。
@@ -48,7 +51,7 @@ namespace Serein.Library.NodeGenerator
// 检查类的特性列表,看看是否存在 MyClassAttribute
if (classDeclaration.AttributeLists
.SelectMany(attrList => attrList.Attributes)
.Any(attr => semanticModel.GetSymbolInfo(attr).Symbol?.ContainingType.Name == "AutoPropertyAttribute"))
.Any(attr => semanticModel.GetSymbolInfo(attr).Symbol?.ContainingType.Name == nameof(NodePropertyAttribute)))
{
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration); // 获取类的符号
var classInfo = classSymbol.BuildCacheOfClass();
@@ -127,7 +130,7 @@ namespace Serein.Library.NodeGenerator
sb.AppendLine($" public partial class {className} : System.ComponentModel.INotifyPropertyChanged");
sb.AppendLine(" {");
var path = classInfo["AutoPropertyAttribute"]["ValuePath"];
var path = classInfo[nameof(NodePropertyAttribute)]["ValuePath"];
//
@@ -156,10 +159,10 @@ namespace Serein.Library.NodeGenerator
var propertyName = field.ToPropertyName(); // 转为合适的属性名称
var attributeInfo = fieldKV.Value; // 缓存的特性信息
var isProtection = attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsProtection), "true"); // 是否为保护字段
var isProtection = attributeInfo.Search("PropertyInfo", "IsProtection", "true"); // 是否为保护字段
// 生成 getter / setter
sb.AppendLine(leadingTrivia);
sb.AppendLine($" public {fieldType} {propertyName}");
@@ -169,34 +172,40 @@ namespace Serein.Library.NodeGenerator
sb.AppendLine(" {");
sb.AppendLine($" if ({fieldName} {(isProtection ? "== default" : "!= value")})"); // 非保护的Setter
sb.AppendLine(" {");
if (attributeInfo.Search("PropertyInfo", "IsPrint", "true")) // 是否打印
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsPrint), "true")) // 是否打印
{
sb.AddCode(5, $"Console.WriteLine({fieldName});");
}
if (attributeInfo.Search("PropertyInfo", "IsNotification", "true")) // 是否通知
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsNotification), "true")) // 是否通知
{
if (classInfo.ExitsPath("NodeModelBase"))
if (classInfo.ExitsPath(nameof(NodeValuePath.Node))) // 节点 or 自定义节点
{
sb.AddCode(5, $"this.env?.NotificationNodeValueChangeAsync(this.Guid, .nameof({propertyName}), value);");
sb.AddCode(5, $"((NodeModelBase)this).Env?.NotificationNodeValueChangeAsync(this.Guid, nameof({propertyName}), value); // 通知远程环境属性发生改变了");
}
else if (classInfo.ExitsPath("MethodDetails"))
else if (classInfo.ExitsPath(nameof(NodeValuePath.Method))) // 节点方法详情
{
sb.AddCode(5, $"nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"MethodDetails.\"+nameof({propertyName}), value);");
sb.AddCode(5, $"nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"MethodDetails.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了");
}
else if (classInfo.ExitsPath("ParameterDetails"))
else if (classInfo.ExitsPath(nameof(NodeValuePath.Parameter))) // 节点方法入参参数描述
{
sb.AddCode(5, "nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"MethodDetails.ParameterDetailss[\"+$\"{Index}\"+\"]." + $"\"+nameof({propertyName}),value);");
sb.AddCode(5, "nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"MethodDetails.ParameterDetailss[\"+$\"{Index}\"+\"]." + $"\"+nameof({propertyName}),value); // 通知远程环境属性发生改变了");
}
else if (classInfo.ExitsPath("NodeDebugSetting"))
else if (classInfo.ExitsPath(nameof(NodeValuePath.DebugSetting))) // 节点的调试信息
{
sb.AddCode(5, $"nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"DebugSetting.\"+nameof({propertyName}), value);");
sb.AddCode(5, $"nodeModel?.Env?.NotificationNodeValueChangeAsync(nodeModel.Guid, \"DebugSetting.\"+nameof({propertyName}), value); // 通知远程环境属性发生改变了");
}
}
sb.AppendLine($" {fieldName} = value;");
sb.AppendLine($" OnPropertyChanged(); // 先更改属性,然后通知属性发生改变了");
sb.AppendLine($" SetProperty<{fieldType}>(ref {fieldName}, value); // 通知UI属性发生改变了");
//sb.AppendLine($" {fieldName} = value;");
//sb.AppendLine($" OnPropertyChanged(); // 通知UI属性发生改变了");
sb.AppendLine(" }");
sb.AppendLine(" }");
sb.AppendLine(" }"); // 属性的结尾大括号
//if (!isProtection && field.TryGetDefaultValue(out var defaultValue))
//{
// sb.AppendLine($" }} = {defaultValue}");
//}
}
@@ -206,19 +215,29 @@ namespace Serein.Library.NodeGenerator
sb.AppendLine(" /// </summary>");
sb.AppendLine(" public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;");
sb.AppendLine(" /// <summary>");
sb.AppendLine(" /// 略");
sb.AppendLine(" /// <para>此方法为自动生成</para>");
sb.AppendLine(" protected void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) ");
sb.AppendLine(" { ");
sb.AppendLine(" if (Equals(storage, value)) ");
sb.AppendLine(" { ");
sb.AppendLine(" return; ");
sb.AppendLine(" } ");
sb.AppendLine(" ");
sb.AppendLine(" storage = value; ");
sb.AppendLine(" OnPropertyChanged(propertyName); ");
sb.AppendLine(" } ");
sb.AppendLine(" /// <summary> ");
sb.AppendLine(" /// 略 ");
sb.AppendLine(" /// <para>此方法为自动生成</para> ");
sb.AppendLine(" /// </summary>");
sb.AppendLine(" /// <param name=\"propertyName\"></param>");
sb.AppendLine(" ");
sb.AppendLine(" protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)");
sb.AppendLine(" /// <param name=\"propertyName\"></param> ");
sb.AppendLine(" ");
sb.AppendLine(" protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) ");
sb.AppendLine(" {");
//sb.AppendLine(" Console.WriteLine(\"测试:\"+ propertyName);");
sb.AppendLine(" PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));");
sb.AppendLine(" PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); ");
sb.AppendLine(" }");
}
finally
{
@@ -347,7 +366,12 @@ namespace Serein.Library.NodeGenerator
{
var key = cata.Key;
var value = cata.Value.Value;
if (!attributeInfo.ContainsKey(key))
if (nameof(NodePropertyAttribute).Equals(attributeName))
{
string literal = Enum.GetName(typeof(NodeValuePath), cata.Value.Value);
attributeInfo.Add(key, literal);
}
else
{
attributeInfo.Add(key, value);
}
@@ -374,6 +398,29 @@ namespace Serein.Library.NodeGenerator
var propertyName = fieldName.StartsWith("_") ? char.ToUpper(fieldName[1]) + fieldName.Substring(2) : char.ToUpper(fieldName[0]) + fieldName.Substring(1); // 创建属性名称
return propertyName;
}
/// <summary>
/// 判断字段是否有默认值
/// </summary>
/// <param name="field"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public static bool TryGetDefaultValue(this FieldDeclarationSyntax field ,out string defaultValue)
{
if (field.Declaration.Variables.First().Initializer != null)
{
defaultValue = field.Declaration.Variables.First().Initializer.Value.ToString();
return true;
}
else
{
defaultValue = null;
return false;
}
}
/// <summary>
/// 判断字段是否为只读
/// </summary>
@@ -500,14 +547,13 @@ namespace Serein.Library.NodeGenerator
public static bool ExitsPath(this Dictionary<string, Dictionary<string, object>> classInfo, string valuePath)
{
// var path = classInfo["AutoPropertyAttribute"]["ValuePath"];
if (!classInfo.TryGetValue("AutoPropertyAttribute", out var keyValuePairs))
if (!classInfo.TryGetValue(nameof(NodePropertyAttribute), out var keyValuePairs))
{
return false;
}
if (!keyValuePairs.TryGetValue("ValuePath", out var value))
if (!keyValuePairs.TryGetValue(nameof(MyPropertyGenerator.NodeProperty.ValuePath), out var value))
{
return false;
}

View File

@@ -1,7 +1 @@
{
"profiles": {
"配置文件 2": {
"commandName": "DebugRoslynComponent"
}
}
}
{}

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsRoslynComponent>true</IsRoslynComponent>
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>SereinFow</Title>
@@ -12,7 +13,6 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />

View File

@@ -10,7 +10,9 @@ namespace Serein.Workbench
/// </summary>
public partial class App : Application
{
#if DEBUG
#endif
public static SereinProjectData? FlowProjectData { get; set; }
public static string FileDataPath { get; set; } = "";
@@ -66,7 +68,7 @@ namespace Serein.Workbench
}
#if DEBUG
else if(1 == 1)
else if(1 == 11)
{
//string filePath = @"F:\临时\project\new project.dnf";

View File

@@ -461,6 +461,11 @@ namespace Serein.Workbench
return;
}
if(nodeModelBase is null)
{
Console.WriteLine("OnNodeCreateEvent事件接收到意外的返回值");
return;
}
// MethodDetails methodDetailss = eventArgs.MethodDetailss;
PositionOfUI position = eventArgs.Position;
@@ -577,15 +582,15 @@ namespace Serein.Workbench
{
string nodeGuid = eventArgs.NodeGuid;
if (!TryGetControl(nodeGuid, out var nodeControl)) return;
if (eventArgs.Class == InterruptClass.None)
{
nodeControl.ViewModel.IsInterrupt = false;
}
else
{
nodeControl.ViewModel.IsInterrupt = true;
}
//if (eventArgs.Class == InterruptClass.None)
//{
// nodeControl.ViewModel.IsInterrupt = false;
//}
//else
//{
// nodeControl.ViewModel.IsInterrupt = true;
//}
foreach (var menuItem in nodeControl.ContextMenu.Items)
{
@@ -1203,35 +1208,48 @@ namespace Serein.Workbench
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void FlowChartCanvas_Drop(object sender, DragEventArgs e)
private void FlowChartCanvas_Drop(object sender, DragEventArgs e)
{
var canvasDropPosition = e.GetPosition(FlowChartCanvas); // 更新画布落点
PositionOfUI position = new PositionOfUI(canvasDropPosition.X, canvasDropPosition.Y);
if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas))
try
{
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeData nodeData)
var canvasDropPosition = e.GetPosition(FlowChartCanvas); // 更新画布落点
PositionOfUI position = new PositionOfUI(canvasDropPosition.X, canvasDropPosition.Y);
if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas))
{
await EnvDecorator.CreateNodeAsync(nodeData.NodeControlType, position, nodeData.MethodDetailsInfo); // 创建DLL文件的节点对象
}
}
else if (e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
{
if (e.Data.GetData(MouseNodeType.CreateBaseNodeInCanvas) is Type droppedType)
{
NodeControlType nodeControlType = droppedType switch
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeData nodeData)
{
Type when typeof(ConditionRegionControl).IsAssignableFrom(droppedType) => NodeControlType.ConditionRegion, // 条件区域
Type when typeof(ConditionNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpCondition,
Type when typeof(ExpOpNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpOp,
_ => NodeControlType.None,
};
if(nodeControlType != NodeControlType.None)
{
await EnvDecorator.CreateNodeAsync(nodeControlType, position); // 创建基础节点对象
Task.Run(async () =>
{
await EnvDecorator.CreateNodeAsync(nodeData.NodeControlType, position, nodeData.MethodDetailsInfo); // 创建DLL文件的节点对象
});
}
}
else if (e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
{
if (e.Data.GetData(MouseNodeType.CreateBaseNodeInCanvas) is Type droppedType)
{
NodeControlType nodeControlType = droppedType switch
{
Type when typeof(ConditionRegionControl).IsAssignableFrom(droppedType) => NodeControlType.ConditionRegion, // 条件区域
Type when typeof(ConditionNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpCondition,
Type when typeof(ExpOpNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpOp,
_ => NodeControlType.None,
};
if (nodeControlType != NodeControlType.None)
{
Task.Run(async () =>
{
await EnvDecorator.CreateNodeAsync(nodeControlType, position); // 创建基础节点对象
});
}
}
}
e.Handled = true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
e.Handled = true;
}
/// <summary>
@@ -1897,7 +1915,7 @@ namespace Serein.Workbench
//Console.WriteLine($"一共选取了{selectNodeControls.Count}个控件");
foreach (var node in selectNodeControls)
{
node.ViewModel.IsSelect =true;
//node.ViewModel.IsSelect =true;
// node.ViewModel.CancelSelect();
node.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFC700"));
node.BorderThickness = new Thickness(4);
@@ -1908,7 +1926,7 @@ namespace Serein.Workbench
IsSelectControl = false;
foreach (var nodeControl in selectNodeControls)
{
nodeControl.ViewModel.IsSelect = false;
//nodeControl.ViewModel.IsSelect = false;
nodeControl.BorderBrush = Brushes.Black;
nodeControl.BorderThickness = new Thickness(0);
if (nodeControl.ViewModel.NodeModel.IsStart)

View File

@@ -40,6 +40,7 @@ namespace Serein.Workbench
else
{
FlowEnvironment = new FlowEnvironmentDecorator(uIContextOperation);
//_ = FlowEnvironment.StartRemoteServerAsync();
this.window = window;
}
}

View File

@@ -9,83 +9,97 @@ namespace Serein.Workbench.Node.ViewModel
public NodeControlViewModelBase(NodeModelBase nodeModel)
{
NodeModel = nodeModel;
MethodDetails = NodeModel.MethodDetails;
// 订阅来自 NodeModel 的通知事件
}
private NodeModelBase _nodeModelBase;
/// <summary>
/// 对应的节点实体类
/// </summary>
internal NodeModelBase NodeModel { get; }
private bool isSelect;
/// <summary>
/// 表示节点控件是否被选中
/// </summary>
internal bool IsSelect
public NodeModelBase NodeModel
{
get => isSelect;
set
get => _nodeModelBase; set
{
isSelect = value;
OnPropertyChanged();
if (value != null)
{
_nodeModelBase = value;
OnPropertyChanged();
}
}
}
//private bool isSelect;
///// <summary>
///// 表示节点控件是否被选中
///// </summary>
//internal bool IsSelect
//{
// get => isSelect;
// set
// {
// isSelect = value;
// OnPropertyChanged();
// }
//}
//private bool isInterrupt;
/////// <summary>
/////// 控制中断状态的视觉效果
/////// </summary>
//public bool IsInterrupt
//{
// get => NodeModel.DebugSetting.IsInterrupt;
// set
// {
// NodeModel.DebugSetting.IsInterrupt = value;
// OnPropertyChanged();
// }
//}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
//Console.WriteLine(propertyName);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// 使节点获得中断能力(以及是否启用节点)
/// </summary>
public NodeDebugSetting DebugSetting
{
get => NodeModel.DebugSetting;
set
{
if (value != null)
{
NodeModel.DebugSetting = value;
OnPropertyChanged();
}
}
}
//public NodeDebugSetting DebugSetting
//{
// get => Node.DebugSetting;
// set
// {
// if (value != null)
// {
// Node.DebugSetting = value;
// OnPropertyChanged();
// }
// }
//}
/// <summary>
/// 使节点能够表达方法信息
/// </summary>
public MethodDetails MethodDetails
{
get => NodeModel.MethodDetails;
set
{
if(value != null)
{
NodeModel.MethodDetails = value;
OnPropertyChanged();
}
}
}
//public MethodDetails MethodDetails
//{
// get => Node.MethodDetails;
// set
// {
// if(value != null)
// {
// Node.MethodDetails = value;
// OnPropertyChanged();
// }
// }
//}
private bool isInterrupt;
/// <summary>
/// 控制中断状态的视觉效果
/// </summary>
public bool IsInterrupt
{
get => isInterrupt;
set
{
isInterrupt = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -21,17 +21,20 @@
<Grid>
<Grid.ToolTip>
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" />
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding NodeModel.MethodDetails.MethodTips}" />
</Grid.ToolTip>
<Border>
<!--<TextBlock Text="{Binding NodelModel.DebugSetting.IsInterrupt}}"></TextBlock>-->
<Border x:Name="InterruptBorder">
<Border.Style>
<Style TargetType="Border">
<!-- 默认无边框 -->
<!--默认无边框-->
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsInterrupt}" Value="True">
<DataTrigger Binding="{Binding Path=NodeModel.DebugSetting.IsInterrupt}" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="#80000000" />
@@ -48,15 +51,16 @@
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Background="#8DE9FD">
<CheckBox IsChecked="{Binding DebugSetting.IsEnable, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="{Binding MethodDetails.IsProtectionParameter, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<TextBlock Text="{Binding MethodDetails.MethodTips}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsEnable, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<TextBlock Text="{Binding NodeModel.MethodDetails.MethodTips, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}"/>
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding NodeModel.MethodDetails}"/>
<!-- ParameterProtectionMask 参数保护 -->
<!--取反 Visibility="{Binding DebugSetting.IsEnable, Converter={StaticResource InvertedBoolConverter}, ConverterParameter=Inverted}"-->
<Border Grid.Row="1" x:Name="ParameterProtectionMask" Background="LightBlue" Opacity="0.5" BorderBrush="#0A4651" BorderThickness="0"
Visibility="{Binding MethodDetails.IsProtectionParameter, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
Visibility="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay,
Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
<Grid Grid.Row="2" Background="#D5F0FC" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
@@ -66,7 +70,7 @@
<TextBlock Text="result" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Border Grid.Column="1" BorderThickness="1">
<TextBlock Text="{Binding MethodDetails.ReturnType}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBlock Text="{Binding NodeModel.MethodDetails.ReturnType, Mode=TwoWay}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Border>
</Grid>

View File

@@ -17,7 +17,7 @@
<Grid>
<Grid.ToolTip>
<ToolTip Background="LightYellow" Foreground="Black" Content="{Binding MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" />
<ToolTip Background="LightYellow" Foreground="Black" Content="{Binding NodeModel.MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" />
</Grid.ToolTip>
<Grid.RowDefinitions>
@@ -33,14 +33,14 @@
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding IsCustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <!--Converter={StaticResource BoolToVis}-->
<TextBox Grid.Column="1" MinWidth="50" Text="{Binding CustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
<CheckBox Grid.Column="0" IsChecked="{Binding NodeModel.IsCustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> <!--Converter={StaticResource BoolToVis}-->
<TextBox Grid.Column="1" MinWidth="50" Text="{Binding NodeModel.CustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Stretch" VerticalAlignment="Center">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsCustomData}" Value="True">
<DataTrigger Binding="{Binding NodeModel.IsCustomData}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
@@ -53,7 +53,7 @@
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsCustomData}" Value="False">
<DataTrigger Binding="{Binding NodeModel.IsCustomData}" Value="False">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
@@ -61,7 +61,7 @@
</TextBlock.Style>
</TextBlock>
</Grid>
<TextBox Grid.Row="2" Background="#f1F66F" MinWidth="100" Text="{Binding Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
<TextBox Grid.Row="2" Background="#f1F66F" MinWidth="100" Text="{Binding NodeModel.Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<!--<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />

View File

@@ -16,7 +16,7 @@
<StackPanel Grid.Row="0" Orientation="Vertical" Background="LightSteelBlue">
<TextBlock Grid.Row="2" Text="表达式"></TextBlock>
<TextBox Text="{Binding Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch"></TextBox>
<TextBox Text="{Binding NodeModel.Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch"></TextBox>
</StackPanel>
</Grid>
</local:NodeControlBase>

View File

@@ -22,7 +22,7 @@
<Grid>
<Grid.ToolTip>
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding MethodDetails.MethodName, UpdateSourceTrigger=PropertyChanged}" />
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding NodeModel.MethodDetails.MethodName, UpdateSourceTrigger=PropertyChanged}" />
</Grid.ToolTip>
<Grid.RowDefinitions>
@@ -32,15 +32,16 @@
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Background="#FCB334">
<CheckBox IsChecked="{Binding DebugSetting.IsEnable, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="{Binding MethodDetails.IsProtectionParameter, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsEnable, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<CheckBox IsChecked="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay}" VerticalContentAlignment="Center"/>
<TextBlock Text="{Binding MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{Binding NodeModel.MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />
<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding NodeModel.MethodDetails}" />
<Border Grid.Row="1" x:Name="ParameterProtectionMask" Background="LightBlue" Opacity="0.5" BorderBrush="#0A4651" BorderThickness="0"
Visibility="{Binding MethodDetails.IsProtectionParameter, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
Visibility="{Binding NodeModel.MethodDetails.IsProtectionParameter, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
<!--<Border Grid.Row="0" Background="#FCB334" >
</Border>-->
@@ -54,7 +55,7 @@
<TextBlock Text="result" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border Grid.Column="1" BorderThickness="1">
<TextBlock Text="{Binding MethodDetails.ReturnType}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBlock Text="{Binding NodeModel.MethodDetails.ReturnType}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Border>
</Grid>
<!--<themes:ConditionControl Grid.Row="2" ></themes:ConditionControl>-->

View File

@@ -1,4 +1,5 @@
using Serein.Library.Api;
using Serein.Library;
using Serein.Library.Api;
using Serein.Workbench.Node.ViewModel;
using System.Windows.Controls;
using System.Windows.Media;
@@ -13,9 +14,8 @@ namespace Serein.Workbench.Node.View
{
public NodeControlViewModelBase ViewModel { get; set; }
protected NodeControlBase()
{
this.Background = Brushes.Transparent;
}
@@ -23,6 +23,7 @@ namespace Serein.Workbench.Node.View
{
ViewModel = viewModelBase;
this.Background = Brushes.Transparent;
this.DataContext = viewModelBase;
}
}

View File

@@ -5,11 +5,20 @@ namespace Serein.Workbench.Node.ViewModel
{
public class ActionNodeControlViewModel : NodeControlViewModelBase
{
private readonly SingleActionNode node;
//public SingleActionNode NodelModel
//{
// get => (SingleActionNode)base.NodeModel; set
// {
// if (base.NodeModel == null)
// {
// base.NodeModel = value;
// }
// }
//}
public ActionNodeControlViewModel(SingleActionNode node):base(node)
{
this.node = node;
// this.NodelModel = node;
}
}
}

View File

@@ -8,32 +8,32 @@ namespace Serein.Workbench.Node.ViewModel
/// </summary>
public class ConditionNodeControlViewModel : NodeControlViewModelBase
{
private readonly SingleConditionNode singleConditionNode;
public new SingleConditionNode NodeModel { get; }
/// <summary>
/// 是否为自定义参数
/// </summary>
public bool IsCustomData
{
get => singleConditionNode.IsCustomData;
set { singleConditionNode.IsCustomData= value; OnPropertyChanged(); }
}
/// <summary>
/// 自定义参数值
/// </summary>
public object? CustomData
{
get => singleConditionNode.CustomData;
set { singleConditionNode.CustomData = value ; OnPropertyChanged(); }
}
/// <summary>
/// 表达式
/// </summary>
public string Expression
{
get => singleConditionNode.Expression;
set { singleConditionNode.Expression = value; OnPropertyChanged(); }
}
///// <summary>
///// 是否为自定义参数
///// </summary>
//public bool IsCustomData
//{
// get => Node.IsCustomData;
// set { Node.IsCustomData= value; OnPropertyChanged(); }
//}
///// <summary>
// /// 自定义参数值
// /// </summary>
//public object? CustomData
//{
// get => Node.CustomData;
// set { Node.CustomData = value ; OnPropertyChanged(); }
//}
///// <summary>
///// 表达式
///// </summary>
//public string Expression
//{
// get => Node.Expression;
// set { Node.Expression = value; OnPropertyChanged(); }
//}
/// <summary>
/// 条件节点
@@ -41,7 +41,7 @@ namespace Serein.Workbench.Node.ViewModel
/// <param name="node"></param>
public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
{
this.singleConditionNode = node;
this.NodeModel = node;
//IsCustomData = false;
//CustomData = "";
//Expression = "PASS";

View File

@@ -5,22 +5,22 @@ namespace Serein.Workbench.Node.ViewModel
{
public class ExpOpNodeViewModel: NodeControlViewModelBase
{
public readonly SingleExpOpNode node;
public new SingleExpOpNode NodeModel { get; }
public string Expression
{
get => node.Expression;
set
{
node.Expression = value;
OnPropertyChanged();
}
}
//public string Expression
//{
// get => node.Expression;
// set
// {
// node.Expression = value;
// OnPropertyChanged();
// }
//}
public ExpOpNodeViewModel(SingleExpOpNode node) : base(node)
public ExpOpNodeViewModel(SingleExpOpNode nodeModel) : base(nodeModel)
{
this.node = node;
this.NodeModel = nodeModel;
}
}
}

View File

@@ -5,10 +5,10 @@ namespace Serein.Workbench.Node.ViewModel
{
public class FlipflopNodeControlViewModel : NodeControlViewModelBase
{
private readonly SingleFlipflopNode node;
public new SingleFlipflopNode NodelModel { get;}
public FlipflopNodeControlViewModel(SingleFlipflopNode node) : base(node)
{
this.node = node;
this.NodelModel = node;
}
}
}

View File

@@ -0,0 +1,292 @@
<Project>
<PropertyGroup>
<AssemblyName>Serein.Workbench</AssemblyName>
<IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
<MSBuildProjectExtensionsPath>D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\</MSBuildProjectExtensionsPath>
<_TargetAssemblyProjectName>Serein.Workbench</_TargetAssemblyProjectName>
<RootNamespace>Serein.Workbench</RootNamespace>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>True</UseWPF>
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--<IsRoslynComponent>true</IsRoslynComponent>-->
</PropertyGroup>
<ItemGroup>
<Compile Remove="Node\NodeModel\**" />
<Compile Remove="Themes\Condition\**" />
<EmbeddedResource Remove="Node\NodeModel\**" />
<EmbeddedResource Remove="Themes\Condition\**" />
<None Remove="Node\NodeModel\**" />
<None Remove="Themes\Condition\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Node\FlipflopRegionControl.xaml.cs" />
<Compile Remove="Node\NodeBase.cs" />
<Compile Remove="Themes\ConditionControl.xaml.cs" />
<Compile Remove="Themes\ConditionControlModel.cs" />
<Compile Remove="Themes\ExplicitDataControl.xaml.cs" />
<Compile Remove="Themes\ObjectViewerControl1.xaml.cs" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Library.Core\Serein.Library.Core.csproj" />
<ProjectReference Include="..\Library.Framework\Serein.Library.Framework.csproj" />
<ProjectReference Include="..\Library\Serein.Library.csproj" />
<ProjectReference Include="..\NodeFlow\Serein.NodeFlow.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<Compile Update="Themes\MethodDetailsControl.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\Accessibility.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\Microsoft.CSharp.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\Microsoft.VisualBasic.Core.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\Microsoft.VisualBasic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\Microsoft.Win32.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\Microsoft.Win32.Registry.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\Microsoft.Win32.Registry.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\Microsoft.Win32.SystemEvents.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\mscorlib.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\netstandard.dll" />
<ReferencePath Include="C:\Users\Az\.nuget\packages\newtonsoft.json\13.0.3\lib\net6.0\Newtonsoft.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationCore.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.Aero.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.Aero2.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.AeroLite.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.Classic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.Luna.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationFramework.Royale.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\PresentationUI.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\ReachFramework.dll" />
<ReferencePath Include="D:\Project\C#\DynamicControl\SereinFlow\.Output\Release\net8.0\Serein.Library.Core.dll" />
<ReferencePath Include="D:\Project\C#\DynamicControl\SereinFlow\.Output\Release\net8.0\Serein.Library.dll" />
<ReferencePath Include="D:\Project\C#\DynamicControl\SereinFlow\.Output\Release\librarynet462\Serein.Library.Framework.dll" />
<ReferencePath Include="D:\Project\C#\DynamicControl\SereinFlow\.Output\Release\netstandard2.0\Serein.Library.NodeGenerator.dll" />
<ReferencePath Include="D:\Project\C#\DynamicControl\SereinFlow\.Output\Release\net8.0\Serein.NodeFlow.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.AppContext.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Buffers.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.CodeDom.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Collections.Concurrent.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Collections.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Collections.Immutable.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Collections.NonGeneric.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Collections.Specialized.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.Annotations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.DataAnnotations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.EventBasedAsync.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ComponentModel.TypeConverter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Configuration.ConfigurationManager.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Configuration.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Console.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Core.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Data.Common.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Data.DataSetExtensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Data.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.Contracts.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.Debug.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.DiagnosticSource.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.EventLog.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.FileVersionInfo.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.PerformanceCounter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.Process.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.StackTrace.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.TextWriterTraceListener.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.Tools.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.TraceSource.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Diagnostics.Tracing.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.DirectoryServices.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Drawing.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Drawing.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Dynamic.Runtime.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Formats.Asn1.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Formats.Tar.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Globalization.Calendars.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Globalization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Globalization.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Compression.Brotli.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Compression.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Compression.FileSystem.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Compression.ZipFile.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.FileSystem.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.FileSystem.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.FileSystem.DriveInfo.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.FileSystem.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.FileSystem.Watcher.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.IsolatedStorage.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.MemoryMappedFiles.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.IO.Packaging.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Pipes.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.Pipes.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.IO.UnmanagedMemoryStream.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Linq.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Linq.Expressions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Linq.Parallel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Linq.Queryable.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Memory.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Http.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Http.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.HttpListener.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Mail.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.NameResolution.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.NetworkInformation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Ping.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Quic.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Requests.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Security.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.ServicePoint.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.Sockets.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.WebClient.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.WebHeaderCollection.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.WebProxy.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.WebSockets.Client.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Net.WebSockets.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Numerics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Numerics.Vectors.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ObjectModel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Printing.dll" />
<ReferencePath Include="C:\Users\Az\.nuget\packages\system.reactive\6.0.1\lib\net6.0\System.Reactive.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.DispatchProxy.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Emit.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Emit.ILGeneration.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Emit.Lightweight.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Metadata.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Reflection.TypeExtensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Resources.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Resources.Reader.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Resources.ResourceManager.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Resources.Writer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.CompilerServices.Unsafe.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.CompilerServices.VisualC.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Handles.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.InteropServices.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.InteropServices.JavaScript.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.InteropServices.RuntimeInformation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Intrinsics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Loader.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Numerics.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Serialization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Serialization.Formatters.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Serialization.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Serialization.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Runtime.Serialization.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Claims.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Algorithms.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Cng.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Csp.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Encoding.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.OpenSsl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Pkcs.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Primitives.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.ProtectedData.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.X509Certificates.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Security.Cryptography.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Security.Permissions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Principal.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.Principal.Windows.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Security.SecureString.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ServiceModel.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ServiceProcess.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.Encoding.CodePages.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.Encoding.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.Encoding.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.Encodings.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.Json.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Text.RegularExpressions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Threading.AccessControl.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Channels.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Overlapped.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Tasks.Dataflow.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Tasks.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Tasks.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Tasks.Parallel.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Thread.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.ThreadPool.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Threading.Timer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Transactions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Transactions.Local.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.ValueTuple.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Web.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Web.HttpUtility.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Windows.Controls.Ribbon.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Windows.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Windows.Extensions.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Windows.Input.Manipulations.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Windows.Presentation.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\System.Xaml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.Linq.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.ReaderWriter.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.Serialization.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.XDocument.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.XmlDocument.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.XmlSerializer.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.XPath.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\ref\net8.0\System.Xml.XPath.XDocument.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\UIAutomationClient.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\UIAutomationClientSideProviders.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\UIAutomationProvider.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\UIAutomationTypes.dll" />
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\8.0.10\ref\net8.0\WindowsBase.dll" />
</ItemGroup>
<ItemGroup>
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\LogWindow.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\MainWindow.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\ActionNodeControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\ActionRegionControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\ConditionNodeControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\ConditionRegionControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\DllControlControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\ExpOpNodeControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Node\View\FlipflopNodeControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\InputDialog.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\IOCObjectViewControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\NodeTreeItemViewControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\NodeTreeViewControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\ObjectViewerControl.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\TypeViewerWindow.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\Themes\WindowDialogInput.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\App.g.cs" />
<Compile Include="D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\Release\net8.0-windows\GeneratedInternalTypeHelper.g.cs" />
</ItemGroup>
<ItemGroup>
<Analyzer Include="C:\Program Files\dotnet\sdk\9.0.100-rc.2.24474.11\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll" />
<Analyzer Include="C:\Program Files\dotnet\sdk\9.0.100-rc.2.24474.11\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.NetAnalyzers.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll" />
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\8.0.10\analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>