diff --git a/FlowEdit/FlowEdit (sqlsugar).7z b/FlowEdit/FlowEdit (sqlsugar).7z deleted file mode 100644 index 06184e8..0000000 Binary files a/FlowEdit/FlowEdit (sqlsugar).7z and /dev/null differ diff --git a/FlowStartTool/FlowEnv.cs b/FlowStartTool/FlowEnv.cs index 7186fa9..7faf082 100644 --- a/FlowStartTool/FlowEnv.cs +++ b/FlowStartTool/FlowEnv.cs @@ -35,14 +35,20 @@ namespace Serein.FlowStartTool // this.window = window; //} - Env = new FlowEnvironmentDecorator(uIContextOperation); + Env = new FlowEnvironmentDecorator(); + Env.SetUIContextOperation(uIContextOperation); Env.LoadProject(new FlowEnvInfo { Project = flowProjectData }, fileDataPath); // 加载项目 - // 获取环境输出 - Env.OnEnvOut += (infoType, value) => + if(Env is IFlowEnvironmentEvent @event) { - Console.WriteLine($"{DateTime.Now} [{infoType}] : {value}{Environment.NewLine}"); - }; + // 获取环境输出 + @event.OnEnvOut += (infoType, value) => + { + Console.WriteLine($"{DateTime.Now} [{infoType}] : {value}{Environment.NewLine}"); + }; + } + + await Env.StartRemoteServerAsync(7525); // 启动 web socket 监听远程请求 diff --git a/Library.Core/DbSql/DBSync.cs b/Library.Core/DbSql/DBSync.cs deleted file mode 100644 index c8abbbc..0000000 --- a/Library.Core/DbSql/DBSync.cs +++ /dev/null @@ -1,606 +0,0 @@ -using SqlSugar; -using System.ComponentModel; -using System.Net.Sockets; -using System.Reflection; - -namespace Serein.DbSql -{ - public enum DBSyncStart - { - /// - /// 无需同步 - /// - [Description("无需同步")] - NotNeed, - /// - /// 同步成功 - /// - [Description("同步成功")] - SyncSuccess, - /// - /// 同步失败 - /// - [Description("同步失败")] - SyncFailure, - /// - /// 连接异常 - /// - [Description("配置/连接异常")] - NetworkError, - /// - /// 没有同步事件 - /// - [Description("没有同步事件,请使用 DBSync.SetSyncDataEvent() 方法设置同步事件")] - NoEvent, - } - public enum DBSyncExType - { - [Description("连接异常")] - ConnectError, - [Description("读写异常")] - CrudError, - [Description("同步异常")] - SyncError, - } - - public class DBSyncConfig - { - public DBSyncConfig(ConnectionConfig primaryDBConfig, - ConnectionConfig secondaryDBConfig) - { - PrimaryDBConfig = primaryDBConfig; - SecondaryDBConfig = secondaryDBConfig; - } - /// - /// 主数据库IP - /// - //private string Host { get; } - /// - /// 主数据库端口 - /// - //private int Port { get; } - /// - /// 主数据库配置 - /// - private ConnectionConfig PrimaryDBConfig { get; } - /// - /// 从数据库配置 - /// - private ConnectionConfig SecondaryDBConfig { get; } - - public override string ToString() - { - return $"[主数据库配置]{PrimaryDBConfig.ConnectionString}" + Environment.NewLine + - $"[从数据库配置]{SecondaryDBConfig.ConnectionString}" + Environment.NewLine; - } - - /// - /// 检查网络状态 - /// - /// - public bool GetNetworkState() - { - var isOpen = DBSync.IsPortOpen(); // 数据库基类获取网络状态 - if (!isOpen) - { - DBSync.SetIsNeedSyncData(true); // 远程数据库查询失败,尝试本地数据库 - } - return isOpen; - } - - /// - /// 返回从数据库 - /// - /// - public SqlSugarClient GetSecondaryDB() - { - DBSync.SyncEvent.Wait(); - return new SqlSugarClient(SecondaryDBConfig); - } - - /// - /// 返回主数据库 - /// - /// - /// - public SqlSugarClient GetPrimaryDB() - { - try - { - // 等待同步事件 - DBSync.SyncEvent.Wait(); - // 检查主数据库连接状态 - if (!DBSync.IsPortOpen()) // 返回主数据库检测网络状态 - { - // Console.WriteLine($"主数据库无法连接,IP:{IP},端口:{Port}"); - DBSync.SetIsNeedSyncData(true); // 网络不可达 - - return null; - - } - - // 检查是否需要同步数据 - /*if (DBSync.GetIsNeedSyncData()) - { - var syncState = DBSync.StartSyncDataBase(); - if (syncState != DBSyncStart.SyncSuccess && syncState != DBSyncStart.NotNeed) - { - // Console.WriteLine($"获取读写客户端前,尝试同步时发生异常:{DBSync.GetDescription(syncState)}"); - return null; - } - }*/ - - // 返回主数据库客户端 - return new SqlSugarClient(PrimaryDBConfig); - } - catch // (Exception ex) - { - // Console.WriteLine($"发生异常:{ex.Message}"); - - return null; - - } - } - - - } - - /// - /// 数据库同步异常 - /// - public class DBSyncException : Exception - { - public DBSyncExType ExceptionType { get; private set; } - - public DBSyncException(DBSyncExType exceptionType) - { - ExceptionType = exceptionType; - } - - public DBSyncException(DBSyncExType exceptionType, string message) : base(message) - { - ExceptionType = exceptionType; - } - - public DBSyncException(DBSyncExType exceptionType, string message, Exception innerException) : base(message, innerException) - { - ExceptionType = exceptionType; - } - public override string ToString() - { - return $"异常: {ExceptionType}: {GetDescription(ExceptionType)}. Message: {Message}"; - } - public static string GetDescription(DBSyncExType value) - { - - FieldInfo field = value.GetType().GetField(value.ToString()); - - - - DescriptionAttribute attribute = (DescriptionAttribute)field.GetCustomAttribute(typeof(DescriptionAttribute)); - - - return attribute == null ? value.ToString() : attribute.Description; - } - - } - - - /// - /// 远程、本地数据库同步 - /// - public static class DBSync - { - /// - /// 主数据库配置 - /// - - private static ConnectionConfig PrimaryConfig { get; set; } - - /// - /// 从数据库配置 - /// - - private static ConnectionConfig SecondaryConfig { get; set; } - - /// - /// 主数据库IP - /// - - private static string Host { get; set; } - - /// - /// 主数据库端口 - /// - private static int Port { get; set; } - /// - /// 同步数据事件(远程数据库,本地数据库,是否执行成功) - /// - - private static Func SyncDataEvent { get; set; } - - - private static Action StateChangeEvent { get; set; } - - /// - /// 数据库设置锁 - /// - //private static object DBSetLock { get; set; } = new object(); - /// - /// 是否需要同步数据 - /// - private static bool IsNeedSyncData { get; set; } = false; - /// - /// 等待次数(执行了多少次操作后才尝试进行同步,设置为0容易影响性能) - /// - private static int WaitCount { get; set; } = 10; - - /// - /// 客户端获取计数 - /// - private static int CrudDBGetCount { get; set; } = 0; - /// - /// 同步端获取计数 - /// - private static int SyncDBGetCount { get; set; } = 0; - - - //public static ManualResetEventSlim SyncEvent { get; } = new ManualResetEventSlim(true); // 同步事件 - /// - /// 远程本地同步阻塞事件 - /// - public static FifoManualResetEvent SyncEvent { get; } = new FifoManualResetEvent(true); - /// - /// 数据同步锁 - /// - private static object SyncLock { get; } = new object(); - /// - /// 是否需要同步数据读写锁 - /// - private static readonly ReaderWriterLockSlim NeedSyncStateLock = new ReaderWriterLockSlim(); - - /// - /// 是否断开过,true=断开过,false=没有断开过 - /// 设置为 false 时自动检测网络情况,只有在网络正常的情况下才能成功设置为 true - /// - /// - public static void SetIsNeedSyncData(bool value) - { - if (value == IsNeedSyncData) - { - return; - } - //Console.WriteLine("变更数据库"); - // 写入锁 - NeedSyncStateLock.EnterWriteLock(); - try - { - if (value) - { - IsNeedSyncData = true; - return; - } - IsNeedSyncData = !IsPortOpen(); // 变更 是否同步 属性时获取网络状态 - } - finally - { - NeedSyncStateLock.ExitWriteLock(); - StateChangeEvent?.Invoke(IsNeedSyncData); - } - } - public static bool GetIsNeedSyncData() - { - // 读取锁 - NeedSyncStateLock.EnterReadLock(); - try - { - return IsNeedSyncData; //是否需要同步数据 - } - finally - { - NeedSyncStateLock.ExitReadLock(); - } - } - - - - /// - /// 配置主数据库 - /// - public static void PrimaryConnect(DbType dbType, string host, int port, string dbName, string user, string password) - { - Host = host; - Port = port; - PrimaryConfig = GetConnectionConfig(dbType, host, port.ToString(), dbName, user, password); - - /*SyncEvent.Wait(); - - if (true || IsPortOpen(host, port)) - { - // 目标端口打通时才会更改数据库配置 - lock (DBSetLock) - { - Host = host; - Port = port; - PrimaryConfig = GetConnectionConfig(dbType, host, port.ToString(), dbName, user, password); - } - } - else - { - throw new DBSyncException(DBSyncExType.ConnectError, $"主数据库配置失败,无法连接,目标配置:IP:{host},端口:{port},目标库名:{dbName},账户:{user}"); - }*/ - } - /// - /// 配置从数据库 - /// - public static void SecondaryConnect(DbType dbType, string host, int port, string dbName, string user, string password) - { - SecondaryConfig = GetConnectionConfig(dbType, host, port.ToString(), dbName, user, password); - - /*if (IsPortOpen(host, port)) - { - lock (DBSetLock) - { - SecondaryConfig = GetConnectionConfig(dbType, host, port.ToString(), dbName, user, password); - } - } - else - { - throw new DBSyncException(DBSyncExType.ConnectError, $"从数据库配置失败,无法连接,目标配置:{host},端口:{port},目标库名:{dbName},账户:{user}"); - }*/ - } - - /// - /// 尝试执行一次数据同步 - /// - public static bool SyncData() - { - SetIsNeedSyncData(true); - var state = StartSyncDataBase(true); // 手动同步 - return state == DBSyncStart.SyncSuccess || state == DBSyncStart.NotNeed; - } - - - - /// - /// 设置同步事件与等待次数。 - /// - /// 同步事件(需要手动同步数据) - /// 等待次数(执行了多少次操作后才尝试进行同步,设置为0容易影响性能) - public static void SetSyncEvent(Func syncDataEvent, int waitCount = 0) - { - SyncDataEvent = syncDataEvent; - WaitCount = waitCount; - } - /// - /// 设置状态变化事件 - /// - /// - /// - public static void SetStateChangeEvent(Action stateChangeEvent) - { - StateChangeEvent = stateChangeEvent; - } - - /// - /// 获取数据库配置(不推荐使用在除了Repository的地方外部调用) - /// - /// - public static DBSyncConfig GetSyncSqlConfig() - { - /*SyncEvent.Wait(); - */ - - if (GetIsNeedSyncData()) - { - _ = Task.Run(() => StartSyncDataBase()); // new了一个RepositoryBase时尝试同步数据 - } - - lock (SyncLock) - { - CrudDBGetCount++; - //Console.WriteLine($"获取客户端:{CrudDBGetCount}"); - return new DBSyncConfig(PrimaryConfig, SecondaryConfig); - } - } - - public static void ReSetCrudDb() - { - CrudDBGetCount--; - Task.Run(() => StartSyncDataBase()); // 释放数据库连接时尝试同步数据 - - /*if (GetIsNeedSyncData()) - { - - }*/ - // Console.WriteLine($"释放客户端:{CrudDBGetCount}"); - } - - public static DBSyncStart StartSyncDataBase(bool isAtOnce = false) - { - /*if (!isAtOnce && WaitCount > 0) - { - WaitCount--; - return DBSyncStart.NotNeed; - }*/ - - SyncEvent.Reset(); // 锁定线程,保证只有一个线程进入该方法 - - if (!GetIsNeedSyncData()) - { - SyncEvent.Set(); - return DBSyncStart.NotNeed; - } - - if (!IsPortOpen()) // 同步时获取网络状态 - { - SetIsNeedSyncData(true); - SyncEvent.Set(); - return DBSyncStart.NetworkError; - } - - - - if (SyncDataEvent == null) - { - SyncEvent.Set(); - return DBSyncStart.NoEvent; - } - - - lock (SyncLock) // 同步锁,避免其它符合进入条件的线程执行多次同步 - { - if (!GetIsNeedSyncData()) - { - SyncEvent.Set(); - return DBSyncStart.NotNeed; - } - Console.WriteLine("网络检测OK,准备同步数据"); - try - { - bool isSuccess = SyncDataEvent.Invoke(new SqlSugarClient(PrimaryConfig), new SqlSugarClient(SecondaryConfig)); - SetIsNeedSyncData(!isSuccess); - - if (isSuccess) - { - return DBSyncStart.SyncSuccess; - } - else - { - return DBSyncStart.SyncFailure; - } - } - catch (Exception ex) - { - // 记录异常日志 - Console.WriteLine($"同步数据时发生异常: {ex.Message}"); - return DBSyncStart.SyncFailure; - } - finally - { - SyncEvent.Set(); // 释放同步事件,以防止其他线程一直被阻塞 - } - } - - } - - - public static string GetDescription(DBSyncStart value) - { - - FieldInfo field = value.GetType().GetField(value.ToString()); - - - - DescriptionAttribute attribute = (DescriptionAttribute)field.GetCustomAttribute(typeof(DescriptionAttribute)); - - - return attribute == null ? value.ToString() : attribute.Description; - } - - /// - /// 检测目标地址是否打通 - /// - /// ip地址 - /// 端口号 - /// 超时时间 - /// - public static bool IsPortOpen(string ip, int port, int timeout = 300) - { - using (var client = new TcpClient()) - { - var result = client.ConnectAsync(ip, port); - try - { - var open = result.Wait(timeout); - return open; - } - catch (SocketException) - { - return false; - } - } - } - /// - /// 检测目标地址是否打通:主数据库IP和端口是否打通(true通,false断) - /// - /// 超时时间 - /// - public static bool IsPortOpen(int timeout = 300) - { - string ip = Host; - int port = Port; - using (var client = new TcpClient()) - { - bool isOpen = true; - try - { - var result = client.ConnectAsync(ip, port); - isOpen = result.Wait(timeout); - if (!isOpen) - { - //Console.WriteLine($"连接超时{ip},{port}"); - } - return isOpen; - } - catch - { - isOpen = false; - return isOpen; - } - finally - { - //Console.WriteLine("网络检测:" + isOpen); - } - } - } - - /// - /// 返回数据库连接串 - /// - /// 数据库类型 - /// 服务器IP地址 - /// 数据库名 - /// 登录账户 - /// 登录密码 - private static ConnectionConfig GetConnectionConfig(DbType dbType, string host, string port, string dbName, string name, string password) - { - ConnectionConfig config; - string ConnectionString; - switch (dbType) - { - case DbType.MySql: - ConnectionString = $"Server={host};DataBase={dbName};Port={port};UserId={name};Password={password};Persist Security Info=True;Allow Zero Datetime=True;Character Set=utf8;"; - config = new ConnectionConfig() - { - ConnectionString = ConnectionString,//连接符字串 - DbType = DbType.MySql, - IsAutoCloseConnection = true, - InitKeyType = InitKeyType.Attribute //从实体特性中读取主键自增列信息 - }; - - break; - case DbType.SqlServer: - ConnectionString = $"Server={host},{port};DataBase={dbName};uid={name};pwd={password}"; - config = new ConnectionConfig() - { - ConnectionString = ConnectionString,//连接符字串 - DbType = DbType.SqlServer, - IsAutoCloseConnection = true, - InitKeyType = InitKeyType.Attribute //从实体特性中读取主键自增列信息 - }; - break; - default: - - config = null; - - break; - } - - return config; - - - } - } - -} diff --git a/Library.Core/DbSql/FifoManualResetEvent.cs b/Library.Core/DbSql/FifoManualResetEvent.cs deleted file mode 100644 index ca9a8f4..0000000 --- a/Library.Core/DbSql/FifoManualResetEvent.cs +++ /dev/null @@ -1,71 +0,0 @@ -namespace Serein.DbSql -{ - /// - /// 线程阻塞 - /// - public class FifoManualResetEvent - { - private readonly object lockObj = new object(); - /// - /// 让线程按进入时间顺序调用 - /// - private readonly Queue waitQueue = new Queue(); - private bool isSet; - - public bool IsSet { get => isSet; set => isSet = value; } - - public FifoManualResetEvent(bool initialState = false) - { - IsSet = initialState; - } - - /// - /// 等待解锁 - /// - public void Wait() - { - lock (lockObj) - { - if (IsSet) - { - // 获取到了发送的信号,线程开始重新执行 - return; - } - - var currentThread = Thread.CurrentThread; - waitQueue.Enqueue(currentThread); - - while (!IsSet || waitQueue.Peek() != currentThread) - { - Monitor.Wait(lockObj); - } - - waitQueue.Dequeue(); - } - } - - /// - /// 发送信号 - /// - public void Set() - { - lock (lockObj) - { - IsSet = true; - Monitor.PulseAll(lockObj); - } - } - - /// - /// 锁定当前线程 - /// - public void Reset() - { - lock (lockObj) - { - IsSet = false; - } - } - } - -} diff --git a/Library.Core/DbSql/IRepositoryBase.cs b/Library.Core/DbSql/IRepositoryBase.cs deleted file mode 100644 index 1df6707..0000000 --- a/Library.Core/DbSql/IRepositoryBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Linq.Expressions; - -namespace Serein.DbSql -{ - public interface IRepositoryBase where TEntity : class, new() - { - TEntity GetModelByID(dynamic ID); - - int Add(TEntity Model); - - int Update(TEntity Model); - - bool DeleteByID(dynamic ID); - - bool Delete(Expression> where); - - int UpdateColumns(TEntity model, Expression> expression); - } -} diff --git a/Library.Core/DbSql/RepositoryBase.cs b/Library.Core/DbSql/RepositoryBase.cs deleted file mode 100644 index 0cd8253..0000000 --- a/Library.Core/DbSql/RepositoryBase.cs +++ /dev/null @@ -1,877 +0,0 @@ - -using Serein.DbSql; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json; -using SqlSugar; -using System.Data; -using System.Linq.Expressions; -using Serein.Tool; - -namespace Serein.Helper -{ - - // public class RepositoryBase : DataBase, IRepositoryBase where TEntity : class, new() - public class RepositoryBase : IRepositoryBase where TEntity : class, new() - { - public bool isHaveErr; - - public string ErrMsg = ""; - - public string filterName = "SubSystemName"; - ~RepositoryBase() - { - DBSync.ReSetCrudDb(); - } - public RepositoryBase() - { - } - /// - /// 是否优先使用本地数据库 - /// - public bool IsUseLoaclDB = false; - - - #region 数据库操作 泛型抽象方法 - - #region 优先查询 主数据库 - - /// - /// 无状态数据操作(查询)泛型抽象方法 - /// - /// - /// - /// - /// - public virtual T SyncExecuteRead(Func func) - { - var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置 - if (IsUseLoaclDB) - { - var secondaryDB = syncSqlConfig.GetSecondaryDB(); - return func.Invoke(secondaryDB); // 尝试查询本地数据库 - } - - - if (syncSqlConfig.GetNetworkState()) // 网络检测 - { - try - { - var primaryDB = syncSqlConfig.GetPrimaryDB(); - if (primaryDB != null) - { - return func.Invoke(primaryDB); // 尝试查询本地数据库 - } - else - { - Console.WriteLine("远程数据库不可用"); - } - } - catch(Exception ex) - { - DBSync.SetIsNeedSyncData(true); // 网络不可达 - Console.WriteLine(ex.ToString()); - } - } - - try - { - var secondaryDB = syncSqlConfig.GetSecondaryDB(); - return func.Invoke(secondaryDB); // 尝试查询本地数据库 - } - catch - { - throw new DBSyncException(DBSyncExType.CrudError, $"主从数据库不可用。\r\n {syncSqlConfig.ToString()} "); - } - } - /// - /// 无状态数据操作(查询)泛型抽象方法 - /// - /// - /// - /// - /// - public virtual T SyncExecuteRead(Func, T> func) - { - var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置 - - if (IsUseLoaclDB) - { - var secondaryDB = syncSqlConfig.GetSecondaryDB().GetSimpleClient(); - return func.Invoke(secondaryDB); // 尝试查询本地数据库 - } - - if (syncSqlConfig.GetNetworkState()) // 网络检测 - { - try - { - var primaryDB = syncSqlConfig.GetPrimaryDB()?.GetSimpleClient(); - if (primaryDB != null) - { - return func.Invoke(primaryDB); // 尝试查询远程数据库 - } - else - { - Console.WriteLine("远程数据库不可用"); - } - } - catch (Exception ex) - { - DBSync.SetIsNeedSyncData(true); // 网络不可达 - Console.WriteLine(ex.ToString()); - } - } - - try - { - var secondaryDB = syncSqlConfig.GetSecondaryDB().GetSimpleClient(); - return func.Invoke(secondaryDB); // 尝试查询本地数据库 - } - catch - { - throw new DBSyncException(DBSyncExType.CrudError, $"主从数据库不可用。\r\n {syncSqlConfig.ToString()} "); - } - } - - #endregion - - - #region 优先查询 从数据库 (已注释) - /* /// - /// 无状态数据操作(查询)泛型抽象方法 - /// - /// - /// - /// - /// - public virtual T ExecuteSyncOperation(Func func) - { - DBSync.SyncEvent.Wait(); - var secondaryDB = SyncSqlConfig.GetSecondaryDB(); - - try - { - return func.Invoke(secondaryDB); // 优先尝试查询本地数据库 - } - catch - { - try - { - var primaryDB = SyncSqlConfig.GetPrimaryDB(); - if (primaryDB != null) - { - if (SyncSqlConfig.GetNetworkState()) // 网络检测 - { - DBSync.SyncEvent.Wait(); - return func.Invoke(primaryDB); // 尝试查询远程数据库 - } - else - { - throw new DBSyncException(DBSyncExType.CrudError, "网络不可达,无法查询远程数据库。"); - } - } - else - { - throw new DBSyncException(DBSyncExType.CrudError, "远程数据库不可用。"); - } - } - catch - { - throw new DBSyncException(DBSyncExType.CrudError, $"远程数据库查询失败。\r\n {SyncSqlConfig.ToString()} "); - } - } - } - - /// - /// 无状态数据操作(查询)泛型抽象方法 - /// - /// - /// - /// - /// - public virtual T ExecuteSyncOperation(Func, T> func) - { - DBSync.SyncEvent.Wait(); - - var secondaryDB = SyncSqlConfig.GetSecondaryDB().GetSimpleClient(); - - try - { - return func.Invoke(secondaryDB); // 优先尝试查询本地数据库 - } - catch - { - // 本地数据库查询失败,尝试远程数据库 - try - { - var primaryDB = SyncSqlConfig.GetPrimaryDB()?.GetSimpleClient(); - if (primaryDB != null) - { - if (SyncSqlConfig.GetNetworkState()) // 网络检测 - { - DBSync.SyncEvent.Wait(); - return func.Invoke(primaryDB); // 尝试查询远程数据库 - } - else - { - throw new DBSyncException(DBSyncExType.CrudError, "网络不可达,无法查询远程数据库。"); - } - } - else - { - throw new DBSyncException(DBSyncExType.CrudError, "远程数据库不可用。"); - } - } - catch - { - throw new DBSyncException(DBSyncExType.CrudError, $"远程数据库查询失败。\r\n {SyncSqlConfig.ToString()} "); - } - } - } - */ - #endregion - - #region 增加、更新、删除 操作泛型方法 - /// - /// 有状态数据操作(更新、增加、删除)泛型抽象方法,优先操作本地数据库,操作远程数据库失败时调用DBSync.SetIsNeedSyncData(true); - /// - /// - /// - /// - /// - /// - public virtual T SyncExecuteCUD(Func func) - { - var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置 - var secondaryDB = syncSqlConfig.GetSecondaryDB(); - try - { - var secondaryResult = func.Invoke(secondaryDB); // 本地数据库操作 - if (IsUseLoaclDB) - { - return secondaryResult; - } - if (syncSqlConfig.GetNetworkState()) // 网络检测 - { - var primaryDB = syncSqlConfig.GetPrimaryDB(); - if(primaryDB != null) - { - var primaryResult = func.Invoke(primaryDB); // 远程数据库操作 - return primaryResult; - } - else - { - Console.WriteLine("远程数据库不可用"); - } - } - return secondaryResult; - } - catch (Exception ex) - { - Console.WriteLine("主从数据库不可用:" + ex.ToString()); - DBSync.SetIsNeedSyncData(true); - throw new DBSyncException(DBSyncExType.CrudError, $"主从数据库不可用。\r\n {syncSqlConfig.ToString()} "); - } - } - - public virtual T SyncExecuteCUD(Func, T> func) - { - var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置 - var secondaryDB = syncSqlConfig.GetSecondaryDB().GetSimpleClient(); - - try - { - var secondaryResult = func.Invoke(secondaryDB); // 本地数据库操作 - if (IsUseLoaclDB) - { - return secondaryResult; - } - if (syncSqlConfig.GetNetworkState()) // 网络检测 - { - var primaryDB = syncSqlConfig.GetPrimaryDB().GetSimpleClient(); - if(primaryDB != null) - { - var primaryResult = func.Invoke(primaryDB); // 远程数据库操作 - return primaryResult; - } - else - { - Console.WriteLine("远程数据库不可用"); - } - } - return secondaryResult; - } - catch (Exception ex) - { - Console.WriteLine("主从数据库不可用:" + ex.ToString()); - DBSync.SetIsNeedSyncData(true); - throw new DBSyncException(DBSyncExType.CrudError, $"主从数据库不可用。\r\n {syncSqlConfig.ToString()} "); - } - } - - - #endregion - - - public TEntity SyncRead(Func func) - { - return SyncExecuteRead(func); - } - - public bool SyncRead(Func func) - { - return SyncExecuteRead(func); - } - - public List SyncRead(Func> func) - { - return SyncExecuteRead(func); - } - - - /// - /// 查询返回实体 - /// - public TEntity SyncRead(Func, TEntity> func) - { - return SyncExecuteRead(func); - } - - /// - /// 查询返回实体列表 - /// - public List SyncRead(Func, List> func) - { - return SyncExecuteRead(func); - } - - public TEntity SyncCUD(Func func) - { - return SyncExecuteCUD(func); - } - - public int SyncCUD(Func func) - { - return SyncExecuteCUD(func); - } - - public bool SyncCUD(Func func) - { - return SyncExecuteCUD(func); - } - - public TEntity SyncSimpleCUD(Func, TEntity> func) - { - - return SyncExecuteCUD(func); - } - - public int SyncSimpleCUD(Func, int> func) - { - return SyncExecuteCUD(func); - } - - public bool SyncSimpleCUD(Func, bool> func) - { - return SyncExecuteCUD(func); - } - - - #endregion - - - - - public virtual TEntity GetModelByID(dynamic ID) - { - return SyncRead(db => db.GetById(ID)); - } - - public virtual TEntity GetModel(Expression> where) - { - try - { - return SyncRead(db => db.Queryable().Where(where).First()); //db.GetSingle(where)); - // GetSingle结果不能大于1 - } - catch (Exception ex) - { - - isHaveErr = true; - ErrMsg = ex.Message; - - return null; - - } - } - - - public virtual int Add(TEntity model) - { - try - { - return SyncCUD(db => db.Insertable(model).ExecuteCommand()); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - - - public virtual int AddAndReturnIndex(TEntity model) - { - try - { - return SyncCUD(db => db.Insertable(model).ExecuteReturnIdentity()); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - - - public virtual bool Exist(Expression> where) - { - try - { - return SyncRead(db => db.Queryable().Where(where).Take(1).Any()); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return false; - } - } - - - public int AddOrUpdate(TEntity model, string keyValue) - { - if (keyValue == "") - { - try - { - return SyncCUD(db => db.Insertable(model).ExecuteCommand()); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - return SyncCUD(db => db.Updateable(model).ExecuteCommand()); - } - - - public virtual int Update(TEntity model) - { - return SyncCUD(db => db.Updateable(model).ExecuteCommand()); - } - - - public virtual int UpdateColumns(TEntity model, Expression> expression) - { - //DatabaseSync.StartcaControls(); - try - { - return SyncCUD(db => db.Updateable(model).UpdateColumns(expression).ExecuteCommand()); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - - - public virtual bool DeleteByID(dynamic ID) - { - - //SyncCUD(db => db.Updateable().RemoveDataCache().ExecuteCommand()); - return SyncSimpleCUD(db => (bool)db.DeleteById(ID)); - } - - - public virtual bool Delete(Expression> where) - { - return SyncSimpleCUD(db => db.Delete(where)); - } - - - - public virtual string GetPageList(Pagination pagination, Expression> where = null) - - { - //DatabaseSync.StartcaControls(); - return new - { - rows = GetList(pagination, where), - total = pagination.total, - page = pagination.page, - records = pagination.records - }.ToJson(); - } - - - public virtual TEntity GetSingle(Expression> expression) - { - //DatabaseSync.StartcaControls(); - return SyncRead(db => db.Queryable().Filter(filterName, isDisabledGobalFilter: true).Single(expression)); - } - - - - public virtual List GetTop(int Top, Expression> expression, OrderByType _OrderByType = OrderByType.Asc, Expression> where = null, string selstr = "*") - - { - return SyncRead(db => db.Queryable().Select(selstr).WhereIF(where != null, where) - .Take(Top) - .OrderBy(expression, _OrderByType) - .Filter(filterName, isDisabledGobalFilter: true) - .ToList()); - } - - /// - /// 排序表达式所用的键,排序方式,搜索条件 - /// - /// - /// - /// - /// - - public virtual TEntity GetFirst(Expression> OrderExpression, OrderByType _OrderByType = OrderByType.Asc, Expression> where = null) - - { - return SyncRead(db => db.Queryable().Filter(filterName, isDisabledGobalFilter: true).WhereIF(where != null, where) - .OrderBy(OrderExpression, _OrderByType) - .First()); - } - - - public virtual List GetList(Pagination pagination, Expression> where = null) - - { - int totalNumber = 0; - List result = SyncRead(db => db.Queryable().WhereIF(where != null, where).OrderBy(pagination.sidx + " " + pagination.sord) - .Filter(filterName, isDisabledGobalFilter: true) - .ToPageList(pagination.page, pagination.rows, ref totalNumber)); - pagination.records = totalNumber; - return result; - } - - - - public virtual List GetList(Expression> where = null) - - { - return SyncRead(db => db.Queryable().WhereIF(where != null, where).Filter(filterName, isDisabledGobalFilter: true) - .ToList()); - } - - public virtual List GetList() - { - return SyncRead(db => db.Queryable().ToList()); - } - - - - - public virtual DataTable GetDataTable(Expression> where = null, Pagination pagination = null) - - - { - if (pagination != null) - { - return DataHelper.ListToDataTable(GetList(pagination, where)); - } - return DataHelper.ListToDataTable(GetList(where)); - } - - public virtual void UseFilter(SqlFilterItem item) - { - SyncCUD(db => - { - db.QueryFilter.Remove(item.FilterName); - db.QueryFilter.Add(item); - return 0; - }); - filterName = item.FilterName; - } - - - public virtual void ClearFilter() - { - SyncCUD(db => - { - db.QueryFilter.Clear(); - return 0; - }); - - - filterName = null; - - } - - - - - - - - - /* public void ReSetConnStr(string constr, SqlSugar.DbType _dbtype) - { - db = DBHelper.CreateDB(constr, _dbtype); - Sclient = db.GetSimpleClient(); - } - - - public virtual TEntity GetModelByID(dynamic ID) - { - return Sclient.GetById(ID); - } - - - public virtual TEntity GetModel(Expression> where) - { - try - { - return Sclient.GetSingle(where); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return null; - } - } - - - public virtual int Add(TEntity model) - { - try - { - return db.Insertable(model).ExecuteCommand(); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - - - public virtual int AddAndReturnIndex(TEntity model) - { - try - { - return db.Insertable(model).ExecuteReturnIdentity(); - } - catch (Exception ex) - { - isHaveErr = true; - ErrMsg = ex.Message; - return 0; - } - } - - - public virtual bool Exist(Expression> where) - { - return db.Queryable().Where(where).Take(1).Any(); - } - - - public int AddOrUpdate(TEntity model, string Keyvale) - { - if (Keyvale == "") - { - return db.Insertable(model).ExecuteCommand(); - } - return db.Updateable(model).ExecuteCommand(); - } - - - public virtual int Update(TEntity model) - { - return db.Updateable(model).ExecuteCommand(); - } - - - public virtual int UpdateColumns(TEntity model, Expression> expression) - { - return db.Updateable(model).UpdateColumns(expression).ExecuteCommand(); - } - - - public virtual bool DeleteByID(dynamic ID) - { - db.Updateable().RemoveDataCache().ExecuteCommand(); - return Sclient.DeleteById(ID); - } - - - public virtual bool Delete(Expression> where) - { - return Sclient.Delete(where); - } - - - public virtual string GetPageList(Pagination pagination, Expression> where = null) - { - return new - { - rows = GetList(pagination, where), - total = pagination.total, - page = pagination.page, - records = pagination.records - }.ToJson(); - } - - - public virtual TEntity GetSingle(Expression> expression) - { - return db.Queryable().Filter(filterName, isDisabledGobalFilter: true).Single(expression); - } - - - public virtual List GetTop(int Top, Expression> expression, OrderByType _OrderByType = OrderByType.Asc, Expression> where = null, string selstr = "*") - { - return db.Queryable().Select(selstr).WhereIF(where != null, where) - .Take(Top) - .OrderBy(expression, _OrderByType) - .Filter(filterName, isDisabledGobalFilter: true) - .ToList(); - } - - - public virtual TEntity GetFirst(Expression> OrderExpression, OrderByType _OrderByType = OrderByType.Asc, Expression> where = null) - { - return db.Queryable().Filter(filterName, isDisabledGobalFilter: true).WhereIF(where != null, where) - .OrderBy(OrderExpression, _OrderByType) - .First(); - } - - public virtual List GetList(Pagination pagination, Expression> where = null) - { - int totalNumber = 0; - List result = db.Queryable().WhereIF(where != null, where).OrderBy(pagination.sidx + " " + pagination.sord) - .Filter(filterName, isDisabledGobalFilter: true) - .ToPageList(pagination.page, pagination.rows, ref totalNumber); - pagination.records = totalNumber; - return result; - } - - - public virtual List GetList(Expression> where = null) - { - return db.Queryable().WhereIF(where != null, where).Filter(filterName, isDisabledGobalFilter: true) - .ToList(); - } - - public virtual List GetList() - { - return db.Queryable().ToList(); - } - - - public virtual DataTable GetDataTable(Expression> where = null, Pagination pagination = null) - { - if (pagination != null) - { - return DataHelper.ListToDataTable(GetList(pagination, where)); - } - return DataHelper.ListToDataTable(GetList(where)); - } - - public virtual void UseFilter(SqlFilterItem item) - { - db.QueryFilter.Remove(item.FilterName); - db.QueryFilter.Add(item); - filterName = item.FilterName; - } - - - public virtual void ClearFilter() - { - db.QueryFilter.Clear(); - filterName = null; - } - - public void BeginTran() - { - db.Ado.BeginTran(); - } - - public void CommitTran() - { - db.Ado.CommitTran(); - } - - public void RollbackTran() - { - db.Ado.RollbackTran(); - }*/ - } - public class Pagination - { - /// - /// 每页行数 - /// - public int rows { get; set; } - - /// - /// 当前页 - /// - public int page { get; set; } - - /// - /// /排序列 - /// - - public string sidx { get; set; } - - - /// - /// 排序类型 - /// - - public string sord { get; set; } - - - /// - /// 总记录数 - /// - public int records { get; set; } - - /// - /// 总页数 - /// - public int total - { - get - { - if (records > 0) - { - if (records % rows != 0) - { - return records / rows + 1; - } - - return records / rows; - } - return 0; - } - } - } - - -} diff --git a/Library.Core/Serein.Library.Core.csproj b/Library.Core/Serein.Library.Core.csproj deleted file mode 100644 index 0658f6b..0000000 --- a/Library.Core/Serein.Library.Core.csproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - 1.0.16 - net8.0 - enable - enable - D:\Project\C#\DynamicControl\SereinFlow\.Output - Library - True - SereinFow - Net8运行时需要添加的依赖 - README.md - https://github.com/fhhyyp/serein-flow - MIT - True - true - latest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - \ - - - True - \ - - - - - - - - - - - - diff --git a/Library.Framework/DynamicContext.cs b/Library.Framework/DynamicContext.cs deleted file mode 100644 index 5ff508d..0000000 --- a/Library.Framework/DynamicContext.cs +++ /dev/null @@ -1,188 +0,0 @@ -using Serein.Library.Api; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace Serein.Library.Framework.NodeFlow -{ - - - /// - /// 动态流程上下文 - /// - public class DynamicContext : IDynamicContext - { - public DynamicContext(/*ISereinIOC sereinIoc,*/ IFlowEnvironment flowEnvironment) - { - // SereinIoc = sereinIoc; - Env = flowEnvironment; - RunState = RunState.Running; - } - - private readonly string _guid = global::System.Guid.NewGuid().ToString(); - string IDynamicContext.Guid => _guid; - - /// - /// 运行环境 - /// - public IFlowEnvironment Env { get; } - - /// - /// 运行状态 - /// - public RunState RunState { get; set; } = RunState.NoStart; - - /// - /// 用来在当前流程上下文间传递数据 - /// - //public Dictionary ContextShareData { get; } = new Dictionary(); - public object Tag { get; set; } - - /// - /// 当前节点执行完成后,设置该属性,让运行环境判断接下来要执行哪个分支的节点。 - /// - public ConnectionInvokeType NextOrientation { get; set; } - - /// - /// 运行时异常信息 - /// - public Exception ExceptionOfRuning { get; set; } - - /// - /// 每个上下文分别存放节点的当前数据 - /// - private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); - - private readonly ConcurrentDictionary dictPreviousNodes = new ConcurrentDictionary(); - - /// - /// 设置运行时上一节点 - /// - /// 当前节点 - /// 上一节点 - public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode) - { - dictPreviousNodes.AddOrUpdate(currentNodeModel, (n1) => PreviousNode, (n1, n2) => PreviousNode); - } - - /// - /// 获取当前节点的运行时上一节点 - /// - /// - /// - public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel) - { - if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node)) - { - return node; - } - else - { - return null; - } - } - - /// - /// 获取节点当前数据 - /// - /// - public object GetFlowData(string nodeGuid) - { - if (dictNodeFlowData.TryGetValue(nodeGuid, out var data)) - { - return data; - } - else - { - return null; - } - } - - /// - /// 添加或更新当前节点数据 - /// - /// 节点 - /// 新的数据 - public void AddOrUpdate(string nodeGuid, object flowData) - { - // this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData); - this.dictNodeFlowData.AddOrUpdate(nodeGuid, n1 => flowData, (n1, n2)=> flowData); - } - - /// - /// 上一节点数据透传到下一节点 - /// - /// - public object TransmissionData(NodeModelBase nodeModel) - { - if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点 - { - if (dictNodeFlowData.TryGetValue(previousNode.Guid, out var data)) // 其次获取上一节点的数据 - { - return data; - //AddOrUpdate(nodeModel.Guid, data); // 然后作为当前节点的数据记录在上下文中 - } - } - return null; - } - - - /// - /// 结束流程 - /// - public void Exit() - { - foreach (var nodeObj in dictNodeFlowData.Values) - { - if (nodeObj is null) - { - continue; - } - else - { - if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable) - { - disposable?.Dispose(); - } - } - } - - if (Tag != null && typeof(IDisposable).IsAssignableFrom(Tag?.GetType()) && Tag is IDisposable tagDisposable) - { - tagDisposable?.Dispose(); - } - this.Tag = null; - this.dictNodeFlowData?.Clear(); - RunState = RunState.Completion; - } - // public NodeRunCts NodeRunCts { get; set; } - // public ISereinIOC SereinIoc { get; } - //public Task CreateTimingTask(Action action, int time = 100, int count = -1) - //{ - // if(NodeRunCts == null) - // { - // NodeRunCts = Env.IOC.Get(); - // } - // // 使用局部变量,避免捕获外部的 `action` - // Action localAction = action; - - // return Task.Run(async () => - // { - // for (int i = 0; i < count && !NodeRunCts.IsCancellationRequested; i++) - // { - // await Task.Delay(time); - // if (NodeRunCts.IsCancellationRequested) { break; } - // //if (FlowEnvironment.IsGlobalInterrupt) - // //{ - // // await FlowEnvironment.GetOrCreateGlobalInterruptAsync(); - // //} - // // 确保对局部变量的引用 - // localAction?.Invoke(); - // } - - // // 清理引用,避免闭包导致的内存泄漏 - // localAction = null; - // }); - //} - } -} diff --git a/Library.Framework/FlipflopContext.cs b/Library.Framework/FlipflopContext.cs deleted file mode 100644 index c4a9e2c..0000000 --- a/Library.Framework/FlipflopContext.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Serein.Library.Api; -using Serein.Library.Utils; -using System; -using System.Threading.Tasks; - -namespace Serein.Library.Framework.NodeFlow -{ - public static class FlipflopFunc - { - /// - /// 传入触发器方法的返回类型,尝试获取Task[Flipflop[]] 中的泛型类型 - /// - //public static Type GetFlipflopInnerType(Type type) - //{ - // // 检查是否为泛型类型且为 Task<> - // if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) - // { - // // 获取 Task<> 的泛型参数类型,即 Flipflop<> - // var innerType = type.GetGenericArguments()[0]; - - // // 检查泛型参数是否为 Flipflop<> - // if (innerType.IsGenericType && innerType.GetGenericTypeDefinition() == typeof(FlipflopContext<>)) - // { - // // 获取 Flipflop<> 的泛型参数类型,即 T - // var flipflopInnerType = innerType.GetGenericArguments()[0]; - - // // 返回 Flipflop<> 中的具体类型 - // return flipflopInnerType; - // } - // } - // // 如果不符合条件,返回 null - // return null; - //} - - public static bool IsTaskOfFlipflop(Type type) - { - // 检查是否为泛型类型且为 Task<> - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>)) - { - // 获取 Task<> 的泛型参数类型 - var innerType = type.GetGenericArguments()[0]; - if (innerType.IsGenericType && type.GetGenericTypeDefinition() == typeof(IFlipflopContext<>)) - { - var flipflop = type.GetGenericArguments()[0]; - return true; - } - - //// 检查泛型参数是否为 Flipflop<> - //if (innerType == typeof(FlipflopContext)) - ////if (innerType.IsGenericType && innerType.GetGenericTypeDefinition() == typeof(FlipflopContext<>)) - //{ - // return true; - //} - } - - return false; - } - } - - /// - /// 触发器上下文 - /// - public class FlipflopContext : IFlipflopContext - { - public FlipflopStateType State { get; set; } - - public TriggerDescription Type { get; set; } - public TResult Value { get; set; } - - public FlipflopContext(FlipflopStateType ffState) - { - State = ffState; - } - - public FlipflopContext(FlipflopStateType ffState, TResult value) - { - State = ffState; - Value = value; - } - } - - -} diff --git a/Library.Framework/Properties/AssemblyInfo.cs b/Library.Framework/Properties/AssemblyInfo.cs deleted file mode 100644 index c3ce276..0000000 --- a/Library.Framework/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Resources; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// 有关程序集的一般信息由以下 -// 控制。更改这些特性值可修改 -// 与程序集关联的信息。 -[assembly: AssemblyTitle("Serein.Library.Framework")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Serein.Library.Framework")] -[assembly: AssemblyCopyright("Copyright © 2024")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// 将 ComVisible 设置为 false 会使此程序集中的类型 -//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 -//请将此类型的 ComVisible 特性设置为 true。 -[assembly: ComVisible(false)] - -// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("73b272e8-222d-4d08-a030-f1e1db70b9d1")] - -// 程序集的版本信息由下列四个值组成: -// -// 主版本 -// 次版本 -// 生成号 -// 修订号 -// -//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 -//通过使用 "*",如下所示: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.1.4")] -[assembly: AssemblyFileVersion("1.0.1.5")] -[assembly: NeutralResourcesLanguage("")] diff --git a/Library.Framework/Serein.Library.Framework.csproj b/Library.Framework/Serein.Library.Framework.csproj deleted file mode 100644 index 332ba9c..0000000 --- a/Library.Framework/Serein.Library.Framework.csproj +++ /dev/null @@ -1,67 +0,0 @@ - - - - - Debug - AnyCPU - {73B272E8-222D-4D08-A030-F1E1DB70B9D1} - Library - Properties - Serein.Library.Framework - Serein.Library.Framework - v4.6.2 - 512 - true - - - - true - full - false - ..\.Output\Debug\librarynet462\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\.Output\Release\librarynet462\ - TRACE - prompt - 4 - ..\.Output\Release\librarynet462\Serein.Library.Framework.xml - - - - ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll - - - - - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - - - - - - - - - - - - - - - - {5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3} - Serein.Library - - - - \ No newline at end of file diff --git a/Library.Framework/packages.config b/Library.Framework/packages.config deleted file mode 100644 index c34824f..0000000 --- a/Library.Framework/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 84f6091..43e404f 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -710,7 +710,6 @@ namespace Serein.Library.Api /// void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial); - /// /// 加载项目文件 /// @@ -960,6 +959,11 @@ namespace Serein.Library.Api /// bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del); + /// + /// 提供设置UI上下文的能力 + /// + /// + void SetUIContextOperation(UIContextOperation uiContextOperation); /// /// 开始运行 diff --git a/Library/Enums/NodeType.cs b/Library/Enums/NodeType.cs index 90f211e..fdd5047 100644 --- a/Library/Enums/NodeType.cs +++ b/Library/Enums/NodeType.cs @@ -12,6 +12,7 @@ namespace Serein.Library /// public enum NodeType { + /// /// 初始化,流程启动时执行(不生成节点) /// 可以异步等待 @@ -28,6 +29,7 @@ namespace Serein.Library /// Exit, + /// /// 触发器节点,必须为标记在可异步等待的方法,建议与继承了 FlowTriggerk<TEnum> 的实例对象搭配使用 /// 方法返回值必须为Task<IFlipflopContext<TResult>>,若为其它返回值,将不会创建节点。 diff --git a/Library/FlowNode/ContainerFlowEnvironment.cs b/Library/FlowNode/ContainerFlowEnvironment.cs new file mode 100644 index 0000000..840b7ac --- /dev/null +++ b/Library/FlowNode/ContainerFlowEnvironment.cs @@ -0,0 +1,384 @@ +using Serein.Library.Api; +using Serein.Library.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.Library +{ + + /// + /// 不提供流程操作能力,仅提供容器功能 + /// + + public class ContainerFlowEnvironment : IFlowEnvironment, ISereinIOC + { + /// + /// 本地运行环境缓存的持久化实例 + /// + private Dictionary PersistennceInstance { get; } = new Dictionary(); + public ContainerFlowEnvironment() + { + + } + + private ISereinIOC sereinIOC => this; + public ISereinIOC IOC => sereinIOC; + + public string EnvName => throw new NotImplementedException(); + + public bool IsGlobalInterrupt => throw new NotImplementedException(); + + public bool IsControlRemoteEnv => throw new NotImplementedException(); + + public InfoClass InfoClass { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public RunState FlowState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public RunState FlipFlopState { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public IFlowEnvironment CurrentEnv => this; + + public UIContextOperation UIContextOperation { get; set; } + + /// + /// 设置在UI线程操作的线程上下文 + /// + /// + public void SetUIContextOperation(UIContextOperation uiContextOperation) + { + this.UIContextOperation = uiContextOperation; + } + + public void ActivateFlipflopNode(string nodeGuid) + { + throw new NotImplementedException(); + } + + public Task ChangeParameter(string nodeGuid, bool isAdd, int paramIndex) + { + throw new NotImplementedException(); + } + + public Task ConnectArgSourceNodeAsync(string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionArgSourceType argSourceType, int argIndex) + { + throw new NotImplementedException(); + } + + public Task ConnectInvokeNodeAsync(string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionInvokeType invokeType) + { + throw new NotImplementedException(); + } + + public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token) + { + throw new NotImplementedException(); + } + + public Task CreateNodeAsync(NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null) + { + throw new NotImplementedException(); + } + + public Task ExitFlowAsync() + { + throw new NotImplementedException(); + } + + public void ExitRemoteEnv() + { + throw new NotImplementedException(); + } + + public Task GetEnvInfoAsync() + { + throw new NotImplementedException(); + } + + public Task GetProjectInfoAsync() + { + throw new NotImplementedException(); + } + + public Task InvokeNodeAsync(IDynamicContext context, string nodeGuid) + { + throw new NotImplementedException(); + } + + public void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true) + { + throw new NotImplementedException(); + } + + public void LoadLibrary(string dllPath) + { + throw new NotImplementedException(); + } + + public bool LoadNativeLibraryOfRuning(string file) + { + throw new NotImplementedException(); + } + + public Task LoadNodeInfosAsync(List nodeInfos) + { + throw new NotImplementedException(); + } + + public void LoadProject(FlowEnvInfo flowEnvInfo, string filePath) + { + throw new NotImplementedException(); + } + + public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType) + { + throw new NotImplementedException(); + } + + public void MoveNode(string nodeGuid, double x, double y) + { + throw new NotImplementedException(); + } + + public void NodeLocated(string nodeGuid) + { + throw new NotImplementedException(); + } + + public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value) + { + throw new NotImplementedException(); + } + + public Task PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid) + { + throw new NotImplementedException(); + } + + public Task RemoveConnectArgSourceAsync(string fromNodeGuid, string toNodeGuid, int argIndex) + { + throw new NotImplementedException(); + } + + public Task RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType) + { + throw new NotImplementedException(); + } + + public Task RemoveNodeAsync(string nodeGuid) + { + throw new NotImplementedException(); + } + + public void SaveProject() + { + throw new NotImplementedException(); + } + + public Task SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType) + { + throw new NotImplementedException(); + } + + public Task SetStartNodeAsync(string nodeGuid) + { + throw new NotImplementedException(); + } + + public Task StartAsyncInSelectNode(string startNodeGuid) + { + throw new NotImplementedException(); + } + + public Task StartFlowAsync() + { + throw new NotImplementedException(); + } + + public Task StartRemoteServerAsync(int port = 7525) + { + throw new NotImplementedException(); + } + + public void StopRemoteServer() + { + throw new NotImplementedException(); + } + + public Task TakeOutNodeToContainerAsync(string nodeGuid) + { + throw new NotImplementedException(); + } + + public void TerminateFlipflopNode(string nodeGuid) + { + throw new NotImplementedException(); + } + + public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type) + { + throw new NotImplementedException(); + } + + public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del) + { + throw new NotImplementedException(); + } + + public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo) + { + throw new NotImplementedException(); + } + + public bool TryUnloadLibrary(string assemblyFullName) + { + throw new NotImplementedException(); + } + + public void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial) + { + throw new NotImplementedException(); + } + + + + #region IOC容器相关 + ISereinIOC ISereinIOC.Reset() + { + sereinIOC.Reset(); + lock (PersistennceInstance) + { + foreach (var kvp in PersistennceInstance) + { + IOC.RegisterPersistennceInstance(kvp.Key, kvp.Value); + } + } // 重置后重新登记 + return this; + } + + ISereinIOC ISereinIOC.Register(Type type, params object[] parameters) + { + sereinIOC.Register(type, parameters); + return this; + } + + ISereinIOC ISereinIOC.Register(params object[] parameters) + { + sereinIOC.Register(parameters); + return this; + } + + ISereinIOC ISereinIOC.Register(params object[] parameters) + { + sereinIOC.Register(parameters); + return this; + } + + //T ISereinIOC.GetOrRegisterInstantiate() + //{ + // return sereinIOC.GetOrRegisterInstantiate(); + + //} + + //object ISereinIOC.GetOrRegisterInstantiate(Type type) + //{ + // return sereinIOC.GetOrRegisterInstantiate(type); + //} + + object ISereinIOC.Get(Type type) + { + return sereinIOC.Get(type); + + } + T ISereinIOC.Get() + { + return (T)sereinIOC.Get(typeof(T)); + } + T ISereinIOC.Get(string key) + { + return sereinIOC.Get(key); + } + + + bool ISereinIOC.RegisterPersistennceInstance(string key, object instance) + { + if (PersistennceInstance.ContainsKey(key)) + { + return false; + } + PersistennceInstance.Add(key, instance); // 记录需要持久化的实例 + return sereinIOC.RegisterPersistennceInstance(key, instance); + } + + bool ISereinIOC.RegisterInstance(string key, object instance) + { + return sereinIOC.RegisterInstance(key, instance); + } + + + object ISereinIOC.Instantiate(Type type) + { + return sereinIOC.Instantiate(type); + } + T ISereinIOC.Instantiate() + { + return sereinIOC.Instantiate(); + } + ISereinIOC ISereinIOC.Build() + { + sereinIOC.Build(); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + + ISereinIOC ISereinIOC.Run(Action action) + { + sereinIOC.Run(action); + return this; + } + #endregion + + + } +} diff --git a/Library.Core/DynamicContext.cs b/Library/FlowNode/DynamicContext.cs similarity index 93% rename from Library.Core/DynamicContext.cs rename to Library/FlowNode/DynamicContext.cs index 7102b02..f80a63b 100644 --- a/Library.Core/DynamicContext.cs +++ b/Library/FlowNode/DynamicContext.cs @@ -1,8 +1,10 @@ using Serein.Library.Api; using Serein.Library.Utils; +using System; using System.Collections.Concurrent; +using System.Collections.Generic; -namespace Serein.Library.Core +namespace Serein.Library { /// @@ -52,7 +54,7 @@ namespace Serein.Library.Core /// /// 每个流程上下文分别存放节点的当前数据 /// - private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); + private readonly ConcurrentDictionary dictNodeFlowData = new ConcurrentDictionary(); /// /// 每个流程上下文存储运行时节点的调用关系 @@ -66,7 +68,7 @@ namespace Serein.Library.Core /// 上一节点 public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode) { - dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (_, _) => PreviousNode); + dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (o, n) => PreviousNode); } /// @@ -91,7 +93,7 @@ namespace Serein.Library.Core /// /// 节点 /// - public object? GetFlowData(string nodeGuid) + public object GetFlowData(string nodeGuid) { if (dictNodeFlowData.TryGetValue(nodeGuid, out var data)) { @@ -108,17 +110,17 @@ namespace Serein.Library.Core /// /// 节点 /// 新的数据 - public void AddOrUpdate(string nodeGuid, object? flowData) + public void AddOrUpdate(string nodeGuid, object flowData) { // this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData); - dictNodeFlowData.AddOrUpdate(nodeGuid, _ => flowData, (_, _) => flowData); + dictNodeFlowData.AddOrUpdate(nodeGuid, _ => flowData, (o,n ) => flowData); } /// /// 上一节点数据透传到下一节点 /// /// - public object? TransmissionData(NodeModelBase nodeModel) + public object TransmissionData(NodeModelBase nodeModel) { if (dictPreviousNodes.TryGetValue(nodeModel, out var previousNode)) // 首先获取当前节点的上一节点 { @@ -138,17 +140,17 @@ namespace Serein.Library.Core { foreach (var nodeObj in dictNodeFlowData.Values) { - if (nodeObj is not null) + if (nodeObj is null) + { + + } + else { if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable) { disposable?.Dispose(); } } - else - { - - } } if (Tag != null && typeof(IDisposable).IsAssignableFrom(Tag?.GetType()) && Tag is IDisposable tagDisposable) { diff --git a/Library.Core/FlipflopContext.cs b/Library/FlowNode/FlipflopContext.cs similarity index 97% rename from Library.Core/FlipflopContext.cs rename to Library/FlowNode/FlipflopContext.cs index 2b59544..885b86f 100644 --- a/Library.Core/FlipflopContext.cs +++ b/Library/FlowNode/FlipflopContext.cs @@ -1,7 +1,9 @@ using Serein.Library.Api; using Serein.Library.Utils; +using System; +using System.Threading.Tasks; -namespace Serein.Library.Core +namespace Serein.Library { public static class FlipflopFunc { diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index a64f74a..5a6d76e 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -1,7 +1,7 @@  - 1.0.19 + 1.1.0 net8.0;net462 D:\Project\C#\DynamicControl\SereinFlow\.Output diff --git a/Net462DllTest/LogicControl/ParkingLogicControl.cs b/Net462DllTest/LogicControl/ParkingLogicControl.cs index 578e95e..70b9260 100644 --- a/Net462DllTest/LogicControl/ParkingLogicControl.cs +++ b/Net462DllTest/LogicControl/ParkingLogicControl.cs @@ -1,7 +1,6 @@ using Net462DllTest.Trigger; using Serein.Library; using Serein.Library.Api; -using Serein.Library.Framework.NodeFlow; using System; using System.Threading.Tasks; diff --git a/Net462DllTest/LogicControl/PlcLogicControl.cs b/Net462DllTest/LogicControl/PlcLogicControl.cs index 6573bd9..25901b7 100644 --- a/Net462DllTest/LogicControl/PlcLogicControl.cs +++ b/Net462DllTest/LogicControl/PlcLogicControl.cs @@ -4,7 +4,6 @@ using Net462DllTest.Model; using Net462DllTest.Trigger; using Serein.Library; using Serein.Library.Api; -using Serein.Library.Framework.NodeFlow; using System; using System.Threading.Tasks; diff --git a/Net462DllTest/LogicControl/ViewLogicControl.cs b/Net462DllTest/LogicControl/ViewLogicControl.cs index 8819845..2d04f0d 100644 --- a/Net462DllTest/LogicControl/ViewLogicControl.cs +++ b/Net462DllTest/LogicControl/ViewLogicControl.cs @@ -3,7 +3,6 @@ using Net462DllTest.Signal; using Net462DllTest.Trigger; using Serein.Library; using Serein.Library.Api; -using Serein.Library.Framework.NodeFlow; using Serein.Library.Utils; using System; using System.Threading.Tasks; diff --git a/Net462DllTest/Net462DllTest.csproj b/Net462DllTest/Net462DllTest.csproj index 32c7fbf..886de87 100644 --- a/Net462DllTest/Net462DllTest.csproj +++ b/Net462DllTest/Net462DllTest.csproj @@ -96,10 +96,6 @@ - - {73B272E8-222D-4D08-A030-F1E1DB70B9D1} - Serein.Library.Framework - {5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3} Serein.Library diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 25e570b..fe32620 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -1,33 +1,16 @@ - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Serein.Library; +using Serein.Library; using Serein.Library.Api; -using Serein.Library.Core; -using Serein.Library.FlowNode; using Serein.Library.Utils; using Serein.Library.Utils.SereinExpression; using Serein.NodeFlow.Model; using Serein.NodeFlow.Tool; -using Serein.Script.Node; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Numerics; using System.Reactive; -using System.Reflection; -using System.Reflection.Metadata.Ecma335; -using System.Runtime.Loader; -using System.Security.AccessControl; using System.Text; -using System.Xml.Linq; namespace Serein.NodeFlow.Env { - - /// /// 运行环境 /// @@ -44,7 +27,7 @@ namespace Serein.NodeFlow.Env /// /// 流程运行环境 /// - public FlowEnvironment(UIContextOperation uiContextOperation) + public FlowEnvironment() { this.sereinIOC = new SereinIOC(); this.IsGlobalInterrupt = false; @@ -57,7 +40,6 @@ namespace Serein.NodeFlow.Env } }; - this.UIContextOperation = uiContextOperation; // 为加载的类库提供在UI线程上执行某些操作的封装工具类 this.FlowLibraryManagement = new FlowLibraryManagement(this); // 实例化类库管理 #region 注册基本节点类型 @@ -74,7 +56,6 @@ namespace Serein.NodeFlow.Env PersistennceInstance.Add(typeof(FlowInterruptTool).FullName, new FlowInterruptTool()); // 缓存流程实例 PersistennceInstance.Add(typeof(IFlowEnvironment).FullName, (FlowEnvironment)this); // 缓存流程实例 PersistennceInstance.Add(typeof(ISereinIOC).FullName, this); // 缓存容器服务 - PersistennceInstance.Add(typeof(UIContextOperation).FullName, uiContextOperation); // 缓存封装好的UI线程上下文 ReRegisterPersistennceInstance(); @@ -1242,6 +1223,21 @@ namespace Serein.NodeFlow.Env return FlowLibraryManagement.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails); } + /// + /// 设置在UI线程操作的线程上下文 + /// + /// + public void SetUIContextOperation(UIContextOperation uiContextOperation) + { + this.UIContextOperation = uiContextOperation; + var fullName = typeof(UIContextOperation).FullName; + if (!string.IsNullOrEmpty(fullName)) + { + PersistennceInstance[fullName] = uiContextOperation; // 缓存封装好的UI线程上下文 + + } + + } /// /// 移动了某个节点(远程插件使用) @@ -1401,6 +1397,8 @@ namespace Serein.NodeFlow.Env #endregion + + #region 流程依赖类库的接口 diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index bb0d442..9dfcaa3 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -12,9 +12,9 @@ namespace Serein.NodeFlow.Env /// public class FlowEnvironmentDecorator : IFlowEnvironment, IFlowEnvironmentEvent, ISereinIOC { - public FlowEnvironmentDecorator(UIContextOperation uiContextOperation) + public FlowEnvironmentDecorator() { - flowEnvironment = new FlowEnvironment(uiContextOperation); + flowEnvironment = new FlowEnvironment(); // 默认使用本地环境 currentFlowEnvironment = flowEnvironment; currentFlowEnvironmentEvent = flowEnvironment; @@ -511,7 +511,14 @@ namespace Serein.NodeFlow.Env { currentFlowEnvironment.TriggerInterrupt(nodeGuid, expression, type); } - + /// + /// 设置在UI线程操作的线程上下文 + /// + /// + public void SetUIContextOperation(UIContextOperation uiContextOperation) + { + currentFlowEnvironment.SetUIContextOperation(uiContextOperation); + } public bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del) { return currentFlowEnvironment.TryGetDelegateDetails(libraryName, methodName, out del); diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index c9da35f..27d7db3 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -1244,7 +1244,7 @@ namespace Serein.NodeFlow.Env del = null; return false; } - + /// /// 对象监视表达式 @@ -1268,7 +1268,14 @@ namespace Serein.NodeFlow.Env this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TriggerInterrupt"); } - + /// + /// 设置在UI线程操作的线程上下文 + /// + /// + public void SetUIContextOperation(UIContextOperation uiContextOperation) + { + // 无须实现 + } #endregion diff --git a/NodeFlow/FlowStarter.cs b/NodeFlow/FlowStarter.cs index 4958779..9e06786 100644 --- a/NodeFlow/FlowStarter.cs +++ b/NodeFlow/FlowStarter.cs @@ -1,9 +1,6 @@ using Serein.Library; using Serein.Library.Api; -using Serein.Library.Core; -using Serein.Library.Network.WebSocketCommunication; using Serein.Library.Utils; -using Serein.Library.Web; using Serein.NodeFlow.Model; using Serein.NodeFlow.Tool; using System.Collections.Concurrent; @@ -39,11 +36,7 @@ namespace Serein.NodeFlow public async Task StartFlowInSelectNodeAsync(IFlowEnvironment env, NodeModelBase startNode) { IDynamicContext context; -#if NET6_0_OR_GREATER - context = new Serein.Library.Core.DynamicContext(env); // 从起始节点启动流程时创建上下文 -#else - Context = new Serein.Library.Framework.DynamicContext(env); -#endif + context = new Serein.Library.DynamicContext(env); // 从起始节点启动流程时创建上下文 await startNode.StartFlowAsync(context); // 开始运行时从选定节点开始运行 context.Exit(); } @@ -93,12 +86,7 @@ namespace Serein.NodeFlow #region 选择运行环境的上下文 // 判断使用哪一种流程上下文 - IDynamicContext Context; -#if NET6_0_OR_GREATER - Context = new Serein.Library.Core.DynamicContext(env); // 从起始节点启动流程时创建上下文 -#else - Context = new Serein.Library.Framework.DynamicContext(env); -#endif + IDynamicContext Context = new Serein.Library.DynamicContext(env); // 从起始节点启动流程时创建上下文 #endregion #region 初始化运行环境的Ioc容器 @@ -342,7 +330,7 @@ namespace Serein.NodeFlow { try { - var context = new DynamicContext(env); // 启动全局触发器时新建上下文 + var context = new Library.DynamicContext(env); // 启动全局触发器时新建上下文 var newFlowData = await singleFlipFlopNode.ExecutingAsync(context); // 获取触发器等待Task context.AddOrUpdate(singleFlipFlopNode.Guid, newFlowData); await NodeModelBase.RefreshFlowDataAndExpInterrupt(context, singleFlipFlopNode, newFlowData); // 全局触发器触发后刷新该触发器的节点数据 diff --git a/NodeFlow/Serein.NodeFlow.csproj b/NodeFlow/Serein.NodeFlow.csproj index 18f57d9..77ad8e2 100644 --- a/NodeFlow/Serein.NodeFlow.csproj +++ b/NodeFlow/Serein.NodeFlow.csproj @@ -1,7 +1,7 @@  - 1.0.19 + 1.1.0 net8.0 enable enable @@ -47,6 +47,7 @@ + diff --git a/NodeFlow/Tool/ToCSharpCodeHelper.cs b/NodeFlow/Tool/ToCSharpCodeHelper.cs new file mode 100644 index 0000000..14e3050 --- /dev/null +++ b/NodeFlow/Tool/ToCSharpCodeHelper.cs @@ -0,0 +1,262 @@ +using Serein.Library; +using Serein.Library.Api; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Tool +{ + internal class ToCSharpCodeHelper + { + /// + /// 运行环境 + /// + private readonly IFlowEnvironment env; + /// + /// 环境中已加载的所有节点 + /// + private readonly List nodes; + /// + /// 获取流程启动时在不同时间点需要自动实例化的类型 + /// + private readonly Dictionary> autoRegisterTypes; + /// + /// 初始化方法 + /// + private readonly List initMethods; + /// + /// 加载时方法 + /// + private readonly List loadingMethods; + /// + /// 结束时方法 + /// + private readonly List exitMethods; + + /// + /// 开始运行(需要准备好方法信息) + /// + /// 运行环境 + /// 环境中已加载的所有节点 + /// 获取流程启动时在不同时间点需要自动实例化的类型 + /// 初始化方法 + /// 加载时方法 + /// 结束时方法 + /// + public ToCSharpCodeHelper(IFlowEnvironment env, + List nodes, + Dictionary> autoRegisterTypes, + List initMethods, + List loadingMethods, + List exitMethods) + { + this.env = env; + this.nodes = nodes; + this.autoRegisterTypes = autoRegisterTypes; + this.initMethods = initMethods; + this.loadingMethods = loadingMethods; + this.exitMethods = exitMethods; + } + + public string ToCode() + { + StringBuilder sb = new StringBuilder(); + + // 确认命名空间 + sb.AppendLine($"using System;"); + sb.AppendLine($"using System.Linq;"); + sb.AppendLine($"using System.Threading;"); + sb.AppendLine($"using System.Threading.Tasks;"); + sb.AppendLine($"using System.Collections.Concurrent;"); + sb.AppendLine($"using System.Collections.Generic;"); + sb.AppendLine($"using Serein.Library;"); + sb.AppendLine($"using Serein.Library.Api;"); + sb.AppendLine($"using Serein.NodeFlow;"); + sb.AppendLine( + """ + using System; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using System.Collections.Concurrent; + using System.Collections.Generic; + using Serein.Library; + using Serein.Library.Api; + using Serein.NodeFlow; + + // 这里添加引用 + + namespace NodeToCode + { + class Program + { + private readonly IFlowEnvironment env; // 流程运行环境 + """ + + DefineVariableCode() + // 这里定义变量 + """ + public void Main(string[] args) + { + """ + + MainOfCSharpCode() + // 这里初始化运行环境 + """ + } + """ + + BusinessOfCSharpCode() + // 流程逻辑代码 + """ + } + } + """ + ); + //sb.AppendLine($"public {returnType} {methodName}({parmasStr})"); + //sb.AppendLine($"{{"); + //sb.AppendLine($"}}"); + + return ""; + } + + public void Main(string[] args) { + var plcLoginControl = ioc.Get(); + var networkLoginControl = ioc.Get(); + + if(nodeModel.) + plcLoginControl.Init("", networkLoginControl.Func("","")) + + foreach (var md in ffMd) + { + Execution(md); + } + + + plcLoginControl.Init("129.123.41.21",123); + + } + + public void Execution(Action action) + { + + } + public object Execution(Func action) + { + + } + public async object Execution(Func task) + { + await task.Invoke(); + } + + private string MainOfCSharpCode() + { + + return ""; + } + private string BusinessOfCSharpCode() + { + // 定义变量 + + // 确定需要实例化的类型 + + // 实例化方法 + + // 确认调用的方法 + + // 确认开辟的线程 + return ""; + } + + private string DefineVariableCode() + { + + } + /* + + */ + + + public StringBuilder ToMethodCode(StringBuilder sb, string methodName, Type returnType, Type[] parmas) + { + var parmasStr = string.Join("," + Environment.NewLine, parmas.Select(t => $"{t} {t.Name.Replace('.', '_')}")); + sb.AppendLine($"public {returnType} {methodName}({parmasStr})"); + sb.AppendLine($"{{"); + sb.AppendLine($"}}"); + return sb; + } + + /// + /// 添加代码 + /// + /// 字符串构建器 + /// 缩进次数(4个空格) + /// 要添加的代码 + /// 字符串构建器本身 + private static StringBuilder AddCode(StringBuilder sb, + int retractCount = 0, + string code = "") + { + if (!string.IsNullOrWhiteSpace(code)) + { + var retract = new string(' ', retractCount * 4); + sb.AppendLine(retract + code); + } + return sb; + } + + public static IEnumerable SeparateLineIntoMultipleDefinitions(ReadOnlySpan line) + { + List definitions = new List(); + + bool captureIsStarted = false; + + int equalSignCount = 0; + int lastEqualSignPosition = 0; + int captureStart = 0; + int captureEnd = 0; + + for (int i = 0; i < line.Length; i++) + { + char c = line[i]; + + if (c != ',' && !char.IsWhiteSpace(c)) + { + if (captureIsStarted) + { + captureEnd = i; + } + + else + { + captureStart = i; + captureIsStarted = true; + } + + if (c == '=') + { + equalSignCount++; + lastEqualSignPosition = i; + } + } + else + { + if (equalSignCount == 1 && lastEqualSignPosition > captureStart && lastEqualSignPosition < captureEnd) + { + definitions.Add(line[captureStart..(captureEnd + 1)].ToString()); + } + + equalSignCount = 0; + captureIsStarted = false; + } + } + + if (captureIsStarted && equalSignCount == 1 && lastEqualSignPosition > captureStart && lastEqualSignPosition < captureEnd) + { + definitions.Add(line[captureStart..(captureEnd + 1)].ToString()); + } + + return definitions; + } + + } +} diff --git a/README.md b/README.md index 40bde3b..963ba40 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ 不定期在Bilibili个人空间上更新相关的视频。 https://space.bilibili.com/33526379 -# 暂停更新 Workbench(WPF)项目 -* 正在使用 Avalonia UI 重写该项目,Library 相关接口可能随时变动,重写进展不定时在个人空间更新。 + # 计划任务 2024年10月28日更新 * 重新完善远程管理与远程客户端的功能(目前仅支持远程修改节点属性、添加/移除节点、启动流程、停止流程) * 重新完善节点树视图、IOC容器对象视图(目前残废版) diff --git a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs index db42a7f..51d7909 100644 --- a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs +++ b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs @@ -521,7 +521,7 @@ namespace Serein.Library.NodeGenerator /// 通过条件检查缓存的信息,决定是否添加代码 /// 首先检查是否存在该特性,如果不存在,返回 false。 /// 然后检查是否存在属性,如果不存在,返回 false - /// 如果存在属性,则返回属性对应的值与 comparisonValue 进行比较,返回 + /// 如果存在属性,则返回属性对应的值与 comparisonValue 进行比较,返回 /// /// 若只传入 attributeName 参数,则只会检查是否存在该特性 /// 若只传入 attributeName与attributePropertyName 参数,则只会检查是否存在该特性的该属性 @@ -529,7 +529,7 @@ namespace Serein.Library.NodeGenerator /// 缓存的特性信息 /// 查询的特性名称 /// 查询的特性属性名称 - /// 比较值 + /// 比较方法 /// 如果存在查询项,返回 true ,否则返回 false public static bool Search(this Dictionary> dict, string attributeName = null, @@ -569,7 +569,6 @@ namespace Serein.Library.NodeGenerator var retract = new string(' ', retractCount * 4); sb.AppendLine(retract + code); } - return sb; } diff --git a/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj b/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj index e111244..fa5086e 100644 --- a/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj +++ b/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 1.0.1 + 1.1.0 true D:\Project\C#\DynamicControl\SereinFlow\.Output diff --git a/Serein.Workbench.Avalonia.Android/Icon.png b/Serein.Workbench.Avalonia.Android/Icon.png deleted file mode 100644 index 41a2a61..0000000 Binary files a/Serein.Workbench.Avalonia.Android/Icon.png and /dev/null differ diff --git a/Serein.Workbench.Avalonia.Android/MainActivity.cs b/Serein.Workbench.Avalonia.Android/MainActivity.cs deleted file mode 100644 index 7d5afa0..0000000 --- a/Serein.Workbench.Avalonia.Android/MainActivity.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Android.App; -using Android.Content.PM; - -using Avalonia; -using Avalonia.Android; - -namespace Serein.Workbench.Avalonia.Android; - -[Activity( - Label = "Serein.Workbench.Avalonia.Android", - Theme = "@style/MyTheme.NoActionBar", - Icon = "@drawable/icon", - MainLauncher = true, - ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] -public class MainActivity : AvaloniaMainActivity -{ - protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) - { - return base.CustomizeAppBuilder(builder) - .WithInterFont(); - } -} diff --git a/Serein.Workbench.Avalonia.Android/Properties/AndroidManifest.xml b/Serein.Workbench.Avalonia.Android/Properties/AndroidManifest.xml deleted file mode 100644 index a561c56..0000000 --- a/Serein.Workbench.Avalonia.Android/Properties/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/Serein.Workbench.Avalonia.Android/Resources/drawable/splash_screen.xml b/Serein.Workbench.Avalonia.Android/Resources/drawable/splash_screen.xml deleted file mode 100644 index 2e920b4..0000000 --- a/Serein.Workbench.Avalonia.Android/Resources/drawable/splash_screen.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - diff --git a/Serein.Workbench.Avalonia.Android/Resources/values-night/colors.xml b/Serein.Workbench.Avalonia.Android/Resources/values-night/colors.xml deleted file mode 100644 index 3d47b6f..0000000 --- a/Serein.Workbench.Avalonia.Android/Resources/values-night/colors.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #212121 - diff --git a/Serein.Workbench.Avalonia.Android/Resources/values/colors.xml b/Serein.Workbench.Avalonia.Android/Resources/values/colors.xml deleted file mode 100644 index 59279d5..0000000 --- a/Serein.Workbench.Avalonia.Android/Resources/values/colors.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #FFFFFF - diff --git a/Serein.Workbench.Avalonia.Android/Resources/values/styles.xml b/Serein.Workbench.Avalonia.Android/Resources/values/styles.xml deleted file mode 100644 index 6e534de..0000000 --- a/Serein.Workbench.Avalonia.Android/Resources/values/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - diff --git a/Serein.Workbench.Avalonia.Android/Serein.Workbench.Avalonia.Android.csproj b/Serein.Workbench.Avalonia.Android/Serein.Workbench.Avalonia.Android.csproj deleted file mode 100644 index 94feb2b..0000000 --- a/Serein.Workbench.Avalonia.Android/Serein.Workbench.Avalonia.Android.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - Exe - net8.0-android - 21 - enable - com.CompanyName.AvaloniaTest - 1 - 1.0 - apk - False - - - - - Resources\drawable\Icon.png - - - - - - - - - - - - diff --git a/Serein.Workbench.Avalonia.Browser/Program.cs b/Serein.Workbench.Avalonia.Browser/Program.cs deleted file mode 100644 index 3fd277e..0000000 --- a/Serein.Workbench.Avalonia.Browser/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Runtime.Versioning; -using System.Threading.Tasks; - -using Avalonia; -using Avalonia.Browser; - -using Serein.Workbench.Avalonia; - -internal sealed partial class Program -{ - private static Task Main(string[] args) => BuildAvaloniaApp() - .WithInterFont() - .StartBrowserAppAsync("out"); - - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure(); -} diff --git a/Serein.Workbench.Avalonia.Browser/Properties/AssemblyInfo.cs b/Serein.Workbench.Avalonia.Browser/Properties/AssemblyInfo.cs deleted file mode 100644 index fb78795..0000000 --- a/Serein.Workbench.Avalonia.Browser/Properties/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/Serein.Workbench.Avalonia.Browser/Properties/launchSettings.json b/Serein.Workbench.Avalonia.Browser/Properties/launchSettings.json deleted file mode 100644 index 33ed958..0000000 --- a/Serein.Workbench.Avalonia.Browser/Properties/launchSettings.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "profiles": { - "Serein.Workbench.Avalonia.Browser": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:7169;http://localhost:5235", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - } - } -} diff --git a/Serein.Workbench.Avalonia.Browser/Serein.Workbench.Avalonia.Browser.csproj b/Serein.Workbench.Avalonia.Browser/Serein.Workbench.Avalonia.Browser.csproj deleted file mode 100644 index a8f3adc..0000000 --- a/Serein.Workbench.Avalonia.Browser/Serein.Workbench.Avalonia.Browser.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - net8.0-browser - Exe - true - - - - - - - - - - diff --git a/Serein.Workbench.Avalonia.Browser/runtimeconfig.template.json b/Serein.Workbench.Avalonia.Browser/runtimeconfig.template.json deleted file mode 100644 index b96a943..0000000 --- a/Serein.Workbench.Avalonia.Browser/runtimeconfig.template.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "wasmHostProperties": { - "perHostConfig": [ - { - "name": "browser", - "host": "browser" - } - ] - } -} \ No newline at end of file diff --git a/Serein.Workbench.Avalonia.Browser/wwwroot/app.css b/Serein.Workbench.Avalonia.Browser/wwwroot/app.css deleted file mode 100644 index 1d6f754..0000000 --- a/Serein.Workbench.Avalonia.Browser/wwwroot/app.css +++ /dev/null @@ -1,58 +0,0 @@ -/* HTML styles for the splash screen */ -.avalonia-splash { - position: absolute; - height: 100%; - width: 100%; - background: white; - font-family: 'Outfit', sans-serif; - justify-content: center; - align-items: center; - display: flex; - pointer-events: none; -} - -/* Light theme styles */ -@media (prefers-color-scheme: light) { - .avalonia-splash { - background: white; - } - - .avalonia-splash h2 { - color: #1b2a4e; - } - - .avalonia-splash a { - color: #0D6EFD; - } -} - -@media (prefers-color-scheme: dark) { - .avalonia-splash { - background: #1b2a4e; - } - - .avalonia-splash h2 { - color: white; - } - - .avalonia-splash a { - color: white; - } -} - -.avalonia-splash h2 { - font-weight: 400; - font-size: 1.5rem; -} - -.avalonia-splash a { - text-decoration: none; - font-size: 2.5rem; - display: block; -} - -.avalonia-splash.splash-close { - transition: opacity 200ms, display 200ms; - display: none; - opacity: 0; -} diff --git a/Serein.Workbench.Avalonia.Browser/wwwroot/favicon.ico b/Serein.Workbench.Avalonia.Browser/wwwroot/favicon.ico deleted file mode 100644 index da8d49f..0000000 Binary files a/Serein.Workbench.Avalonia.Browser/wwwroot/favicon.ico and /dev/null differ diff --git a/Serein.Workbench.Avalonia.Browser/wwwroot/index.html b/Serein.Workbench.Avalonia.Browser/wwwroot/index.html deleted file mode 100644 index 276740d..0000000 --- a/Serein.Workbench.Avalonia.Browser/wwwroot/index.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Serein.Workbench.Avalonia - - - - - - -
-
-

- Powered by - - - - - - - - - - - - - - -

-
-
- - - - diff --git a/Serein.Workbench.Avalonia.Browser/wwwroot/main.js b/Serein.Workbench.Avalonia.Browser/wwwroot/main.js deleted file mode 100644 index bf1555e..0000000 --- a/Serein.Workbench.Avalonia.Browser/wwwroot/main.js +++ /dev/null @@ -1,13 +0,0 @@ -import { dotnet } from './_framework/dotnet.js' - -const is_browser = typeof window != "undefined"; -if (!is_browser) throw new Error(`Expected to be running in a browser`); - -const dotnetRuntime = await dotnet - .withDiagnosticTracing(false) - .withApplicationArgumentsFromQuery() - .create(); - -const config = dotnetRuntime.getConfig(); - -await dotnetRuntime.runMain(config.mainAssemblyName, [globalThis.location.href]); diff --git a/Serein.Workbench.Avalonia/App.axaml.cs b/Serein.Workbench.Avalonia/App.axaml.cs index c823dd3..5cf29aa 100644 --- a/Serein.Workbench.Avalonia/App.axaml.cs +++ b/Serein.Workbench.Avalonia/App.axaml.cs @@ -74,7 +74,8 @@ public static class ServiceCollectionExtensions UIContextOperation? uIContextOperation = null; uIContextOperation = new UIContextOperation(getSyncContext); // 封装一个调用UI线程的工具类 - FlowEnvironmentDecorator flowEnvironmentDecorator = new FlowEnvironmentDecorator(uIContextOperation); + var flowEnvironmentDecorator = new FlowEnvironmentDecorator(); + flowEnvironmentDecorator.SetUIContextOperation(uIContextOperation); collection.AddSingleton(uIContextOperation); // 注册UI线程操作上下文 collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境 collection.AddSingleton(flowEnvironmentDecorator); // 注册运行环境事件 diff --git a/Serein.Workbench.Avalonia/Custom/Node/ViewModels/NodeViewModelBase.cs b/Serein.Workbench.Avalonia/Custom/Node/ViewModels/NodeViewModelBase.cs index d55f24f..c6dc73c 100644 --- a/Serein.Workbench.Avalonia/Custom/Node/ViewModels/NodeViewModelBase.cs +++ b/Serein.Workbench.Avalonia/Custom/Node/ViewModels/NodeViewModelBase.cs @@ -4,7 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using Serein.Library; using Serein.Workbench.Avalonia.Api; using Serein.Workbench.Avalonia.Custom.Node.Views; -using Serein.Workbench.Avalonia.Custom.Views; +using Serein.Workbench.Avalonia.Model; using Serein.Workbench.Avalonia.ViewModels; using System; using System.Collections.Generic; @@ -30,11 +30,7 @@ namespace Serein.Workbench.Avalonia.Custom.Node.ViewModels public NodeModelBase NodeModel { get; set; } - /// - /// 记录与该节点控件有关的所有连接 - /// - private readonly List connectionControls = new List(); - + //public NodeControlViewModelBase ViewModel { get; set; } @@ -42,48 +38,6 @@ namespace Serein.Workbench.Avalonia.Custom.Node.ViewModels public void SetNodeModel(NodeModelBase nodeModel) => this.NodeModel = nodeModel; - /// - /// 添加与该节点有关的连接后,记录下来 - /// - /// - public void AddCnnection(NodeConnectionLineView connection) - { - connectionControls.Add(connection); - } - - /// - /// 删除了连接之后,还需要从节点中的记录移除 - /// - /// - public void RemoveConnection(NodeConnectionLineView connection) - { - connectionControls.Remove(connection); - //connection.Remote(); - } - - /// - /// 删除所有连接 - /// - public void RemoveAllConection() - { - foreach (var connection in this.connectionControls) - { - //connection.Remote(); - } - } - - /// - /// 更新与该节点有关的数据 - /// - public void UpdateLocationConnections() - { - foreach (var connection in this.connectionControls) - { - //connection.RefreshLine(); // 主动更新连线位置 - } - } - - /// /// 设置绑定: /// Canvas.X and Y : 画布位置 diff --git a/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml b/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml index 372387a..e621f97 100644 --- a/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml +++ b/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml @@ -21,7 +21,7 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml.cs b/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml.cs index c669790..0c6e84f 100644 --- a/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml.cs +++ b/Serein.Workbench.Avalonia/Custom/Node/Views/ActionNodeView.axaml.cs @@ -5,10 +5,11 @@ using Serein.Library; using Serein.NodeFlow.Model; using Serein.Workbench.Avalonia.Api; using Serein.Workbench.Avalonia.Custom.Node.ViewModels; +using Serein.Workbench.Avalonia.Custom.Views; namespace Serein.Workbench.Avalonia.Custom.Node.Views; -public partial class ActionNodeView : NodeControlBase +public partial class ActionNodeView : NodeControlBase, INodeJunction { private ActionNodeViewModel _vm; @@ -20,4 +21,11 @@ public partial class ActionNodeView : NodeControlBase //DataContext = _vm; } + public NodeJunctionView ExecuteJunction => this.ExecuteJunctionControl; + + public NodeJunctionView NextStepJunction => this.NextStepJunctionControl; + + public NodeJunctionView[] ArgDataJunction => throw new System.NotImplementedException(); + + public NodeJunctionView ReturnDataJunction => throw new System.NotImplementedException(); } \ No newline at end of file diff --git a/Serein.Workbench.Avalonia/Custom/Node/Views/NodeControlBase.cs b/Serein.Workbench.Avalonia/Custom/Node/Views/NodeControlBase.cs index 151799d..2bec141 100644 --- a/Serein.Workbench.Avalonia/Custom/Node/Views/NodeControlBase.cs +++ b/Serein.Workbench.Avalonia/Custom/Node/Views/NodeControlBase.cs @@ -14,13 +14,62 @@ using System.Threading.Tasks; namespace Serein.Workbench.Avalonia.Custom.Node.Views { - public class NodeControlBase : UserControl + public abstract class NodeControlBase : UserControl { + /// + /// 记录与该节点控件有关的所有连接 + /// + private readonly List connectionControls = new List(); + protected NodeControlBase() { this.Background = Brushes.Transparent; } + + /// + /// 添加与该节点有关的连接后,记录下来 + /// + /// + public void AddConnection(NodeConnectionLineControl connection) + { + connectionControls.Add(connection); + } + + /// + /// 删除了连接之后,还需要从节点中的记录移除 + /// + /// + public void RemoveConnection(NodeConnectionLineControl connection) + { + connectionControls.Remove(connection); + connection.Remove(); + } + + /// + /// 删除所有连接 + /// + public void RemoveAllConection() + { + foreach (var connection in this.connectionControls) + { + connection.Remove(); + } + } + + /// + /// 更新与该节点有关的数据 + /// + public void UpdateLocationConnections() + { + foreach (var connection in this.connectionControls) + { + connection.RefreshLineDsiplay(); // 主动更新连线位置 + } + } + + + /// /// 放置在某个节点容器中 /// diff --git a/Serein.Workbench.Avalonia/Custom/Views/ConnectionLineShape.cs b/Serein.Workbench.Avalonia/Custom/Views/ConnectionLineShape.cs index bf79df9..2adfd67 100644 --- a/Serein.Workbench.Avalonia/Custom/Views/ConnectionLineShape.cs +++ b/Serein.Workbench.Avalonia/Custom/Views/ConnectionLineShape.cs @@ -62,7 +62,7 @@ namespace Serein.Workbench.Avalonia.Custom.Views //visualPen.Freeze(); // Freeze以提高性能 linkSize = 4; // 整线条粗细 - int zIndex = 999999; + int zIndex = -999999; this.ZIndex = zIndex; //Panel.SetZIndex(this, zIndex); // 置底 @@ -111,6 +111,15 @@ namespace Serein.Workbench.Avalonia.Custom.Views this.leftPoint = left; InvalidateVisual(); // 触发重绘 } + /// + /// 刷新颜色 + /// + /// + public void UpdateColor(Brush brush ) + { + visualPen = new Pen(brush, 3.0); // 默认可视化Pen + InvalidateVisual(); // 触发重绘 + } /// /// 控件重绘事件 diff --git a/Serein.Workbench.Avalonia/Custom/Views/NodeContainerView.axaml.cs b/Serein.Workbench.Avalonia/Custom/Views/NodeContainerView.axaml.cs index 1c8e6d5..f50f5b9 100644 --- a/Serein.Workbench.Avalonia/Custom/Views/NodeContainerView.axaml.cs +++ b/Serein.Workbench.Avalonia/Custom/Views/NodeContainerView.axaml.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using Serein.Library; using Serein.Library.Utils; using Serein.Workbench.Avalonia.Api; +using Serein.Workbench.Avalonia.Custom.Node.Views; using Serein.Workbench.Avalonia.Custom.ViewModels; using Serein.Workbench.Avalonia.Extension; using Serein.Workbench.Avalonia.Services; @@ -51,7 +52,7 @@ public partial class NodeContainerView : UserControl /// /// ǰѡȡĿؼ /// - private readonly List selectNodeControls = []; + private readonly List selectNodeControls = []; /// /// ¼ʼ϶ڵؼʱλ @@ -98,7 +99,7 @@ public partial class NodeContainerView : UserControl { IsCanvasDragging = false; IsControlDragging = false; - nodeOperationService.ConnectingData.Reset(); + nodeOperationService.ConnectingManage.Reset(); } }; #endregion @@ -192,7 +193,7 @@ public partial class NodeContainerView : UserControl private void NodeContainerView_PointerMoved(object? sender, PointerEventArgs e) { // Ƿ - var myData = nodeOperationService.ConnectingData; + var myData = nodeOperationService.ConnectingManage; if (myData.IsCreateing) { var isPass = e.JudgePointer(sender, PointerType.Mouse, p => p.IsLeftButtonPressed); @@ -318,7 +319,7 @@ public partial class NodeContainerView : UserControl } /// - /// ؼ¼϶ + /// ؼҼ¼϶ /// private void Block_MouseLeftButtonDown(object? sender, PointerPressedEventArgs e) { @@ -328,10 +329,11 @@ public partial class NodeContainerView : UserControl return; } - if (sender is Control nodeControl) + if (sender is NodeControlBase nodeControl) { IsControlDragging = true; startControlDragPoint = GetPositionOfCanvas(e); // ¼갴ʱλ + e.Handled = true; // ֹ¼Ӱؼ } @@ -343,7 +345,7 @@ public partial class NodeContainerView : UserControl private void Block_MouseMove(object? sender, PointerEventArgs e) { - if (sender is not Control nodeControl) + if (sender is not NodeControlBase nodeControl) { return; } @@ -365,6 +367,7 @@ public partial class NodeContainerView : UserControl double newLeft = Canvas.GetLeft(nodeControl) + deltaX; // µ߾ double newTop = Canvas.GetTop(nodeControl) + deltaY; // µϱ߾ DragControl(nodeControl, newLeft, newTop); + nodeControl.UpdateLocationConnections(); } // ƶ else @@ -401,10 +404,10 @@ public partial class NodeContainerView : UserControl } // ½ڵ֮ߵλ - //foreach (var nodeControl in selectNodeControls) - //{ - // //nodeControl.UpdateLocationConnections(); - //} + foreach (var item in selectNodeControls) + { + item.UpdateLocationConnections(); + } } startControlDragPoint = currentPosition; // ʼλ } diff --git a/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs b/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs index 18fe1ff..eac6477 100644 --- a/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs +++ b/Serein.Workbench.Avalonia/Custom/Views/NodeJunctionView.axaml.cs @@ -7,6 +7,7 @@ using Serein.Library.Api; using Serein.Workbench.Avalonia.Api; using Serein.Workbench.Avalonia.Extension; using System; +using System.Diagnostics; using Color = Avalonia.Media.Color; using Point = Avalonia.Point; @@ -76,7 +77,7 @@ public class NodeJunctionView : TemplatedControl private void NodeJunctionView_PointerMoved(object? sender, PointerEventArgs e) { - if (!nodeOperationService.ConnectingData.IsCreateing) + if (!nodeOperationService.ConnectingManage.IsCreateing) return; if (nodeOperationService.MainCanvas is not InputElement inputElement) return; @@ -87,7 +88,7 @@ public class NodeJunctionView : TemplatedControl } else { - var oldNj = nodeOperationService.ConnectingData.CurrentJunction; + var oldNj = nodeOperationService.ConnectingManage.CurrentJunction; if (oldNj is not null) { oldNj.IsPreviewing = false; @@ -98,7 +99,7 @@ public class NodeJunctionView : TemplatedControl private void RefreshDisplay(NodeJunctionView junctionView) { - var oldNj = nodeOperationService.ConnectingData.CurrentJunction; + var oldNj = nodeOperationService.ConnectingManage.CurrentJunction; if (oldNj is not null ) { if (junctionView.Equals(oldNj)) @@ -108,11 +109,11 @@ public class NodeJunctionView : TemplatedControl oldNj.IsPreviewing = false; oldNj.InvalidateVisual(); } - nodeOperationService.ConnectingData.CurrentJunction = junctionView; - if (!this.Equals(junctionView)) + nodeOperationService.ConnectingManage.CurrentJunction = junctionView; + if (!this.Equals(junctionView) && nodeOperationService.ConnectingManage.IsCanConnected()) { - - nodeOperationService.ConnectingData.TempLine?.ToEnd(junctionView); + Debug.WriteLine("ok"); + nodeOperationService.ConnectingManage.TempLine?.ToEnd(junctionView); } junctionView.IsPreviewing = true; junctionView.InvalidateVisual(); @@ -132,12 +133,12 @@ public class NodeJunctionView : TemplatedControl private void NodeJunctionView_PointerReleased(object? sender, PointerReleasedEventArgs e) { CheckJunvtion(); - nodeOperationService.ConnectingData.Reset(); + nodeOperationService.ConnectingManage.Reset(); } private void CheckJunvtion() { - var myData = nodeOperationService.ConnectingData; + var myData = nodeOperationService.ConnectingManage; if(myData.StartJunction is null || myData.CurrentJunction is null) { return; @@ -246,7 +247,7 @@ public class NodeJunctionView : TemplatedControl /// protected IBrush GetBackgrounp() { - var myData = nodeOperationService.ConnectingData; + var myData = nodeOperationService.ConnectingManage; if (IsPreviewing == false || !myData.IsCreateing ) { return new SolidColorBrush(Color.Parse("#76ABEE")); diff --git a/Serein.Workbench.Avalonia/DataTemplates/LibraryMethodInfoDataTemplate.cs b/Serein.Workbench.Avalonia/DataTemplates/LibraryMethodInfoDataTemplate.cs index b513421..6973fc5 100644 --- a/Serein.Workbench.Avalonia/DataTemplates/LibraryMethodInfoDataTemplate.cs +++ b/Serein.Workbench.Avalonia/DataTemplates/LibraryMethodInfoDataTemplate.cs @@ -40,7 +40,7 @@ namespace Serein.Workbench.Avalonia.DataTemplates textBlock.FontSize = 12; return textBlock; } - + } public bool Match(object data) @@ -57,7 +57,7 @@ namespace Serein.Workbench.Avalonia.DataTemplates } var dragData = new DataObject(); // 设置需要传递的数据 dragData.Set(DataFormats.Text, mdInfo.ToJsonText()); - _ = DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy); + _ = DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy); //var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy); //Debug.WriteLine("DoDrag :" + result); //switch (result) diff --git a/Serein.Workbench.Avalonia/Model/ConnectingData.cs b/Serein.Workbench.Avalonia/Model/ConnectingManage.cs similarity index 94% rename from Serein.Workbench.Avalonia/Model/ConnectingData.cs rename to Serein.Workbench.Avalonia/Model/ConnectingManage.cs index 24e63ea..acf8463 100644 --- a/Serein.Workbench.Avalonia/Model/ConnectingData.cs +++ b/Serein.Workbench.Avalonia/Model/ConnectingManage.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Threading; using Serein.Library; +using Serein.Workbench.Avalonia.Api; using Serein.Workbench.Avalonia.Custom.Views; using System; using System.Collections.Generic; @@ -15,12 +16,13 @@ namespace Serein.Workbench.Avalonia.Model /// /// 节点之间连接线的相关控制方法 /// - public class ConnectingData + internal class ConnectingManage { /// /// 是否正在创建连线 /// public bool IsCreateing { get; set; } + /// /// 起始控制点 /// @@ -29,14 +31,11 @@ namespace Serein.Workbench.Avalonia.Model /// 当前的控制点 /// public NodeJunctionView? CurrentJunction { get; set; } - /// - /// 开始坐标 - /// - public Point StartPoint { get; set; } + /// /// 线条样式 /// - public NodeConnectionLineView? TempLine { get; set; } + public NodeConnectionLineControl? TempLine { get; set; } /// /// 线条类别(方法调用) @@ -51,7 +50,10 @@ namespace Serein.Workbench.Avalonia.Model /// 判断当前连接类型 /// public JunctionOfConnectionType? Type => StartJunction?.JunctionType.ToConnectyionType(); - + + private readonly INodeOperationService nodeOperationService1; + + /// /// 是否允许连接 @@ -105,6 +107,10 @@ namespace Serein.Workbench.Avalonia.Model } } + + + + /// /// 重置 /// diff --git a/Serein.Workbench.Avalonia/Custom/Views/NodeConnectionLineView.cs b/Serein.Workbench.Avalonia/Model/NodeConnectionLineControl.cs similarity index 60% rename from Serein.Workbench.Avalonia/Custom/Views/NodeConnectionLineView.cs rename to Serein.Workbench.Avalonia/Model/NodeConnectionLineControl.cs index b491f2e..d163293 100644 --- a/Serein.Workbench.Avalonia/Custom/Views/NodeConnectionLineView.cs +++ b/Serein.Workbench.Avalonia/Model/NodeConnectionLineControl.cs @@ -5,6 +5,7 @@ using Avalonia.Media; using Avalonia.VisualTree; using Serein.Library; using Serein.Script.Node; +using Serein.Workbench.Avalonia.Custom.Views; using Serein.Workbench.Avalonia.Extension; using Serein.Workbench.Avalonia.Services; using System; @@ -18,12 +19,12 @@ using System.Threading.Tasks; using Color = Avalonia.Media.Color; using Point = Avalonia.Point; -namespace Serein.Workbench.Avalonia.Custom.Views +namespace Serein.Workbench.Avalonia.Model { - - public class NodeConnectionLineView + + public class NodeConnectionLineControl { /// /// 线条类别(方法调用) @@ -53,13 +54,37 @@ namespace Serein.Workbench.Avalonia.Custom.Views /// public ConnectionLineShape? ConnectionLineShape { get; private set; } - public NodeConnectionLineView(Canvas canvas, + private NodeJunctionView StartNodeJunctionView; + + public NodeConnectionLineControl(Canvas canvas, NodeJunctionView? leftNodeJunctionView, NodeJunctionView? rightNodeJunctionView) { - this.Canvas = canvas; - this.LeftNodeJunctionView = leftNodeJunctionView; - this.RightNodeJunctionView = rightNodeJunctionView; + if (leftNodeJunctionView is null && rightNodeJunctionView is null) + { + throw new Exception("不能都为空"); + } + + Canvas = canvas; + LeftNodeJunctionView = leftNodeJunctionView; + RightNodeJunctionView = rightNodeJunctionView; + + if (leftNodeJunctionView is null && rightNodeJunctionView is not null) + { + StartNodeJunctionView = rightNodeJunctionView; + } + else if(leftNodeJunctionView is not null && rightNodeJunctionView is null) + { + StartNodeJunctionView = leftNodeJunctionView; + } + else if (leftNodeJunctionView is not null && rightNodeJunctionView is not null) + { + LeftNodeJunctionView = leftNodeJunctionView; + RightNodeJunctionView = rightNodeJunctionView; + RefreshLineDsiplay(); + } + + } /// @@ -68,35 +93,52 @@ namespace Serein.Workbench.Avalonia.Custom.Views /// public void ToEnd(NodeJunctionView endNodeJunctionView) { - if((endNodeJunctionView.JunctionType == JunctionType.NextStep - || endNodeJunctionView.JunctionType == JunctionType.ReturnData) - && RightNodeJunctionView is not null - /*&& LeftNodeJunctionView is null*/ - /*&& !LeftNodeJunctionView.Equals(endNodeJunctionView)*/) + var @bool = endNodeJunctionView.JunctionType == JunctionType.Execute || endNodeJunctionView.JunctionType == JunctionType.ArgData; + (LeftNodeJunctionView, RightNodeJunctionView) = @bool? (StartNodeJunctionView, endNodeJunctionView) : (endNodeJunctionView, StartNodeJunctionView); + RefreshLineDsiplay(); + return; + + /*if(StartNodeJunctionView.JunctionType == JunctionType.NextStep + && endNodeJunctionView.JunctionType == JunctionType.Execute + && StartNodeJunctionView.MyNode?.Equals(endNodeJunctionView.MyNode) == false) { - LeftNodeJunctionView = endNodeJunctionView; + LeftNodeJunctionView = StartNodeJunctionView; + RightNodeJunctionView = endNodeJunctionView; RefreshLineDsiplay(); return; } - else if ((endNodeJunctionView.JunctionType == JunctionType.Execute - || endNodeJunctionView.JunctionType == JunctionType.ArgData) - && LeftNodeJunctionView is not null - /*&& RightNodeJunctionView is null*/ - /*&& !RightNodeJunctionView.Equals(endNodeJunctionView)*/) + + if (StartNodeJunctionView.JunctionType == JunctionType.ReturnData + && endNodeJunctionView.JunctionType == JunctionType.ArgData + && StartNodeJunctionView.MyNode?.Equals(endNodeJunctionView.MyNode) == false) { + LeftNodeJunctionView = StartNodeJunctionView; RightNodeJunctionView = endNodeJunctionView; RefreshLineDsiplay(); return; } - // + if (StartNodeJunctionView.JunctionType == JunctionType.Execute + && endNodeJunctionView.JunctionType == JunctionType.NextStep + && StartNodeJunctionView.MyNode?.Equals(endNodeJunctionView.MyNode) == false) + { + LeftNodeJunctionView = endNodeJunctionView; + RightNodeJunctionView = StartNodeJunctionView; + RefreshLineDsiplay(); + return; + } + + if (StartNodeJunctionView.JunctionType == JunctionType.ArgData + && endNodeJunctionView.JunctionType == JunctionType.ReturnData + && StartNodeJunctionView.MyNode?.Equals(endNodeJunctionView.MyNode) == false) + { + LeftNodeJunctionView = endNodeJunctionView; + RightNodeJunctionView = StartNodeJunctionView; + RefreshLineDsiplay(); + return; + }*/ - //var leftPoint = GetPoint(LeftNodeJunctionView); - //var rightPoint = GetPoint(RightNodeJunctionView); - //var brush = GetBackgrounp(); - //ConnectionLineShape.UpdatePoint(leftPoint, rightPoint); - //CreateLineShape(startPoint, endPoint, brush); } /// @@ -104,7 +146,7 @@ namespace Serein.Workbench.Avalonia.Custom.Views /// public void RefreshLineDsiplay() { - if(LeftNodeJunctionView is null || RightNodeJunctionView is null) + if (LeftNodeJunctionView is null || RightNodeJunctionView is null) { return; } @@ -112,30 +154,35 @@ namespace Serein.Workbench.Avalonia.Custom.Views var rightPoint = GetPoint(RightNodeJunctionView); if (ConnectionLineShape is null) { - Debug.WriteLine("创建"); CreateLineShape(leftPoint, rightPoint, GetBackgrounp()); } else { - Debug.WriteLine("刷新"); var brush = GetBackgrounp(); - ConnectionLineShape.UpdatePoint( leftPoint, rightPoint, brush); + ConnectionLineShape.UpdatePoint(leftPoint, rightPoint, brush); } } + //public void UpdateColor() + //{ + // var brush = GetBackgrounp(); + // ConnectionLineShape?.UpdateColor(brush); + //} /// /// 刷新临时线的显示 /// public void RefreshRightPointOfTempLineDsiplay(Point rightPoint) { - if(ConnectionLineShape is not null) + if (ConnectionLineShape is not null) { + + RightNodeJunctionView = null; var brush = GetBackgrounp(); ConnectionLineShape.UpdateRightPoint(rightPoint, brush); return; } - + if (LeftNodeJunctionView is not null) { var leftPoint = GetPoint(LeftNodeJunctionView); @@ -143,18 +190,20 @@ namespace Serein.Workbench.Avalonia.Custom.Views CreateLineShape(leftPoint, rightPoint, brush); } } + /// /// 刷新临时线的显示 /// public void RefreshLeftPointOfTempLineDsiplay(Point leftPoint) { - if(ConnectionLineShape is not null) + if (ConnectionLineShape is not null) { var brush = GetBackgrounp(); + LeftNodeJunctionView = null; ConnectionLineShape.UpdateLeftPoints(leftPoint, brush); return; } - + if (RightNodeJunctionView is not null) { var rightPoint = GetPoint(RightNodeJunctionView); @@ -163,56 +212,6 @@ namespace Serein.Workbench.Avalonia.Custom.Views } } - - - private static Point defaultPoint = new Point(0, 0); - int count; - private Point GetPoint(NodeJunctionView nodeJunctionView) - { - - var junctionSize = nodeJunctionView.GetTransformedBounds()!.Value.Bounds.Size; - Point junctionPoint; - if (nodeJunctionView.JunctionType == JunctionType.ArgData || nodeJunctionView.JunctionType == JunctionType.Execute) - { - junctionPoint = new Point(junctionSize.Width / 2 - 11, junctionSize.Height / 2); // 选择左侧 - } - else - { - junctionPoint = new Point(junctionSize.Width / 2 + 11, junctionSize.Height / 2); // 选择右侧 - } - if (nodeJunctionView.TranslatePoint(junctionPoint, Canvas) is Point point) - { - //myData.StartPoint = point; - return point; - } - else - { - return defaultPoint; - } - - //var point = nodeJunctionView.TranslatePoint(defaultPoint , Canvas); - //if(point is null) - //{ - // return defaultPoint; - //} - //else - //{ - // return point.Value; - // } - } - - private void CreateLineShape(Point leftPoint, Point rightPoint, Brush brush) - { - ConnectionLineShape = new ConnectionLineShape(leftPoint, rightPoint, brush); - Canvas.Children.Add(ConnectionLineShape); - } - - private JunctionOfConnectionType GetConnectionType() - { - return LeftNodeJunctionView.JunctionType.ToConnectyionType(); - } - - /// /// 获取背景颜色 /// @@ -220,7 +219,7 @@ namespace Serein.Workbench.Avalonia.Custom.Views public Brush GetBackgrounp() { - if(LeftNodeJunctionView is null || RightNodeJunctionView is null) + if (LeftNodeJunctionView is null || RightNodeJunctionView is null) { return new SolidColorBrush(Color.Parse("#FF0000")); // 没有终点 } @@ -231,16 +230,19 @@ namespace Serein.Workbench.Avalonia.Custom.Views return new SolidColorBrush(Color.Parse("#FF0000")); } - + if (GetConnectionType() == JunctionOfConnectionType.Invoke) { return ConnectionInvokeType.ToLineColor(); // 调用 - } - else - { + } + else if (GetConnectionType() == JunctionOfConnectionType.Arg) + { return ConnectionArgSourceType.ToLineColor(); // 参数 } - + else + { + return new SolidColorBrush(Color.Parse("#FF0000")); + } } public bool IsCanConnected() @@ -269,11 +271,69 @@ namespace Serein.Workbench.Avalonia.Custom.Views /// public void Remove() { - if(ConnectionLineShape is null) + if (ConnectionLineShape is null) { return; } Canvas.Children.Remove(ConnectionLineShape); } + + + private static Point defaultPoint = new Point(0, 0); + int count; + private Point GetPoint(NodeJunctionView nodeJunctionView) + { + + var junctionSize = nodeJunctionView.GetTransformedBounds()!.Value.Bounds.Size; + Point junctionPoint; + if (nodeJunctionView.JunctionType == JunctionType.ArgData || nodeJunctionView.JunctionType == JunctionType.Execute) + { + junctionPoint = new Point(junctionSize.Width / 2 - 11, junctionSize.Height / 2); // 选择左侧 + } + else + { + junctionPoint = new Point(junctionSize.Width / 2 + 11, junctionSize.Height / 2); // 选择右侧 + } + if (nodeJunctionView.TranslatePoint(junctionPoint, Canvas) is Point point) + { + //myData.StartPoint = point; + return point; + } + else + { + return defaultPoint; + } + } + + private void CreateLineShape(Point leftPoint, Point rightPoint, Brush brush) + { + ConnectionLineShape = new ConnectionLineShape(leftPoint, rightPoint, brush); + Canvas.Children.Add(ConnectionLineShape); + } + + private JunctionOfConnectionType GetConnectionType() + { + if(LeftNodeJunctionView is null) + { + if(RightNodeJunctionView is null) + { + + return JunctionOfConnectionType.None; + } + else + { + + return RightNodeJunctionView.JunctionType.ToConnectyionType(); + } + } + else + { + + return LeftNodeJunctionView.JunctionType.ToConnectyionType(); + } + } + + + } } diff --git a/Serein.Workbench.Avalonia/Services/NodeOperationService.cs b/Serein.Workbench.Avalonia/Services/NodeOperationService.cs index e6079af..cc13f59 100644 --- a/Serein.Workbench.Avalonia/Services/NodeOperationService.cs +++ b/Serein.Workbench.Avalonia/Services/NodeOperationService.cs @@ -34,7 +34,7 @@ namespace Serein.Workbench.Avalonia.Api /// /// 连接数据 /// - ConnectingData ConnectingData { get; } + ConnectingManage ConnectingManage { get; } /// /// 主画布 @@ -116,7 +116,6 @@ namespace Serein.Workbench.Avalonia.Services feefService.OnNodeCreate += FeefService_OnNodeCreate; // 订阅运行环境创建节点事件 feefService.OnNodeConnectChange += FeefService_OnNodeConnectChange; // 订阅运行环境连接了节点事件 NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeView), typeof(ActionNodeViewModel)); // 注册动作节点 - // 手动加载项目 _ = Task.Run(async delegate { @@ -128,13 +127,11 @@ namespace Serein.Workbench.Avalonia.Services var projectDfilePath = System.IO.Path.GetDirectoryName(filePath)!; flowEnvironment.LoadProject(new FlowEnvInfo { Project = projectData }, projectDfilePath); }, CancellationToken.None); - - } #region 接口属性 - public ConnectingData ConnectingData { get; private set; } = new ConnectingData(); + public ConnectingManage ConnectingManage { get; private set; } = new ConnectingManage(); public Canvas MainCanvas { get; set; } #endregion @@ -149,7 +146,7 @@ namespace Serein.Workbench.Avalonia.Services /// /// 存储所有连接 /// - private List Connections { get; } = []; + private List Connections { get; } = []; @@ -227,7 +224,6 @@ namespace Serein.Workbench.Avalonia.Services /// private void FeefService_OnNodeConnectChange(NodeConnectChangeEventArgs eventArgs) { -#if false string fromNodeGuid = eventArgs.FromNodeGuid; string toNodeGuid = eventArgs.ToNodeGuid; if (!TryGetControl(fromNodeGuid, out var fromNodeControl) @@ -236,6 +232,7 @@ namespace Serein.Workbench.Avalonia.Services return; } + if (eventArgs.JunctionOfConnectionType == JunctionOfConnectionType.Invoke) { ConnectionInvokeType connectionType = eventArgs.ConnectionInvokeType; @@ -251,16 +248,20 @@ namespace Serein.Workbench.Avalonia.Services var startJunction = IFormJunction.NextStepJunction; var endJunction = IToJunction.ExecuteJunction; - startJunction.TransformToVisual(MainCanvas); + NodeConnectionLineControl nodeConnectionLineControl = new NodeConnectionLineControl(MainCanvas, startJunction, endJunction); - // 添加连接 - var shape = new ConnectionLineShape( - FlowChartCanvas, - connectionType, - startJunction, - endJunction - ); - NodeConnectionLine nodeConnectionLine = new NodeConnectionLine(MainCanvas, shape); + //startJunction.TransformToVisual(MainCanvas); + + //// 添加连接 + //var shape = new ConnectionLineShape( + // FlowChartCanvas, + // connectionType, + // startJunction, + // endJunction + //); + + + //NodeConnectionLine nodeConnectionLine = new NodeConnectionLine(MainCanvas, shape); //if (toNodeControl is FlipflopNodeControl flipflopControl // && flipflopControl?.ViewModel?.NodeModel is NodeModelBase nodeModel) // 某个节点连接到了触发器,尝试从全局触发器视图中移除该触发器 @@ -268,15 +269,15 @@ namespace Serein.Workbench.Avalonia.Services // NodeTreeViewer.RemoveGlobalFlipFlop(nodeModel); // 从全局触发器树树视图中移除 //} - Connections.Add(nodeConnectionLine); - fromNodeControl.AddCnnection(shape); - toNodeControl.AddCnnection(shape); + Connections.Add(nodeConnectionLineControl); + fromNodeControl.AddConnection(nodeConnectionLineControl); + toNodeControl.AddConnection(nodeConnectionLineControl); } #endregion -#if false + #region 移除连接 - else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remove) // 移除连接 + /* else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remove) // 移除连接 { // 需要移除连接 var removeConnections = Connections.Where(c => @@ -297,16 +298,16 @@ namespace Serein.Workbench.Avalonia.Services JudgmentFlipFlopNode(control); // 连接关系变更时判断 } } - } + }*/ #endregion -#endif + #endregion } - else + /*else { - #if false - ConnectionArgSourceType connectionArgSourceType = eventArgs.ConnectionArgSourceType; + + ConnectionArgSourceType connectionArgSourceType = eventArgs.ConnectionArgSourceType; #region 创建/删除节点之间的参数传递关系 #region 创建连接 if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接 @@ -383,9 +384,9 @@ namespace Serein.Workbench.Avalonia.Services } #endregion #endregion -#endif - } -#endif + + } */ + } #endregion @@ -490,18 +491,18 @@ namespace Serein.Workbench.Avalonia.Services { if (MainCanvas is not null) { - ConnectingData.Reset(); - ConnectingData.IsCreateing = true; // 表示开始连接 - ConnectingData.StartJunction = startJunction; - ConnectingData.CurrentJunction = startJunction; + ConnectingManage.Reset(); + ConnectingManage.IsCreateing = true; // 表示开始连接 + ConnectingManage.StartJunction = startJunction; + ConnectingManage.CurrentJunction = startJunction; if(startJunction.JunctionType == JunctionType.NextStep || startJunction.JunctionType == JunctionType.ReturnData) { - ConnectingData.TempLine = new NodeConnectionLineView(MainCanvas, startJunction, null); + ConnectingManage.TempLine = new NodeConnectionLineControl(MainCanvas, startJunction, null); } else { - ConnectingData.TempLine = new NodeConnectionLineView(MainCanvas,null ,startJunction); + ConnectingManage.TempLine = new NodeConnectionLineControl(MainCanvas,null ,startJunction); } diff --git a/SereinFlow.sln b/SereinFlow.sln index 549ddc0..a97822f 100644 --- a/SereinFlow.sln +++ b/SereinFlow.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.9.34728.123 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Workbench", "WorkBench\Serein.Workbench.csproj", "{EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library.Core", "Library.Core\Serein.Library.Core.csproj", "{4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.NodeFlow", "NodeFlow\Serein.NodeFlow.csproj", "{7B51A19A-88AB-471E-BCE3-3888C67C936D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{938F25F8-E497-4FCF-A028-9309C155A8EF}" @@ -14,8 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serein.Library.Framework", "Library.Framework\Serein.Library.Framework.csproj", "{73B272E8-222D-4D08-A030-F1E1DB70B9D1}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library", "Library\Serein.Library.csproj", "{5E19D0F2-913A-4D1C-A6F8-1E1227BAA0E3}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net462DllTest", "Net462DllTest\Net462DllTest.csproj", "{E40EE629-1A38-4011-88E3-9AD036869987}" @@ -42,18 +38,10 @@ Global {EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}.Release|Any CPU.ActiveCfg = Release|Any CPU {EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}.Release|Any CPU.Build.0 = Release|Any CPU - {4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}.Release|Any CPU.Build.0 = Release|Any CPU {7B51A19A-88AB-471E-BCE3-3888C67C936D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B51A19A-88AB-471E-BCE3-3888C67C936D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B51A19A-88AB-471E-BCE3-3888C67C936D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B51A19A-88AB-471E-BCE3-3888C67C936D}.Release|Any CPU.Build.0 = Release|Any CPU - {73B272E8-222D-4D08-A030-F1E1DB70B9D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {73B272E8-222D-4D08-A030-F1E1DB70B9D1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {73B272E8-222D-4D08-A030-F1E1DB70B9D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {73B272E8-222D-4D08-A030-F1E1DB70B9D1}.Release|Any CPU.Build.0 = Release|Any CPU {5E19D0F2-913A-4D1C-A6F8-1E1227BAA0E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5E19D0F2-913A-4D1C-A6F8-1E1227BAA0E3}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E19D0F2-913A-4D1C-A6F8-1E1227BAA0E3}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Workbench/MainWindowViewModel.cs b/Workbench/MainWindowViewModel.cs index 0aedffd..7868056 100644 --- a/Workbench/MainWindowViewModel.cs +++ b/Workbench/MainWindowViewModel.cs @@ -41,7 +41,8 @@ namespace Serein.Workbench } else { - FlowEnvironment = new FlowEnvironmentDecorator(uIContextOperation); + FlowEnvironment = new FlowEnvironmentDecorator(); + FlowEnvironment.SetUIContextOperation(uIContextOperation); //_ = FlowEnvironment.StartRemoteServerAsync(); this.window = window; } diff --git a/Workbench/Node/View/ConditionRegionControl.xaml.cs b/Workbench/Node/View/ConditionRegionControl.xaml.cs index 9e50faa..d598733 100644 --- a/Workbench/Node/View/ConditionRegionControl.xaml.cs +++ b/Workbench/Node/View/ConditionRegionControl.xaml.cs @@ -1,9 +1,6 @@ using Serein.NodeFlow.Model; using Serein.Workbench.Node.ViewModel; using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; namespace Serein.Workbench.Node.View { diff --git a/Workbench/Node/View/FlipflopNodeControl.xaml.cs b/Workbench/Node/View/FlipflopNodeControl.xaml.cs index e325f13..353ec67 100644 --- a/Workbench/Node/View/FlipflopNodeControl.xaml.cs +++ b/Workbench/Node/View/FlipflopNodeControl.xaml.cs @@ -1,7 +1,6 @@ -using Serein.NodeFlow.Model; -using Serein.Workbench.Node.ViewModel; -using System.Windows.Controls; +using Serein.Workbench.Node.ViewModel; using System.Windows; +using System.Windows.Controls; namespace Serein.Workbench.Node.View { diff --git a/Workbench/Node/View/GlobalDataControl.xaml.cs b/Workbench/Node/View/GlobalDataControl.xaml.cs index f3f4bf3..0d79af3 100644 --- a/Workbench/Node/View/GlobalDataControl.xaml.cs +++ b/Workbench/Node/View/GlobalDataControl.xaml.cs @@ -1,19 +1,5 @@ using Serein.NodeFlow.Model; using Serein.Workbench.Node.ViewModel; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; namespace Serein.Workbench.Node.View { diff --git a/Workbench/Node/ViewModel/GlobalDataNodeControlViewModel.cs b/Workbench/Node/ViewModel/GlobalDataNodeControlViewModel.cs index a396cba..a292b23 100644 --- a/Workbench/Node/ViewModel/GlobalDataNodeControlViewModel.cs +++ b/Workbench/Node/ViewModel/GlobalDataNodeControlViewModel.cs @@ -1,11 +1,4 @@ -using Serein.Library; -using Serein.NodeFlow.Model; -using Serein.Workbench.Node.View; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Serein.NodeFlow.Model; using System.Windows; using System.Windows.Input; diff --git a/Workbench/Node/ViewModel/ScriptNodeControlViewModel.cs b/Workbench/Node/ViewModel/ScriptNodeControlViewModel.cs index 6b03113..9783c0c 100644 --- a/Workbench/Node/ViewModel/ScriptNodeControlViewModel.cs +++ b/Workbench/Node/ViewModel/ScriptNodeControlViewModel.cs @@ -1,5 +1,4 @@ using Serein.Library; -using Serein.Library.Core; using Serein.Library.Utils; using Serein.NodeFlow.Model; using System; @@ -30,7 +29,7 @@ namespace Serein.Workbench.Node.ViewModel { try { - var result = await NodeModel.ExecutingAsync(new DynamicContext(nodeModel.Env)); + var result = await NodeModel.ExecutingAsync(new Library.DynamicContext(nodeModel.Env)); SereinEnv.WriteLine(InfoType.INFO, result?.ToString()); } catch (Exception ex) diff --git a/Workbench/Serein.WorkBench.csproj b/Workbench/Serein.WorkBench.csproj index ad7578f..3e76512 100644 --- a/Workbench/Serein.WorkBench.csproj +++ b/Workbench/Serein.WorkBench.csproj @@ -47,8 +47,6 @@ - -