mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 15:50:47 +08:00
破坏性更新,移除了Core/Framework(对应的上下文类移动到了Library)
This commit is contained in:
Binary file not shown.
@@ -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 监听远程请求
|
||||
|
||||
|
||||
@@ -1,606 +0,0 @@
|
||||
using SqlSugar;
|
||||
using System.ComponentModel;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Serein.DbSql
|
||||
{
|
||||
public enum DBSyncStart
|
||||
{
|
||||
/// <summary>
|
||||
/// 无需同步
|
||||
/// </summary>
|
||||
[Description("无需同步")]
|
||||
NotNeed,
|
||||
/// <summary>
|
||||
/// 同步成功
|
||||
/// </summary>
|
||||
[Description("同步成功")]
|
||||
SyncSuccess,
|
||||
/// <summary>
|
||||
/// 同步失败
|
||||
/// </summary>
|
||||
[Description("同步失败")]
|
||||
SyncFailure,
|
||||
/// <summary>
|
||||
/// 连接异常
|
||||
/// </summary>
|
||||
[Description("配置/连接异常")]
|
||||
NetworkError,
|
||||
/// <summary>
|
||||
/// 没有同步事件
|
||||
/// </summary>
|
||||
[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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 主数据库IP
|
||||
/// </summary>
|
||||
//private string Host { get; }
|
||||
/// <summary>
|
||||
/// 主数据库端口
|
||||
/// </summary>
|
||||
//private int Port { get; }
|
||||
/// <summary>
|
||||
/// 主数据库配置
|
||||
/// </summary>
|
||||
private ConnectionConfig PrimaryDBConfig { get; }
|
||||
/// <summary>
|
||||
/// 从数据库配置
|
||||
/// </summary>
|
||||
private ConnectionConfig SecondaryDBConfig { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[主数据库配置]{PrimaryDBConfig.ConnectionString}" + Environment.NewLine +
|
||||
$"[从数据库配置]{SecondaryDBConfig.ConnectionString}" + Environment.NewLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查网络状态
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool GetNetworkState()
|
||||
{
|
||||
var isOpen = DBSync.IsPortOpen(); // 数据库基类获取网络状态
|
||||
if (!isOpen)
|
||||
{
|
||||
DBSync.SetIsNeedSyncData(true); // 远程数据库查询失败,尝试本地数据库
|
||||
}
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回从数据库
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SqlSugarClient GetSecondaryDB()
|
||||
{
|
||||
DBSync.SyncEvent.Wait();
|
||||
return new SqlSugarClient(SecondaryDBConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回主数据库
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据库同步异常
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 远程、本地数据库同步
|
||||
/// </summary>
|
||||
public static class DBSync
|
||||
{
|
||||
/// <summary>
|
||||
/// 主数据库配置
|
||||
/// </summary>
|
||||
|
||||
private static ConnectionConfig PrimaryConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 从数据库配置
|
||||
/// </summary>
|
||||
|
||||
private static ConnectionConfig SecondaryConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主数据库IP
|
||||
/// </summary>
|
||||
|
||||
private static string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 主数据库端口
|
||||
/// </summary>
|
||||
private static int Port { get; set; }
|
||||
/// <summary>
|
||||
/// 同步数据事件(远程数据库,本地数据库,是否执行成功)
|
||||
/// </summary>
|
||||
|
||||
private static Func<SqlSugarClient, SqlSugarClient, bool> SyncDataEvent { get; set; }
|
||||
|
||||
|
||||
private static Action<bool> StateChangeEvent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据库设置锁
|
||||
/// </summary>
|
||||
//private static object DBSetLock { get; set; } = new object();
|
||||
/// <summary>
|
||||
/// 是否需要同步数据
|
||||
/// </summary>
|
||||
private static bool IsNeedSyncData { get; set; } = false;
|
||||
/// <summary>
|
||||
/// 等待次数(执行了多少次操作后才尝试进行同步,设置为0容易影响性能)
|
||||
/// </summary>
|
||||
private static int WaitCount { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 客户端获取计数
|
||||
/// </summary>
|
||||
private static int CrudDBGetCount { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// 同步端获取计数
|
||||
/// </summary>
|
||||
private static int SyncDBGetCount { get; set; } = 0;
|
||||
|
||||
|
||||
//public static ManualResetEventSlim SyncEvent { get; } = new ManualResetEventSlim(true); // 同步事件
|
||||
/// <summary>
|
||||
/// 远程本地同步阻塞事件
|
||||
/// </summary>
|
||||
public static FifoManualResetEvent SyncEvent { get; } = new FifoManualResetEvent(true);
|
||||
/// <summary>
|
||||
/// 数据同步锁
|
||||
/// </summary>
|
||||
private static object SyncLock { get; } = new object();
|
||||
/// <summary>
|
||||
/// 是否需要同步数据读写锁
|
||||
/// </summary>
|
||||
private static readonly ReaderWriterLockSlim NeedSyncStateLock = new ReaderWriterLockSlim();
|
||||
|
||||
/// <summary>
|
||||
/// 是否断开过,true=断开过,false=没有断开过
|
||||
/// 设置为 false 时自动检测网络情况,只有在网络正常的情况下才能成功设置为 true
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 配置主数据库
|
||||
/// </summary>
|
||||
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}");
|
||||
}*/
|
||||
}
|
||||
/// <summary>
|
||||
/// 配置从数据库
|
||||
/// </summary>
|
||||
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}");
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试执行一次数据同步
|
||||
/// </summary>
|
||||
public static bool SyncData()
|
||||
{
|
||||
SetIsNeedSyncData(true);
|
||||
var state = StartSyncDataBase(true); // 手动同步
|
||||
return state == DBSyncStart.SyncSuccess || state == DBSyncStart.NotNeed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置同步事件与等待次数。
|
||||
/// </summary>
|
||||
/// <param name="syncDataEvent">同步事件(需要手动同步数据)</param>
|
||||
/// <param name="waitCount">等待次数(执行了多少次操作后才尝试进行同步,设置为0容易影响性能)</param>
|
||||
public static void SetSyncEvent(Func<SqlSugarClient, SqlSugarClient, bool> syncDataEvent, int waitCount = 0)
|
||||
{
|
||||
SyncDataEvent = syncDataEvent;
|
||||
WaitCount = waitCount;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置状态变化事件
|
||||
/// </summary>
|
||||
/// <param name="stateChangeEvent"></param>
|
||||
/// <param name="isAtOnce"></param>
|
||||
public static void SetStateChangeEvent(Action<bool> stateChangeEvent)
|
||||
{
|
||||
StateChangeEvent = stateChangeEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库配置(不推荐使用在除了Repository的地方外部调用)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测目标地址是否打通
|
||||
/// </summary>
|
||||
/// <param name="ip">ip地址</param>
|
||||
/// <param name="port">端口号</param>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 检测目标地址是否打通:主数据库IP和端口是否打通(true通,false断)
|
||||
/// </summary>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回数据库连接串
|
||||
/// </summary>
|
||||
/// <param name="dbType">数据库类型</param>
|
||||
/// <param name="host">服务器IP地址</param>
|
||||
/// <param name="dbName">数据库名</param>
|
||||
/// <param name="name">登录账户</param>
|
||||
/// <param name="password">登录密码</param>
|
||||
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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
namespace Serein.DbSql
|
||||
{
|
||||
/// <summary>
|
||||
/// 线程阻塞
|
||||
/// </summary>
|
||||
public class FifoManualResetEvent
|
||||
{
|
||||
private readonly object lockObj = new object();
|
||||
/// <summary>
|
||||
/// 让线程按进入时间顺序调用
|
||||
/// </summary>
|
||||
private readonly Queue<Thread> waitQueue = new Queue<Thread>();
|
||||
private bool isSet;
|
||||
|
||||
public bool IsSet { get => isSet; set => isSet = value; }
|
||||
|
||||
public FifoManualResetEvent(bool initialState = false)
|
||||
{
|
||||
IsSet = initialState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待解锁
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送信号
|
||||
/// </summary>
|
||||
public void Set()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
IsSet = true;
|
||||
Monitor.PulseAll(lockObj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 锁定当前线程
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
IsSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Serein.DbSql
|
||||
{
|
||||
public interface IRepositoryBase<TEntity> where TEntity : class, new()
|
||||
{
|
||||
TEntity GetModelByID(dynamic ID);
|
||||
|
||||
int Add(TEntity Model);
|
||||
|
||||
int Update(TEntity Model);
|
||||
|
||||
bool DeleteByID(dynamic ID);
|
||||
|
||||
bool Delete(Expression<Func<TEntity, bool>> where);
|
||||
|
||||
int UpdateColumns(TEntity model, Expression<Func<TEntity, object>> expression);
|
||||
}
|
||||
}
|
||||
@@ -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<TEntity> : DataBase, IRepositoryBase<TEntity> where TEntity : class, new()
|
||||
public class RepositoryBase<TEntity> : IRepositoryBase<TEntity> where TEntity : class, new()
|
||||
{
|
||||
public bool isHaveErr;
|
||||
|
||||
public string ErrMsg = "";
|
||||
|
||||
public string filterName = "SubSystemName";
|
||||
~RepositoryBase()
|
||||
{
|
||||
DBSync.ReSetCrudDb();
|
||||
}
|
||||
public RepositoryBase()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否优先使用本地数据库
|
||||
/// </summary>
|
||||
public bool IsUseLoaclDB = false;
|
||||
|
||||
|
||||
#region 数据库操作 泛型抽象方法
|
||||
|
||||
#region 优先查询 主数据库
|
||||
|
||||
/// <summary>
|
||||
/// 无状态数据操作(查询)泛型抽象方法
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
public virtual T SyncExecuteRead<T>(Func<SqlSugarClient, T> 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()} ");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 无状态数据操作(查询)泛型抽象方法
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
public virtual T SyncExecuteRead<T>(Func<SimpleClient<TEntity>, T> func)
|
||||
{
|
||||
var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置
|
||||
|
||||
if (IsUseLoaclDB)
|
||||
{
|
||||
var secondaryDB = syncSqlConfig.GetSecondaryDB().GetSimpleClient<TEntity>();
|
||||
return func.Invoke(secondaryDB); // 尝试查询本地数据库
|
||||
}
|
||||
|
||||
if (syncSqlConfig.GetNetworkState()) // 网络检测
|
||||
{
|
||||
try
|
||||
{
|
||||
var primaryDB = syncSqlConfig.GetPrimaryDB()?.GetSimpleClient<TEntity>();
|
||||
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<TEntity>();
|
||||
return func.Invoke(secondaryDB); // 尝试查询本地数据库
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new DBSyncException(DBSyncExType.CrudError, $"主从数据库不可用。\r\n {syncSqlConfig.ToString()} ");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 优先查询 从数据库 (已注释)
|
||||
/* /// <summary>
|
||||
/// 无状态数据操作(查询)泛型抽象方法
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
public virtual T ExecuteSyncOperation<T>(Func<SqlSugarClient, T> 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()} ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无状态数据操作(查询)泛型抽象方法
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="func"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
public virtual T ExecuteSyncOperation<T>(Func<SimpleClient<TEntity>, T> func)
|
||||
{
|
||||
DBSync.SyncEvent.Wait();
|
||||
|
||||
var secondaryDB = SyncSqlConfig.GetSecondaryDB().GetSimpleClient<TEntity>();
|
||||
|
||||
try
|
||||
{
|
||||
return func.Invoke(secondaryDB); // 优先尝试查询本地数据库
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 本地数据库查询失败,尝试远程数据库
|
||||
try
|
||||
{
|
||||
var primaryDB = SyncSqlConfig.GetPrimaryDB()?.GetSimpleClient<TEntity>();
|
||||
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 增加、更新、删除 操作泛型方法
|
||||
/// <summary>
|
||||
/// 有状态数据操作(更新、增加、删除)泛型抽象方法,优先操作本地数据库,操作远程数据库失败时调用DBSync.SetIsNeedSyncData(true);
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="primaryFunc"></param>
|
||||
/// <param name="secondaryFunc"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="DBSyncException"></exception>
|
||||
public virtual T SyncExecuteCUD<T>(Func<SqlSugarClient, T> 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<T>(Func<SimpleClient<TEntity>, T> func)
|
||||
{
|
||||
var syncSqlConfig = DBSync.GetSyncSqlConfig(); // 基类获取数据库配置
|
||||
var secondaryDB = syncSqlConfig.GetSecondaryDB().GetSimpleClient<TEntity>();
|
||||
|
||||
try
|
||||
{
|
||||
var secondaryResult = func.Invoke(secondaryDB); // 本地数据库操作
|
||||
if (IsUseLoaclDB)
|
||||
{
|
||||
return secondaryResult;
|
||||
}
|
||||
if (syncSqlConfig.GetNetworkState()) // 网络检测
|
||||
{
|
||||
var primaryDB = syncSqlConfig.GetPrimaryDB().GetSimpleClient<TEntity>();
|
||||
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<SqlSugarClient, TEntity> func)
|
||||
{
|
||||
return SyncExecuteRead(func);
|
||||
}
|
||||
|
||||
public bool SyncRead(Func<SqlSugarClient, bool> func)
|
||||
{
|
||||
return SyncExecuteRead(func);
|
||||
}
|
||||
|
||||
public List<T> SyncRead<T>(Func<SqlSugarClient, List<T>> func)
|
||||
{
|
||||
return SyncExecuteRead(func);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查询返回实体
|
||||
/// </summary>
|
||||
public TEntity SyncRead(Func<SimpleClient<TEntity>, TEntity> func)
|
||||
{
|
||||
return SyncExecuteRead(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询返回实体列表
|
||||
/// </summary>
|
||||
public List<T> SyncRead<T>(Func<SimpleClient<TEntity>, List<T>> func)
|
||||
{
|
||||
return SyncExecuteRead(func);
|
||||
}
|
||||
|
||||
public TEntity SyncCUD(Func<SqlSugarClient, TEntity> func)
|
||||
{
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
public int SyncCUD(Func<SqlSugarClient, int> func)
|
||||
{
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
public bool SyncCUD(Func<SqlSugarClient, bool> func)
|
||||
{
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
public TEntity SyncSimpleCUD(Func<SimpleClient<TEntity>, TEntity> func)
|
||||
{
|
||||
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
public int SyncSimpleCUD(Func<SimpleClient<TEntity>, int> func)
|
||||
{
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
public bool SyncSimpleCUD(Func<SimpleClient<TEntity>, bool> func)
|
||||
{
|
||||
return SyncExecuteCUD(func);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public virtual TEntity GetModelByID(dynamic ID)
|
||||
{
|
||||
return SyncRead(db => db.GetById(ID));
|
||||
}
|
||||
|
||||
public virtual TEntity GetModel(Expression<Func<TEntity, bool>> where)
|
||||
{
|
||||
try
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().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<Func<TEntity, bool>> where)
|
||||
{
|
||||
try
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().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<Func<TEntity, object>> 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<TEntity>().RemoveDataCache().ExecuteCommand());
|
||||
return SyncSimpleCUD(db => (bool)db.DeleteById(ID));
|
||||
}
|
||||
|
||||
|
||||
public virtual bool Delete(Expression<Func<TEntity, bool>> where)
|
||||
{
|
||||
return SyncSimpleCUD(db => db.Delete(where));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual string GetPageList(Pagination pagination, Expression<Func<TEntity, bool>> 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<Func<TEntity, bool>> expression)
|
||||
{
|
||||
//DatabaseSync.StartcaControls();
|
||||
return SyncRead(db => db.Queryable<TEntity>().Filter(filterName, isDisabledGobalFilter: true).Single(expression));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public virtual List<TEntity> GetTop(int Top, Expression<Func<TEntity, object>> expression, OrderByType _OrderByType = OrderByType.Asc, Expression<Func<TEntity, bool>> where = null, string selstr = "*")
|
||||
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().Select(selstr).WhereIF(where != null, where)
|
||||
.Take(Top)
|
||||
.OrderBy(expression, _OrderByType)
|
||||
.Filter(filterName, isDisabledGobalFilter: true)
|
||||
.ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 排序表达式所用的键,排序方式,搜索条件
|
||||
/// </summary>
|
||||
/// <param name="OrderExpression"></param>
|
||||
/// <param name="_OrderByType"></param>
|
||||
/// <param name="where"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public virtual TEntity GetFirst(Expression<Func<TEntity, object>> OrderExpression, OrderByType _OrderByType = OrderByType.Asc, Expression<Func<TEntity, bool>> where = null)
|
||||
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().Filter(filterName, isDisabledGobalFilter: true).WhereIF(where != null, where)
|
||||
.OrderBy(OrderExpression, _OrderByType)
|
||||
.First());
|
||||
}
|
||||
|
||||
|
||||
public virtual List<TEntity> GetList(Pagination pagination, Expression<Func<TEntity, bool>> where = null)
|
||||
|
||||
{
|
||||
int totalNumber = 0;
|
||||
List<TEntity> result = SyncRead(db => db.Queryable<TEntity>().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<TEntity> GetList(Expression<Func<TEntity, bool>> where = null)
|
||||
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().WhereIF(where != null, where).Filter(filterName, isDisabledGobalFilter: true)
|
||||
.ToList());
|
||||
}
|
||||
|
||||
public virtual List<TEntity> GetList()
|
||||
{
|
||||
return SyncRead(db => db.Queryable<TEntity>().ToList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public virtual DataTable GetDataTable(Expression<Func<TEntity, bool>> 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<TEntity>();
|
||||
}
|
||||
|
||||
|
||||
public virtual TEntity GetModelByID(dynamic ID)
|
||||
{
|
||||
return Sclient.GetById(ID);
|
||||
}
|
||||
|
||||
|
||||
public virtual TEntity GetModel(Expression<Func<TEntity, bool>> 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<Func<TEntity, bool>> where)
|
||||
{
|
||||
return db.Queryable<TEntity>().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<Func<TEntity, object>> expression)
|
||||
{
|
||||
return db.Updateable(model).UpdateColumns(expression).ExecuteCommand();
|
||||
}
|
||||
|
||||
|
||||
public virtual bool DeleteByID(dynamic ID)
|
||||
{
|
||||
db.Updateable<TEntity>().RemoveDataCache().ExecuteCommand();
|
||||
return Sclient.DeleteById(ID);
|
||||
}
|
||||
|
||||
|
||||
public virtual bool Delete(Expression<Func<TEntity, bool>> where)
|
||||
{
|
||||
return Sclient.Delete(where);
|
||||
}
|
||||
|
||||
|
||||
public virtual string GetPageList(Pagination pagination, Expression<Func<TEntity, bool>> where = null)
|
||||
{
|
||||
return new
|
||||
{
|
||||
rows = GetList(pagination, where),
|
||||
total = pagination.total,
|
||||
page = pagination.page,
|
||||
records = pagination.records
|
||||
}.ToJson();
|
||||
}
|
||||
|
||||
|
||||
public virtual TEntity GetSingle(Expression<Func<TEntity, bool>> expression)
|
||||
{
|
||||
return db.Queryable<TEntity>().Filter(filterName, isDisabledGobalFilter: true).Single(expression);
|
||||
}
|
||||
|
||||
|
||||
public virtual List<TEntity> GetTop(int Top, Expression<Func<TEntity, object>> expression, OrderByType _OrderByType = OrderByType.Asc, Expression<Func<TEntity, bool>> where = null, string selstr = "*")
|
||||
{
|
||||
return db.Queryable<TEntity>().Select(selstr).WhereIF(where != null, where)
|
||||
.Take(Top)
|
||||
.OrderBy(expression, _OrderByType)
|
||||
.Filter(filterName, isDisabledGobalFilter: true)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
public virtual TEntity GetFirst(Expression<Func<TEntity, object>> OrderExpression, OrderByType _OrderByType = OrderByType.Asc, Expression<Func<TEntity, bool>> where = null)
|
||||
{
|
||||
return db.Queryable<TEntity>().Filter(filterName, isDisabledGobalFilter: true).WhereIF(where != null, where)
|
||||
.OrderBy(OrderExpression, _OrderByType)
|
||||
.First();
|
||||
}
|
||||
|
||||
public virtual List<TEntity> GetList(Pagination pagination, Expression<Func<TEntity, bool>> where = null)
|
||||
{
|
||||
int totalNumber = 0;
|
||||
List<TEntity> result = db.Queryable<TEntity>().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<TEntity> GetList(Expression<Func<TEntity, bool>> where = null)
|
||||
{
|
||||
return db.Queryable<TEntity>().WhereIF(where != null, where).Filter(filterName, isDisabledGobalFilter: true)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public virtual List<TEntity> GetList()
|
||||
{
|
||||
return db.Queryable<TEntity>().ToList();
|
||||
}
|
||||
|
||||
|
||||
public virtual DataTable GetDataTable(Expression<Func<TEntity, bool>> 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
|
||||
{
|
||||
/// <summary>
|
||||
/// 每页行数
|
||||
/// </summary>
|
||||
public int rows { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public int page { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// /排序列
|
||||
/// </summary>
|
||||
|
||||
public string sidx { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 排序类型
|
||||
/// </summary>
|
||||
|
||||
public string sord { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 总记录数
|
||||
/// </summary>
|
||||
public int records { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总页数
|
||||
/// </summary>
|
||||
public int total
|
||||
{
|
||||
get
|
||||
{
|
||||
if (records > 0)
|
||||
{
|
||||
if (records % rows != 0)
|
||||
{
|
||||
return records / rows + 1;
|
||||
}
|
||||
|
||||
return records / rows;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.0.16</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||
<OutputType>Library</OutputType>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Title>SereinFow</Title>
|
||||
<Description>Net8运行时需要添加的依赖</Description>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="DbSql\**" />
|
||||
<Compile Remove="Flow\**" />
|
||||
<Compile Remove="Http\**" />
|
||||
<Compile Remove="IOC\**" />
|
||||
<Compile Remove="obj\**" />
|
||||
<Compile Remove="SerinExpression\**" />
|
||||
<Compile Remove="Tool\**" />
|
||||
<EmbeddedResource Remove="DbSql\**" />
|
||||
<EmbeddedResource Remove="Flow\**" />
|
||||
<EmbeddedResource Remove="Http\**" />
|
||||
<EmbeddedResource Remove="IOC\**" />
|
||||
<EmbeddedResource Remove="obj\**" />
|
||||
<EmbeddedResource Remove="SerinExpression\**" />
|
||||
<EmbeddedResource Remove="Tool\**" />
|
||||
<None Remove="DbSql\**" />
|
||||
<None Remove="Flow\**" />
|
||||
<None Remove="Http\**" />
|
||||
<None Remove="IOC\**" />
|
||||
<None Remove="obj\**" />
|
||||
<None Remove="SerinExpression\**" />
|
||||
<None Remove="Tool\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="ServiceContainer.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
<None Include="..\README.md">
|
||||
<Pack>True</Pack>
|
||||
<PackagePath>\</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,188 +0,0 @@
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Serein.Library.Framework.NodeFlow
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 动态流程上下文
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
/// </summary>
|
||||
public IFlowEnvironment Env { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 运行状态
|
||||
/// </summary>
|
||||
public RunState RunState { get; set; } = RunState.NoStart;
|
||||
|
||||
/// <summary>
|
||||
/// 用来在当前流程上下文间传递数据
|
||||
/// </summary>
|
||||
//public Dictionary<string, object> ContextShareData { get; } = new Dictionary<string, object>();
|
||||
public object Tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点执行完成后,设置该属性,让运行环境判断接下来要执行哪个分支的节点。
|
||||
/// </summary>
|
||||
public ConnectionInvokeType NextOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 运行时异常信息
|
||||
/// </summary>
|
||||
public Exception ExceptionOfRuning { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个上下文分别存放节点的当前数据
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, object> dictNodeFlowData = new ConcurrentDictionary<string, object>();
|
||||
|
||||
private readonly ConcurrentDictionary<NodeModelBase, NodeModelBase> dictPreviousNodes = new ConcurrentDictionary<NodeModelBase, NodeModelBase>();
|
||||
|
||||
/// <summary>
|
||||
/// 设置运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel">当前节点</param>
|
||||
/// <param name="PreviousNode">上一节点</param>
|
||||
public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
|
||||
{
|
||||
dictPreviousNodes.AddOrUpdate(currentNodeModel, (n1) => PreviousNode, (n1, n2) => PreviousNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前节点的运行时上一节点
|
||||
/// </summary>
|
||||
/// <param name="currentNodeModel"></param>
|
||||
/// <returns></returns>
|
||||
public NodeModelBase GetPreviousNode(NodeModelBase currentNodeModel)
|
||||
{
|
||||
if (dictPreviousNodes.TryGetValue(currentNodeModel, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点当前数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public object GetFlowData(string nodeGuid)
|
||||
{
|
||||
if (dictNodeFlowData.TryGetValue(nodeGuid, out var data))
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新当前节点数据
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <param name="flowData">新的数据</param>
|
||||
public void AddOrUpdate(string nodeGuid, object flowData)
|
||||
{
|
||||
// this.dictNodeFlowData.TryGetValue(nodeGuid, out var oldFlowData);
|
||||
this.dictNodeFlowData.AddOrUpdate(nodeGuid, n1 => flowData, (n1, n2)=> flowData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一节点数据透传到下一节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 结束流程
|
||||
/// </summary>
|
||||
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<NodeRunCts>();
|
||||
// }
|
||||
// // 使用局部变量,避免捕获外部的 `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;
|
||||
// });
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 传入触发器方法的返回类型,尝试获取Task[Flipflop[]] 中的泛型类型
|
||||
/// </summary>
|
||||
//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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发器上下文
|
||||
/// </summary>
|
||||
public class FlipflopContext<TResult> : IFlipflopContext<TResult>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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("")]
|
||||
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{73B272E8-222D-4D08-A030-F1E1DB70B9D1}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Serein.Library.Framework</RootNamespace>
|
||||
<AssemblyName>Serein.Library.Framework</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\.Output\Debug\librarynet462\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\.Output\Release\librarynet462\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\.Output\Release\librarynet462\Serein.Library.Framework.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FlipflopContext.cs" />
|
||||
<Compile Include="DynamicContext.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj">
|
||||
<Project>{5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3}</Project>
|
||||
<Name>Serein.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -710,7 +710,6 @@ namespace Serein.Library.Api
|
||||
/// <param name="type"></param>
|
||||
void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 加载项目文件
|
||||
/// </summary>
|
||||
@@ -960,6 +959,11 @@ namespace Serein.Library.Api
|
||||
/// <returns></returns>
|
||||
bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del);
|
||||
|
||||
/// <summary>
|
||||
/// 提供设置UI上下文的能力
|
||||
/// </summary>
|
||||
/// <param name="uiContextOperation"></param>
|
||||
void SetUIContextOperation(UIContextOperation uiContextOperation);
|
||||
|
||||
/// <summary>
|
||||
/// 开始运行
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
public enum NodeType
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 初始化,流程启动时执行(不生成节点)
|
||||
/// <para>可以异步等待</para>
|
||||
@@ -28,6 +29,7 @@ namespace Serein.Library
|
||||
/// </summary>
|
||||
Exit,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <para>触发器节点,必须为标记在可异步等待的方法,建议与继承了 FlowTriggerk<TEnum> 的实例对象搭配使用</para>
|
||||
/// <para>方法返回值必须为Task<IFlipflopContext<TResult>>,若为其它返回值,将不会创建节点。</para>
|
||||
|
||||
384
Library/FlowNode/ContainerFlowEnvironment.cs
Normal file
384
Library/FlowNode/ContainerFlowEnvironment.cs
Normal file
@@ -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
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 不提供流程操作能力,仅提供容器功能
|
||||
/// </summary>
|
||||
|
||||
public class ContainerFlowEnvironment : IFlowEnvironment, ISereinIOC
|
||||
{
|
||||
/// <summary>
|
||||
/// 本地运行环境缓存的持久化实例
|
||||
/// </summary>
|
||||
private Dictionary<string, object> PersistennceInstance { get; } = new Dictionary<string, object>();
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置在UI线程操作的线程上下文
|
||||
/// </summary>
|
||||
/// <param name="uiContextOperation"></param>
|
||||
public void SetUIContextOperation(UIContextOperation uiContextOperation)
|
||||
{
|
||||
this.UIContextOperation = uiContextOperation;
|
||||
}
|
||||
|
||||
public void ActivateFlipflopNode(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> ChangeParameter(string nodeGuid, bool isAdd, int paramIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> ConnectArgSourceNodeAsync(string fromNodeGuid, string toNodeGuid, JunctionType fromNodeJunctionType, JunctionType toNodeJunctionType, ConnectionArgSourceType argSourceType, int argIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> 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<NodeInfo> CreateNodeAsync(NodeControlType nodeType, PositionOfUI position, MethodDetailsInfo methodDetailsInfo = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> ExitFlowAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void ExitRemoteEnv()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<SereinProjectData> GetProjectInfoAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<object> 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<NodeInfo> 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<bool> PlaceNodeToContainerAsync(string nodeGuid, string containerNodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> RemoveConnectArgSourceAsync(string fromNodeGuid, string toNodeGuid, int argIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> RemoveConnectInvokeAsync(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> RemoveNodeAsync(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SaveProject()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> SetConnectPriorityInvoke(string fromNodeGuid, string toNodeGuid, ConnectionInvokeType connectionType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<string> SetStartNodeAsync(string nodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> StartAsyncInSelectNode(string startNodeGuid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> StartFlowAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task StartRemoteServerAsync(int port = 7525)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void StopRemoteServer()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<bool> 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<T>(params object[] parameters)
|
||||
{
|
||||
sereinIOC.Register<T>(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Register<TService, TImplementation>(params object[] parameters)
|
||||
{
|
||||
sereinIOC.Register<TService, TImplementation>(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
//T ISereinIOC.GetOrRegisterInstantiate<T>()
|
||||
//{
|
||||
// return sereinIOC.GetOrRegisterInstantiate<T>();
|
||||
|
||||
//}
|
||||
|
||||
//object ISereinIOC.GetOrRegisterInstantiate(Type type)
|
||||
//{
|
||||
// return sereinIOC.GetOrRegisterInstantiate(type);
|
||||
//}
|
||||
|
||||
object ISereinIOC.Get(Type type)
|
||||
{
|
||||
return sereinIOC.Get(type);
|
||||
|
||||
}
|
||||
T ISereinIOC.Get<T>()
|
||||
{
|
||||
return (T)sereinIOC.Get(typeof(T));
|
||||
}
|
||||
T ISereinIOC.Get<T>(string key)
|
||||
{
|
||||
return sereinIOC.Get<T>(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<T>()
|
||||
{
|
||||
return sereinIOC.Instantiate<T>();
|
||||
}
|
||||
ISereinIOC ISereinIOC.Build()
|
||||
{
|
||||
sereinIOC.Build();
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T>(Action<T> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2>(Action<T1, T2> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3>(Action<T1, T2, T3> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
ISereinIOC ISereinIOC.Run<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> action)
|
||||
{
|
||||
sereinIOC.Run(action);
|
||||
return this;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@@ -52,7 +54,7 @@ namespace Serein.Library.Core
|
||||
/// <summary>
|
||||
/// 每个流程上下文分别存放节点的当前数据
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, object?> dictNodeFlowData = new ConcurrentDictionary<string, object?>();
|
||||
private readonly ConcurrentDictionary<string, object> dictNodeFlowData = new ConcurrentDictionary<string, object>();
|
||||
|
||||
/// <summary>
|
||||
/// 每个流程上下文存储运行时节点的调用关系
|
||||
@@ -66,7 +68,7 @@ namespace Serein.Library.Core
|
||||
/// <param name="PreviousNode">上一节点</param>
|
||||
public void SetPreviousNode(NodeModelBase currentNodeModel, NodeModelBase PreviousNode)
|
||||
{
|
||||
dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (_, _) => PreviousNode);
|
||||
dictPreviousNodes.AddOrUpdate(currentNodeModel, (_) => PreviousNode, (o, n) => PreviousNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -91,7 +93,7 @@ namespace Serein.Library.Core
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <returns></returns>
|
||||
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
|
||||
/// </summary>
|
||||
/// <param name="nodeGuid">节点</param>
|
||||
/// <param name="flowData">新的数据</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上一节点数据透传到下一节点
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
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)
|
||||
{
|
||||
@@ -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
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.0.19</Version>
|
||||
<Version>1.1.0</Version>
|
||||
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
|
||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -96,10 +96,6 @@
|
||||
<Compile Include="Web\PlcSocketService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\DynamicControl\SereinFlow\Library.Framework\Serein.Library.Framework.csproj">
|
||||
<Project>{73B272E8-222D-4D08-A030-F1E1DB70B9D1}</Project>
|
||||
<Name>Serein.Library.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj">
|
||||
<Project>{5e19d0f2-913a-4d1c-a6f8-1e1227baa0e3}</Project>
|
||||
<Name>Serein.Library</Name>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
/// </summary>
|
||||
@@ -44,7 +27,7 @@ namespace Serein.NodeFlow.Env
|
||||
/// <summary>
|
||||
/// 流程运行环境
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置在UI线程操作的线程上下文
|
||||
/// </summary>
|
||||
/// <param name="uiContextOperation"></param>
|
||||
public void SetUIContextOperation(UIContextOperation uiContextOperation)
|
||||
{
|
||||
this.UIContextOperation = uiContextOperation;
|
||||
var fullName = typeof(UIContextOperation).FullName;
|
||||
if (!string.IsNullOrEmpty(fullName))
|
||||
{
|
||||
PersistennceInstance[fullName] = uiContextOperation; // 缓存封装好的UI线程上下文
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移动了某个节点(远程插件使用)
|
||||
@@ -1401,6 +1397,8 @@ namespace Serein.NodeFlow.Env
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region 流程依赖类库的接口
|
||||
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ namespace Serein.NodeFlow.Env
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置在UI线程操作的线程上下文
|
||||
/// </summary>
|
||||
/// <param name="uiContextOperation"></param>
|
||||
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);
|
||||
|
||||
@@ -1244,7 +1244,7 @@ namespace Serein.NodeFlow.Env
|
||||
del = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 对象监视表达式
|
||||
@@ -1268,7 +1268,14 @@ namespace Serein.NodeFlow.Env
|
||||
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口:TriggerInterrupt");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置在UI线程操作的线程上下文
|
||||
/// </summary>
|
||||
/// <param name="uiContextOperation"></param>
|
||||
public void SetUIContextOperation(UIContextOperation uiContextOperation)
|
||||
{
|
||||
// 无须实现
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
@@ -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); // 全局触发器触发后刷新该触发器的节点数据
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.0.19</Version>
|
||||
<Version>1.1.0</Version>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -47,6 +47,7 @@
|
||||
<Compile Remove="Tool\ExpressionHelper.cs" />
|
||||
<Compile Remove="Tool\NodeModelBaseFunc.cs" />
|
||||
<Compile Remove="Tool\TcsSignal.cs" />
|
||||
<Compile Remove="Tool\ToCSharpCodeHelper.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
262
NodeFlow/Tool/ToCSharpCodeHelper.cs
Normal file
262
NodeFlow/Tool/ToCSharpCodeHelper.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
/// </summary>
|
||||
private readonly IFlowEnvironment env;
|
||||
/// <summary>
|
||||
/// 环境中已加载的所有节点
|
||||
/// </summary>
|
||||
private readonly List<NodeModelBase> nodes;
|
||||
/// <summary>
|
||||
/// 获取流程启动时在不同时间点需要自动实例化的类型
|
||||
/// </summary>
|
||||
private readonly Dictionary<RegisterSequence, List<Type>> autoRegisterTypes;
|
||||
/// <summary>
|
||||
/// 初始化方法
|
||||
/// </summary>
|
||||
private readonly List<MethodDetails> initMethods;
|
||||
/// <summary>
|
||||
/// 加载时方法
|
||||
/// </summary>
|
||||
private readonly List<MethodDetails> loadingMethods;
|
||||
/// <summary>
|
||||
/// 结束时方法
|
||||
/// </summary>
|
||||
private readonly List<MethodDetails> exitMethods;
|
||||
|
||||
/// <summary>
|
||||
/// 开始运行(需要准备好方法信息)
|
||||
/// </summary>
|
||||
/// <param name="env">运行环境</param>
|
||||
/// <param name="nodes">环境中已加载的所有节点</param>
|
||||
/// <param name="autoRegisterTypes">获取流程启动时在不同时间点需要自动实例化的类型</param>
|
||||
/// <param name="initMethods">初始化方法</param>
|
||||
/// <param name="loadingMethods">加载时方法</param>
|
||||
/// <param name="exitMethods">结束时方法</param>
|
||||
/// <returns></returns>
|
||||
public ToCSharpCodeHelper(IFlowEnvironment env,
|
||||
List<NodeModelBase> nodes,
|
||||
Dictionary<RegisterSequence, List<Type>> autoRegisterTypes,
|
||||
List<MethodDetails> initMethods,
|
||||
List<MethodDetails> loadingMethods,
|
||||
List<MethodDetails> 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<PlcLoginControl>();
|
||||
var networkLoginControl = ioc.Get<PlcLoginControl>();
|
||||
|
||||
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<object> action)
|
||||
{
|
||||
|
||||
}
|
||||
public async object Execution(Func<Task> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加代码
|
||||
/// </summary>
|
||||
/// <param name="sb">字符串构建器</param>
|
||||
/// <param name="retractCount">缩进次数(4个空格)</param>
|
||||
/// <param name="code">要添加的代码</param>
|
||||
/// <returns>字符串构建器本身</returns>
|
||||
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<string> SeparateLineIntoMultipleDefinitions(ReadOnlySpan<char> line)
|
||||
{
|
||||
List<string> definitions = new List<string>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,7 @@
|
||||
不定期在Bilibili个人空间上更新相关的视频。
|
||||
https://space.bilibili.com/33526379
|
||||
|
||||
# 暂停更新 Workbench(WPF)项目
|
||||
* 正在使用 Avalonia UI 重写该项目,Library 相关接口可能随时变动,重写进展不定时在个人空间更新。
|
||||
|
||||
# 计划任务 2024年10月28日更新
|
||||
* 重新完善远程管理与远程客户端的功能(目前仅支持远程修改节点属性、添加/移除节点、启动流程、停止流程)
|
||||
* 重新完善节点树视图、IOC容器对象视图(目前残废版)
|
||||
|
||||
@@ -521,7 +521,7 @@ namespace Serein.Library.NodeGenerator
|
||||
/// <para>通过条件检查缓存的信息,决定是否添加代码</para>
|
||||
/// <para>首先检查是否存在该特性,如果不存在,返回 false。</para>
|
||||
/// <para>然后检查是否存在属性,如果不存在,返回 false</para>
|
||||
/// <para>如果存在属性,则返回属性对应的值与 comparisonValue 进行比较,返回
|
||||
/// <para>如果存在属性,则返回属性对应的值与 comparisonValue 进行比较,返回</para>
|
||||
/// <para></para>
|
||||
/// <para>若只传入 attributeName 参数,则只会检查是否存在该特性</para>
|
||||
/// <para>若只传入 attributeName与attributePropertyName 参数,则只会检查是否存在该特性的该属性</para>
|
||||
@@ -529,7 +529,7 @@ namespace Serein.Library.NodeGenerator
|
||||
/// <param name="dict">缓存的特性信息</param>
|
||||
/// <param name="attributeName">查询的特性名称</param>
|
||||
/// <param name="attributePropertyName">查询的特性属性名称</param>
|
||||
/// <param name="comparisonValue">比较值</param>
|
||||
/// <param name="judgeFunc">比较方法</param>
|
||||
/// <returns>如果存在查询项,返回 true ,否则返回 false</returns>
|
||||
public static bool Search(this Dictionary<string, Dictionary<string, string>> dict,
|
||||
string attributeName = null,
|
||||
@@ -569,7 +569,6 @@ namespace Serein.Library.NodeGenerator
|
||||
var retract = new string(' ', retractCount * 4);
|
||||
sb.AppendLine(retract + code);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>1.0.1</Version>
|
||||
<Version>1.1.0</Version>
|
||||
<IsRoslynComponent>true</IsRoslynComponent>
|
||||
|
||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
@@ -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<App>
|
||||
{
|
||||
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
|
||||
{
|
||||
return base.CustomizeAppBuilder(builder)
|
||||
.WithInterFont();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application android:label="AvaloniaTest" android:icon="@drawable/Icon" />
|
||||
</manifest>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<color android:color="@color/splash_background"/>
|
||||
</item>
|
||||
|
||||
<item android:drawable="@drawable/icon"
|
||||
android:width="120dp"
|
||||
android:height="120dp"
|
||||
android:gravity="center" />
|
||||
|
||||
</layer-list>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="splash_background">#212121</color>
|
||||
</resources>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="splash_background">#FFFFFF</color>
|
||||
</resources>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<resources>
|
||||
|
||||
<style name="MyTheme">
|
||||
</style>
|
||||
|
||||
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowBackground">@drawable/splash_screen</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,28 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0-android</TargetFramework>
|
||||
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ApplicationId>com.CompanyName.AvaloniaTest</ApplicationId>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||
<AndroidPackageFormat>apk</AndroidPackageFormat>
|
||||
<AndroidEnableProfiledAot>False</AndroidEnableProfiledAot>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Icon.png">
|
||||
<Link>Resources\drawable\Icon.png</Link>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia.Android" Version="11.2.3" />
|
||||
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="11.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Serein.Workbench.Avalonia\Serein.Workbench.Avalonia.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -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<App>();
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")]
|
||||
@@ -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}",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-browser</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia.Browser" Version="11.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Serein.Workbench.Avalonia\Serein.Workbench.Avalonia.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"wasmHostProperties": {
|
||||
"perHostConfig": [
|
||||
{
|
||||
"name": "browser",
|
||||
"host": "browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 172 KiB |
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Serein.Workbench.Avalonia</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="./app.css" />
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden">
|
||||
<div id="out">
|
||||
<div class="avalonia-splash">
|
||||
<h2>
|
||||
Powered by
|
||||
<a href="https://www.avaloniaui.net/" target="_blank">
|
||||
<svg width="266" height="52" viewBox="0 0 266 52" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M55.8592 47.3941C54.9035 47.3941 54.1184 47.1723 53.504 46.7285C52.9237 46.2848 52.5483 45.6875 52.3776 44.9365C52.2411 44.1856 52.3947 43.3493 52.8384 42.4277L65.9456 13.7045C66.4917 12.544 67.1403 11.7077 67.8912 11.1957C68.6421 10.6496 69.5125 10.3765 70.5024 10.3765C71.4923 10.3765 72.3627 10.6496 73.1136 11.1957C73.8645 11.7077 74.496 12.544 75.008 13.7045L88.2176 42.4277C88.6613 43.3493 88.8149 44.2027 88.6784 44.9877C88.576 45.7387 88.2347 46.336 87.6544 46.7797C87.0741 47.1893 86.3232 47.3941 85.4016 47.3941C84.2411 47.3941 83.3365 47.1211 82.688 46.5749C82.0736 46.0288 81.5275 45.1755 81.0496 44.0149L78.9279 39.0997H62.0415L59.9552 44.0149C59.4432 45.2096 58.8971 46.08 58.3168 46.6261C57.7707 47.1381 56.9515 47.3941 55.8592 47.3941ZM70.4 19.2853L64.6844 32.9045H76.2627L70.5024 19.2853H70.4Z" fill="currentColor"/>
|
||||
<path d="M101.869 47.3941C100.879 47.3941 100.009 47.1381 99.258 46.6261C98.5071 46.08 97.9096 45.2779 97.4659 44.2197L89.7348 26.4021C89.3593 25.5147 89.2228 24.6955 89.3252 23.9445C89.4276 23.1595 89.786 22.5451 90.4004 22.1013C91.0489 21.6235 91.9364 21.3845 93.0628 21.3845C93.9844 21.3845 94.7353 21.6064 95.3156 22.0501C95.8959 22.4597 96.4079 23.2619 96.8516 24.4565L102.018 37.95L107.552 24.4053C108.03 23.2448 108.559 22.4597 109.14 22.0501C109.72 21.6064 110.522 21.3845 111.546 21.3845C112.433 21.3845 113.133 21.6235 113.645 22.1013C114.191 22.5451 114.516 23.1424 114.618 23.8933C114.755 24.6443 114.618 25.4635 114.208 26.3509L106.324 44.2197C105.88 45.312 105.283 46.1141 104.532 46.6261C103.815 47.1381 102.927 47.3941 101.869 47.3941Z" fill="currentColor"/>
|
||||
<path d="M126.569 47.4965C124.726 47.4965 123.07 47.1381 121.602 46.4213C120.135 45.7045 118.991 44.7317 118.172 43.5029C117.353 42.2741 116.943 40.8917 116.943 39.3557C116.943 37.5125 117.421 36.0619 118.377 35.0037C119.333 33.9115 120.886 33.1435 123.036 32.6997C125.186 32.2219 128.037 31.9829 131.586 31.9829H133.43V35.9765H131.638C129.897 35.9765 128.48 36.0789 127.388 36.2837C126.33 36.4544 125.562 36.7616 125.084 37.2053C124.64 37.6491 124.418 38.2635 124.418 39.0485C124.418 40.0043 124.743 40.7893 125.391 41.4037C126.074 42.0181 127.047 42.3253 128.31 42.3253C129.299 42.3253 130.17 42.1035 130.921 41.6597C131.706 41.1819 132.32 40.5504 132.764 39.7653C133.208 38.9461 133.43 38.0245 133.43 37.0005V31.1125C133.43 29.6107 133.088 28.5525 132.406 27.9381C131.723 27.2896 130.562 26.9653 128.924 26.9653C128.002 26.9653 126.995 27.0848 125.903 27.3237C124.845 27.5285 123.667 27.8869 122.37 28.3989C121.619 28.7403 120.954 28.8256 120.374 28.6549C119.793 28.4501 119.35 28.1088 119.042 27.6309C118.735 27.1189 118.582 26.5728 118.582 25.9925C118.582 25.3781 118.752 24.7979 119.094 24.2517C119.435 23.6715 119.998 23.2448 120.783 22.9717C122.387 22.3232 123.889 21.8795 125.289 21.6405C126.722 21.4016 128.037 21.2821 129.231 21.2821C131.859 21.2821 134.01 21.6747 135.682 22.4597C137.389 23.2107 138.669 24.3883 139.522 25.9925C140.376 27.5627 140.802 29.5936 140.802 32.0853V43.4517C140.802 44.7147 140.495 45.6875 139.881 46.3701C139.266 47.0528 138.379 47.3941 137.218 47.3941C136.058 47.3941 135.153 47.0528 134.505 46.3701C133.89 45.6875 133.583 44.7147 133.583 43.4517L133.594 43.15C133.594 43.15 133.293 44.032 132.61 44.8853C131.962 45.7045 131.126 46.3531 130.102 46.8309C129.078 47.2747 127.9 47.4965 126.569 47.4965Z" fill="currentColor"/>
|
||||
<path d="M155.632 47.4965C152.594 47.4965 150.324 46.6603 148.822 44.9877C147.321 43.2811 146.57 40.7552 146.57 37.4101V14.3189C146.57 13.0219 146.894 12.0491 147.542 11.4005C148.225 10.7179 149.198 10.3765 150.461 10.3765C151.69 10.3765 152.628 10.7179 153.277 11.4005C153.959 12.0491 154.301 13.0219 154.301 14.3189V37.1029C154.301 38.5024 154.591 39.5435 155.171 40.2261C155.786 40.8747 156.588 41.1989 157.578 41.1989C157.851 41.1989 158.107 41.1819 158.346 41.1477C158.585 41.1136 158.841 41.0965 159.114 41.0965C159.66 41.0283 160.035 41.1989 160.24 41.6085C160.479 41.984 160.598 42.752 160.598 43.9125C160.598 44.9365 160.394 45.7216 159.984 46.2677C159.574 46.7797 158.943 47.1211 158.09 47.2917C157.748 47.3259 157.356 47.36 156.912 47.3941C156.468 47.4624 156.042 47.4965 155.632 47.4965Z" fill="currentColor"/>
|
||||
<path d="M175.453 47.4965C172.756 47.4965 170.401 46.9675 168.387 45.9093C166.407 44.8512 164.871 43.3323 163.779 41.3525C162.687 39.3728 162.141 37.0347 162.141 34.3381C162.141 32.3243 162.448 30.5152 163.062 28.9109C163.677 27.3067 164.564 25.9413 165.725 24.8149C166.919 23.6544 168.336 22.784 169.974 22.2037C171.613 21.5893 173.439 21.2821 175.453 21.2821C178.149 21.2821 180.487 21.8112 182.467 22.8693C184.481 23.9275 186.034 25.4293 187.126 27.3749C188.253 29.3205 188.816 31.6416 188.816 34.3381C188.816 36.3861 188.492 38.2123 187.843 39.8165C187.229 41.4208 186.341 42.8032 185.181 43.9637C184.02 45.1243 182.604 46.0117 180.931 46.6261C179.293 47.2064 177.467 47.4965 175.453 47.4965ZM175.453 41.7109C176.579 41.7109 177.552 41.4379 178.371 40.8917C179.19 40.3456 179.839 39.5435 180.317 38.4853C180.795 37.3931 181.034 36.0107 181.034 34.3381C181.034 31.8464 180.522 30.0203 179.498 28.8597C178.474 27.6651 177.125 27.0677 175.453 27.0677C174.361 27.0677 173.388 27.3237 172.534 27.8357C171.715 28.3477 171.067 29.1499 170.589 30.2421C170.145 31.3003 169.923 32.6656 169.923 34.3381C169.923 36.8299 170.435 38.6901 171.459 39.9189C172.483 41.1136 173.814 41.7109 175.453 41.7109Z" fill="currentColor"/>
|
||||
<path d="M197.411 47.3941C196.148 47.3941 195.175 47.0528 194.492 46.3701C193.844 45.6875 193.52 44.7147 193.52 43.4517V25.2757C193.52 24.0128 193.844 23.0571 194.492 22.4085C195.175 21.7259 196.114 21.3845 197.308 21.3845C198.537 21.3845 199.476 21.7259 200.124 22.4085C200.773 23.0571 201.112 24.1871 201.112 25.45C201.141 25.3955 202.48 23.552 204.016 22.6645C205.586 21.7429 207.361 21.2821 209.34 21.2821C211.354 21.2821 213.01 21.6747 214.307 22.4597C215.604 23.2107 216.577 24.3712 217.225 25.9413C217.874 27.4773 218.198 29.44 218.198 31.8293V43.4517C218.198 44.7147 217.857 45.6875 217.174 46.3701C216.525 47.0528 215.57 47.3941 214.307 47.3941C213.078 47.3941 212.122 47.0528 211.44 46.3701C210.791 45.6875 210.467 44.7147 210.467 43.4517V32.1877C210.467 30.4469 210.143 29.2011 209.494 28.4501C208.88 27.6651 207.924 27.2725 206.627 27.2725C204.988 27.2725 203.674 27.7845 202.684 28.8085C201.729 29.8325 201.251 31.1979 201.251 32.9045V43.4517C201.251 46.08 199.971 47.3941 197.411 47.3941Z" fill="currentColor"/>
|
||||
<path d="M227.861 47.3429C226.598 47.3429 225.625 46.9845 224.942 46.2677C224.294 45.5168 223.97 44.4757 223.97 43.1445V25.6341C223.97 24.2688 224.294 23.2277 224.942 22.5109C225.625 21.76 226.598 21.3845 227.861 21.3845C229.09 21.3845 230.028 21.76 230.677 22.5109C231.359 23.2277 231.701 24.2688 231.701 25.6341V43.1445C231.701 44.4757 231.377 45.5168 230.728 46.2677C230.079 46.9845 229.124 47.3429 227.861 47.3429ZM227.861 17.1861C226.427 17.1861 225.318 16.8619 224.533 16.2133C223.782 15.5307 223.406 14.5749 223.406 13.3461C223.406 12.0832 223.782 11.1275 224.533 10.4789C225.318 9.79629 226.427 9.45496 227.861 9.45496C229.294 9.45496 230.387 9.79629 231.138 10.4789C231.889 11.1275 232.264 12.0832 232.264 13.3461C232.264 14.5749 231.889 15.5307 231.138 16.2133C230.387 16.8619 229.294 17.1861 227.861 17.1861Z" fill="currentColor"/>
|
||||
<path d="M246.169 47.4965C244.326 47.4965 242.67 47.1381 241.202 46.4213C239.735 45.7045 238.591 44.7317 237.772 43.5029C236.953 42.2741 236.543 40.8917 236.543 39.3557C236.543 37.5125 237.021 36.0619 237.977 35.0037C238.933 33.9115 240.486 33.1435 242.636 32.6997C244.786 32.2219 247.637 31.9829 251.186 31.9829H253.03V35.9765H251.238C249.497 35.9765 248.08 36.0789 246.988 36.2837C245.93 36.4544 245.162 36.7616 244.684 37.2053C244.24 37.6491 244.018 38.2635 244.018 39.0485C244.018 40.0043 244.343 40.7893 244.991 41.4037C245.674 42.0181 246.647 42.3253 247.91 42.3253C248.899 42.3253 249.77 42.1035 250.521 41.6597C251.306 41.1819 251.92 40.5504 252.364 39.7653C252.808 38.9461 253.03 38.0245 253.03 37.0005V31.1125C253.03 29.6107 252.688 28.5525 252.006 27.9381C251.323 27.2896 250.162 26.9653 248.524 26.9653C247.602 26.9653 246.595 27.0848 245.503 27.3237C244.445 27.5285 243.267 27.8869 241.97 28.3989C241.219 28.7403 240.554 28.8256 239.974 28.6549C239.393 28.4501 238.95 28.1088 238.642 27.6309C238.335 27.1189 238.182 26.5728 238.182 25.9925C238.182 25.3781 238.352 24.7979 238.694 24.2517C239.035 23.6715 239.598 23.2448 240.383 22.9717C241.987 22.3232 243.489 21.8795 244.889 21.6405C246.322 21.4016 247.637 21.2821 248.831 21.2821C251.459 21.2821 253.61 21.6747 255.282 22.4597C256.989 23.2107 258.269 24.3883 259.122 25.9925C259.976 27.5627 260.402 29.5936 260.402 32.0853V43.4517C260.402 44.7147 260.095 45.6875 259.481 46.3701C258.866 47.0528 257.979 47.3941 256.818 47.3941C255.658 47.3941 254.753 47.0528 254.105 46.3701C253.49 45.6875 253.183 44.7147 253.183 43.4517V43.1789C253.183 43.3144 252.893 44.032 252.21 44.8853C251.562 45.7045 250.726 46.3531 249.702 46.8309C248.678 47.2747 247.5 47.4965 246.169 47.4965Z" fill="currentColor"/>
|
||||
<path d="M22.3444 20.9916C18.7895 20.9916 15.9077 24.0073 15.9077 27.7274C15.9077 31.4475 18.7895 34.4632 22.3444 34.4632C25.8993 34.4632 28.7811 31.4475 28.7811 27.7274C28.7811 24.0073 25.8993 20.9916 22.3444 20.9916Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M37.6937 49.0667H21.9271C10.8346 48.8653 1.90173 39.3893 1.90173 27.7333C1.90173 15.9513 11.0289 6.40002 22.2878 6.40002C33.3638 6.40002 42.3768 15.6435 42.6667 27.161L42.6314 44.4824C42.338 47.0679 40.2434 49.0667 37.6937 49.0667ZM9.22617 24.667C10.5612 18.3725 15.9275 13.6656 22.3444 13.6656C29.7657 13.6656 35.7818 19.9613 35.7818 27.7274C35.7818 27.7857 35.7825 27.8488 35.7831 27.9136C35.7846 28.0483 35.7861 28.1901 35.7818 28.3103V41.6939H28.7907V40.0685C26.877 41.1655 24.6803 41.7892 22.3444 41.7892C15.9275 41.7892 10.5612 37.0823 9.22617 30.7878C10.5043 30.4129 11.4416 29.1847 11.4416 27.7274C11.4416 26.2701 10.5043 25.0419 9.22617 24.667ZM8.33937 29.9683C9.52696 29.9683 10.4897 28.9609 10.4897 27.7181C10.4897 26.4753 9.52696 25.4678 8.33937 25.4678C7.15178 25.4678 6.18904 26.4753 6.18904 27.7181C6.18904 28.9609 7.15178 29.9683 8.33937 29.9683Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</a>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<script type='module' src="./main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -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]);
|
||||
@@ -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>(uIContextOperation); // 注册UI线程操作上下文
|
||||
collection.AddSingleton<IFlowEnvironment>(flowEnvironmentDecorator); // 注册运行环境
|
||||
collection.AddSingleton<IFlowEnvironmentEvent>(flowEnvironmentDecorator); // 注册运行环境事件
|
||||
|
||||
@@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// 记录与该节点控件有关的所有连接
|
||||
/// </summary>
|
||||
private readonly List<NodeConnectionLineView> connectionControls = new List<NodeConnectionLineView>();
|
||||
|
||||
|
||||
//public NodeControlViewModelBase ViewModel { get; set; }
|
||||
|
||||
|
||||
@@ -42,48 +38,6 @@ namespace Serein.Workbench.Avalonia.Custom.Node.ViewModels
|
||||
public void SetNodeModel(NodeModelBase nodeModel) => this.NodeModel = nodeModel;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加与该节点有关的连接后,记录下来
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
public void AddCnnection(NodeConnectionLineView connection)
|
||||
{
|
||||
connectionControls.Add(connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除了连接之后,还需要从节点中的记录移除
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
public void RemoveConnection(NodeConnectionLineView connection)
|
||||
{
|
||||
connectionControls.Remove(connection);
|
||||
//connection.Remote();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有连接
|
||||
/// </summary>
|
||||
public void RemoveAllConection()
|
||||
{
|
||||
foreach (var connection in this.connectionControls)
|
||||
{
|
||||
//connection.Remote();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新与该节点有关的数据
|
||||
/// </summary>
|
||||
public void UpdateLocationConnections()
|
||||
{
|
||||
foreach (var connection in this.connectionControls)
|
||||
{
|
||||
//connection.RefreshLine(); // 主动更新连线位置
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置绑定:
|
||||
/// Canvas.X and Y : 画布位置
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<!--调用控制点,方法名称,下一个方法调用控制点-->
|
||||
<Grid x:Name="HeaderGrid" Grid.Row="0" ColumnDefinitions="auto,*,auto" VerticalAlignment="Center">
|
||||
<cv:NodeJunctionView Grid.Column="0" JunctionType="Execute" MyNode="{Binding NodeMoel}" Width="30" Height="15" Margin="4,0,2,0" />
|
||||
<cv:NodeJunctionView x:Name="ExecuteJunctionControl" Grid.Column="0" JunctionType="Execute" MyNode="{Binding NodeMoel}" Width="30" Height="15" Margin="4,0,2,0" />
|
||||
<StackPanel Grid.Column="1" Grid.RowSpan="2" >
|
||||
<TextBlock Text="{Binding NodeMoel.DisplayName}" FontSize="17" HorizontalAlignment="Center">
|
||||
<ToolTip.Tip>
|
||||
@@ -31,7 +31,7 @@
|
||||
</ToolTip.Tip>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<cv:NodeJunctionView Grid.Column="2" JunctionType="NextStep" MyNode="{Binding NodeMoel}" Width="30" Height="15" Margin="2,0,8,0"/>
|
||||
<cv:NodeJunctionView x:Name="NextStepJunctionControl" Grid.Column="2" JunctionType="NextStep" MyNode="{Binding NodeMoel}" Width="30" Height="15" Margin="2,0,8,0"/>
|
||||
</Grid>
|
||||
|
||||
<!--入参信息-->
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -14,13 +14,62 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Workbench.Avalonia.Custom.Node.Views
|
||||
{
|
||||
public class NodeControlBase : UserControl
|
||||
public abstract class NodeControlBase : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录与该节点控件有关的所有连接
|
||||
/// </summary>
|
||||
private readonly List<NodeConnectionLineControl> connectionControls = new List<NodeConnectionLineControl>();
|
||||
|
||||
protected NodeControlBase()
|
||||
{
|
||||
this.Background = Brushes.Transparent;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加与该节点有关的连接后,记录下来
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
public void AddConnection(NodeConnectionLineControl connection)
|
||||
{
|
||||
connectionControls.Add(connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除了连接之后,还需要从节点中的记录移除
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
public void RemoveConnection(NodeConnectionLineControl connection)
|
||||
{
|
||||
connectionControls.Remove(connection);
|
||||
connection.Remove();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除所有连接
|
||||
/// </summary>
|
||||
public void RemoveAllConection()
|
||||
{
|
||||
foreach (var connection in this.connectionControls)
|
||||
{
|
||||
connection.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新与该节点有关的数据
|
||||
/// </summary>
|
||||
public void UpdateLocationConnections()
|
||||
{
|
||||
foreach (var connection in this.connectionControls)
|
||||
{
|
||||
connection.RefreshLineDsiplay(); // 主动更新连线位置
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 放置在某个节点容器中
|
||||
/// </summary>
|
||||
|
||||
@@ -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(); // 触发重绘
|
||||
}
|
||||
/// <summary>
|
||||
/// 刷新颜色
|
||||
/// </summary>
|
||||
/// <param name="brush"></param>
|
||||
public void UpdateColor(Brush brush )
|
||||
{
|
||||
visualPen = new Pen(brush, 3.0); // 默认可视化Pen
|
||||
InvalidateVisual(); // 触发重绘
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 控件重绘事件
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// 当前选取的控件
|
||||
/// </summary>
|
||||
private readonly List<Control> selectNodeControls = [];
|
||||
private readonly List<NodeControlBase> selectNodeControls = [];
|
||||
|
||||
/// <summary>
|
||||
/// 记录开始拖动节点控件时的鼠标位置
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 控件的鼠标左键按下事件,启动拖动操作。
|
||||
/// 控件的鼠标右键按下事件,启动拖动操作。
|
||||
/// </summary>
|
||||
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; // 更新起始点位置
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/// <returns></returns>
|
||||
protected IBrush GetBackgrounp()
|
||||
{
|
||||
var myData = nodeOperationService.ConnectingData;
|
||||
var myData = nodeOperationService.ConnectingManage;
|
||||
if (IsPreviewing == false || !myData.IsCreateing )
|
||||
{
|
||||
return new SolidColorBrush(Color.Parse("#76ABEE"));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// 节点之间连接线的相关控制方法
|
||||
/// </summary>
|
||||
public class ConnectingData
|
||||
internal class ConnectingManage
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否正在创建连线
|
||||
/// </summary>
|
||||
public bool IsCreateing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 起始控制点
|
||||
/// </summary>
|
||||
@@ -29,14 +31,11 @@ namespace Serein.Workbench.Avalonia.Model
|
||||
/// 当前的控制点
|
||||
/// </summary>
|
||||
public NodeJunctionView? CurrentJunction { get; set; }
|
||||
/// <summary>
|
||||
/// 开始坐标
|
||||
/// </summary>
|
||||
public Point StartPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 线条样式
|
||||
/// </summary>
|
||||
public NodeConnectionLineView? TempLine { get; set; }
|
||||
public NodeConnectionLineControl? TempLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 线条类别(方法调用)
|
||||
@@ -51,7 +50,10 @@ namespace Serein.Workbench.Avalonia.Model
|
||||
/// 判断当前连接类型
|
||||
/// </summary>
|
||||
public JunctionOfConnectionType? Type => StartJunction?.JunctionType.ToConnectyionType();
|
||||
|
||||
|
||||
private readonly INodeOperationService nodeOperationService1;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否允许连接
|
||||
@@ -105,6 +107,10 @@ namespace Serein.Workbench.Avalonia.Model
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 重置
|
||||
/// </summary>
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 线条类别(方法调用)
|
||||
@@ -53,13 +54,37 @@ namespace Serein.Workbench.Avalonia.Custom.Views
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,35 +93,52 @@ namespace Serein.Workbench.Avalonia.Custom.Views
|
||||
/// <param name="endNodeJunctionView"></param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -104,7 +146,7 @@ namespace Serein.Workbench.Avalonia.Custom.Views
|
||||
/// </summary>
|
||||
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);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新临时线的显示
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新临时线的显示
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取背景颜色
|
||||
/// </summary>
|
||||
@@ -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
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Serein.Workbench.Avalonia.Api
|
||||
/// <summary>
|
||||
/// 连接数据
|
||||
/// </summary>
|
||||
ConnectingData ConnectingData { get; }
|
||||
ConnectingManage ConnectingManage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 主画布
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// 存储所有连接
|
||||
/// </summary>
|
||||
private List<NodeConnectionLineView> Connections { get; } = [];
|
||||
private List<NodeConnectionLineControl> Connections { get; } = [];
|
||||
|
||||
|
||||
|
||||
@@ -227,7 +224,6 @@ namespace Serein.Workbench.Avalonia.Services
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,7 +41,8 @@ namespace Serein.Workbench
|
||||
}
|
||||
else
|
||||
{
|
||||
FlowEnvironment = new FlowEnvironmentDecorator(uIContextOperation);
|
||||
FlowEnvironment = new FlowEnvironmentDecorator();
|
||||
FlowEnvironment.SetUIContextOperation(uIContextOperation);
|
||||
//_ = FlowEnvironment.StartRemoteServerAsync();
|
||||
this.window = window;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<ProjectReference Include="..\Library.Core\Serein.Library.Core.csproj" />
|
||||
<ProjectReference Include="..\Library.Framework\Serein.Library.Framework.csproj" />
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj" />
|
||||
<ProjectReference Include="..\NodeFlow\Serein.NodeFlow.csproj" />
|
||||
<ProjectReference Include="..\Serein.Script\Serein.Script.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user