mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-05-04 14:21:32 +08:00
重新设计了@get 表达式,修改了 Workbench后台长时间运行时,重新切换到前台会产生参数连接线错误显示的问题
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using Serein.Library.Utils;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.SqlTypes;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -11,6 +13,109 @@ namespace Serein.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static partial class SereinExtension
|
public static partial class SereinExtension
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 字面量转为对应类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="valueStr"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Type ToTypeOfString(this string valueStr)
|
||||||
|
{
|
||||||
|
if (valueStr.IndexOf('.') != -1)
|
||||||
|
{
|
||||||
|
// 通过指定的类型名称获取类型
|
||||||
|
return Type.GetType(valueStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (valueStr.Equals("bool", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(bool);
|
||||||
|
}
|
||||||
|
#region 整数型
|
||||||
|
else if (valueStr.Equals("sbyte", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(SByte), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(SByte);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("short", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Int16), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Int16);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("int", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Int32), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Int32);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("long", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Int64), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Int64);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (valueStr.Equals("byte", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Byte), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Byte);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("ushort", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(UInt16), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(UInt16);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("uint", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(UInt32), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(UInt32);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("ulong", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(UInt64), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(UInt64);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 浮点型
|
||||||
|
else if (valueStr.Equals("float", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Single), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Single);
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("double", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Double), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Double);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 小数型
|
||||||
|
|
||||||
|
else if (valueStr.Equals("decimal", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| valueStr.Equals(nameof(Decimal), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(Decimal);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 其他常见的类型
|
||||||
|
else if (valueStr.Equals(nameof(DateTime), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(DateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (valueStr.Equals(nameof(String), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return typeof(String);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"无法解析的字面量类型[{valueStr}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 判断连接类型
|
/// 判断连接类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -357,6 +357,10 @@ namespace Serein.Library
|
|||||||
/// <returns>节点传回数据对象</returns>
|
/// <returns>节点传回数据对象</returns>
|
||||||
public virtual async Task<object> ExecutingAsync(IDynamicContext context)
|
public virtual async Task<object> ExecutingAsync(IDynamicContext context)
|
||||||
{
|
{
|
||||||
|
if(context.NextOrientation == ConnectionInvokeType.IsError)
|
||||||
|
{
|
||||||
|
Console.WriteLine("");
|
||||||
|
}
|
||||||
#region 调试中断
|
#region 调试中断
|
||||||
|
|
||||||
if (DebugSetting.IsInterrupt) // 执行触发检查是否需要中断
|
if (DebugSetting.IsInterrupt) // 执行触发检查是否需要中断
|
||||||
@@ -468,7 +472,6 @@ namespace Serein.Library
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
inputParameter = context.GetFlowData(previousNode.Guid); // 当前传递的数据
|
inputParameter = context.GetFlowData(previousNode.Guid); // 当前传递的数据
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -485,8 +488,17 @@ namespace Serein.Library
|
|||||||
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
else if (pd.ArgDataSourceType == ConnectionArgSourceType.GetOtherNodeDataOfInvoke)
|
||||||
{
|
{
|
||||||
// 立刻调用对应节点获取数据。
|
// 立刻调用对应节点获取数据。
|
||||||
var result = await context.Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid);
|
try
|
||||||
inputParameter = result;
|
{
|
||||||
|
var result = await context.Env.InvokeNodeAsync(context, pd.ArgDataSourceNodeGuid);
|
||||||
|
inputParameter = result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
context.NextOrientation = ConnectionInvokeType.IsError;
|
||||||
|
context.ExceptionOfRuning = ex;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region 意料之外的参数
|
#region 意料之外的参数
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ namespace Serein.Library
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NodeAction(NodeType.Action, "逻辑分支")]
|
||||||
|
private object SereinLogicalBranch(bool @bool, object t_value,object f_value)
|
||||||
|
{
|
||||||
|
return @bool ? t_value : f_value;
|
||||||
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "文本拼接")]
|
[NodeAction(NodeType.Action, "文本拼接")]
|
||||||
private string SereinTextJoin(params object[] value)
|
private string SereinTextJoin(params object[] value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ namespace Serein.Library.Utils
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ConvertHelper
|
public static class ConvertHelper
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static TResult ToConvert<TResult>(this object data)
|
public static TResult ToConvert<TResult>(this object data)
|
||||||
{
|
{
|
||||||
var type = typeof(TResult);
|
var type = typeof(TResult);
|
||||||
@@ -203,6 +206,14 @@ namespace Serein.Library.Utils
|
|||||||
#endif
|
#endif
|
||||||
else if(type == typeof(DateTime))
|
else if(type == typeof(DateTime))
|
||||||
{
|
{
|
||||||
|
if (valueStr.Equals("now"))
|
||||||
|
{
|
||||||
|
return DateTime.Now;
|
||||||
|
}
|
||||||
|
else if (valueStr.Equals("utcnow"))
|
||||||
|
{
|
||||||
|
return DateTime.UtcNow;
|
||||||
|
}
|
||||||
return DateTime.Parse(valueStr);
|
return DateTime.Parse(valueStr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Serein.Library.Utils.SereinExpression.Resolver
|
|||||||
public override bool Evaluate(object obj)
|
public override bool Evaluate(object obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
return Value.Equals(Data);
|
return Value.Equals(obj);
|
||||||
//if (obj is bool boolObj && Value is bool boolValue)
|
//if (obj is bool boolObj && Value is bool boolValue)
|
||||||
//{
|
//{
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
|
|
||||||
public static SereinConditionResolver ConditionParse(object data, string expression)
|
public static SereinConditionResolver ConditionParse(object data, string expression)
|
||||||
{
|
{
|
||||||
if (expression.StartsWith(".")) // 表达式前缀属于从上一个节点数据对象获取成员值
|
if (expression[0] == '.') // 表达式前缀属于从上一个节点数据对象获取成员值
|
||||||
{
|
{
|
||||||
return ParseObjectExpression(data, expression);
|
return ParseObjectExpression(data, expression);
|
||||||
}
|
}
|
||||||
@@ -190,61 +190,7 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
operatorStr = parts[0].ToLower(); // 操作类型
|
operatorStr = parts[0].ToLower(); // 操作类型
|
||||||
valueStr = string.Join(" ", parts.Skip(1)); // 表达式值
|
valueStr = string.Join(" ", parts.Skip(1)); // 表达式值
|
||||||
}
|
}
|
||||||
Type tempType;
|
type = typeStr.ToTypeOfString();
|
||||||
|
|
||||||
switch (typeStr)
|
|
||||||
{
|
|
||||||
case "bool":
|
|
||||||
tempType = typeof(bool);
|
|
||||||
break;
|
|
||||||
case "float":
|
|
||||||
tempType = typeof(float);
|
|
||||||
break;
|
|
||||||
case "decimal":
|
|
||||||
tempType = typeof(decimal);
|
|
||||||
break;
|
|
||||||
case "double":
|
|
||||||
tempType = typeof(double);
|
|
||||||
break;
|
|
||||||
case "sbyte":
|
|
||||||
tempType = typeof(sbyte);
|
|
||||||
break;
|
|
||||||
case "byte":
|
|
||||||
tempType = typeof(byte);
|
|
||||||
break;
|
|
||||||
case "short":
|
|
||||||
tempType = typeof(short);
|
|
||||||
break;
|
|
||||||
case "ushort":
|
|
||||||
tempType = typeof(ushort);
|
|
||||||
break;
|
|
||||||
case "int":
|
|
||||||
tempType = typeof(int);
|
|
||||||
break;
|
|
||||||
case "uint":
|
|
||||||
tempType = typeof(uint);
|
|
||||||
break;
|
|
||||||
case "long":
|
|
||||||
tempType = typeof(long);
|
|
||||||
break;
|
|
||||||
case "ulong":
|
|
||||||
tempType = typeof(ulong);
|
|
||||||
break;
|
|
||||||
// 如果需要支持 nint 和 nuint
|
|
||||||
// case "nint":
|
|
||||||
// tempType = typeof(nint);
|
|
||||||
// break;
|
|
||||||
// case "nuint":
|
|
||||||
// tempType = typeof(nuint);
|
|
||||||
// break;
|
|
||||||
case "string":
|
|
||||||
tempType = typeof(string);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tempType = Type.GetType(typeStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
type = tempType ?? throw new ArgumentException("对象表达式无效的类型声明");
|
|
||||||
if (string.IsNullOrWhiteSpace(memberPath))
|
if (string.IsNullOrWhiteSpace(memberPath))
|
||||||
{
|
{
|
||||||
targetObj = Convert.ChangeType(data, type);
|
targetObj = Convert.ChangeType(data, type);
|
||||||
@@ -362,32 +308,6 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
/// <exception cref="NotSupportedException"></exception>
|
/// <exception cref="NotSupportedException"></exception>
|
||||||
private static SereinConditionResolver ParseSimpleExpression(object data, string expression)
|
private static SereinConditionResolver ParseSimpleExpression(object data, string expression)
|
||||||
{
|
{
|
||||||
if ("pass".Equals(expression.ToLower()))
|
|
||||||
{
|
|
||||||
return new PassConditionResolver
|
|
||||||
{
|
|
||||||
Op = PassConditionResolver.Operator.Pass,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ("not pass".Equals(expression.ToLower()))
|
|
||||||
{
|
|
||||||
return new PassConditionResolver
|
|
||||||
{
|
|
||||||
Op = PassConditionResolver.Operator.NotPass,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if ("!pass".Equals(expression.ToLower()))
|
|
||||||
{
|
|
||||||
return new PassConditionResolver
|
|
||||||
{
|
|
||||||
Op = PassConditionResolver.Operator.NotPass,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var parts = expression.Split(' ');
|
var parts = expression.Split(' ');
|
||||||
|
|
||||||
if (parts.Length < 2)
|
if (parts.Length < 2)
|
||||||
@@ -395,11 +315,11 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
|
|
||||||
string operatorStr;
|
string operatorStr;
|
||||||
string valueStr;
|
string valueStr;
|
||||||
Type type = null;
|
|
||||||
// 尝试获取指定类型
|
// 尝试获取指定类型
|
||||||
int typeStartIndex = expression.IndexOf('<');
|
|
||||||
int typeEndIndex = expression.IndexOf('>');
|
var hasType = SereinExpressionExtension.TryGetType(expression, out _, out var type);
|
||||||
if (typeStartIndex + typeStartIndex == -2)
|
|
||||||
|
if (!hasType)
|
||||||
{
|
{
|
||||||
// 如果不需要转为指定类型
|
// 如果不需要转为指定类型
|
||||||
operatorStr = parts[0];
|
operatorStr = parts[0];
|
||||||
@@ -410,72 +330,16 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
|
|
||||||
valueStr = StringHelper.JoinStrings(parts, 1, parts.Length - 1, ' ');
|
valueStr = StringHelper.JoinStrings(parts, 1, parts.Length - 1, ' ');
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
type = data.GetType();
|
type = data.GetType();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{//string typeStr = parts[0];
|
{//string typeStr = parts[0];
|
||||||
string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1)
|
|
||||||
.Trim().ToLower(); // 手动置顶的类型
|
int endIndex = expression.IndexOf('>');
|
||||||
parts = expression.Substring(typeEndIndex + 1).Trim().Split(' ');
|
parts = expression.Substring(endIndex + 1).Split(' ');
|
||||||
operatorStr = parts[0].ToLower(); // 操作类型
|
operatorStr = parts[0].ToLower(); // 操作类型
|
||||||
valueStr = string.Join(" ", parts.Skip(1)); // 表达式值
|
valueStr = string.Join(" ", parts.Skip(1)); // 表达式值
|
||||||
|
|
||||||
|
|
||||||
Type tempType;
|
|
||||||
|
|
||||||
switch (typeStr)
|
|
||||||
{
|
|
||||||
case "bool":
|
|
||||||
tempType = typeof(bool);
|
|
||||||
break;
|
|
||||||
case "float":
|
|
||||||
tempType = typeof(float);
|
|
||||||
break;
|
|
||||||
case "decimal":
|
|
||||||
tempType = typeof(decimal);
|
|
||||||
break;
|
|
||||||
case "double":
|
|
||||||
tempType = typeof(double);
|
|
||||||
break;
|
|
||||||
case "sbyte":
|
|
||||||
tempType = typeof(sbyte);
|
|
||||||
break;
|
|
||||||
case "byte":
|
|
||||||
tempType = typeof(byte);
|
|
||||||
break;
|
|
||||||
case "short":
|
|
||||||
tempType = typeof(short);
|
|
||||||
break;
|
|
||||||
case "ushort":
|
|
||||||
tempType = typeof(ushort);
|
|
||||||
break;
|
|
||||||
case "int":
|
|
||||||
tempType = typeof(int);
|
|
||||||
break;
|
|
||||||
case "uint":
|
|
||||||
tempType = typeof(uint);
|
|
||||||
break;
|
|
||||||
case "long":
|
|
||||||
tempType = typeof(long);
|
|
||||||
break;
|
|
||||||
case "ulong":
|
|
||||||
tempType = typeof(ulong);
|
|
||||||
break;
|
|
||||||
// 如果需要支持 nint 和 nuint
|
|
||||||
// case "nint":
|
|
||||||
// tempType = typeof(nint);
|
|
||||||
// break;
|
|
||||||
// case "nuint":
|
|
||||||
// tempType = typeof(nuint);
|
|
||||||
// break;
|
|
||||||
case "string":
|
|
||||||
tempType = typeof(string);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tempType = Type.GetType(typeStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
Library/Utils/SereinExpression/SereinExpressionExtension.cs
Normal file
57
Library/Utils/SereinExpression/SereinExpressionExtension.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Serein.Library.Utils.SereinExpression
|
||||||
|
{
|
||||||
|
internal class SereinExpressionExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 尝试获取类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <param name="elementName"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryGetType(string context, out string elementName , out Type type)
|
||||||
|
{
|
||||||
|
int startIndex = context.IndexOf('<');
|
||||||
|
int endIndex = context.IndexOf('>');
|
||||||
|
if (startIndex < 0 || endIndex < 0 || startIndex > endIndex)
|
||||||
|
{
|
||||||
|
type = null;
|
||||||
|
elementName = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
elementName = context.Substring(0,startIndex);
|
||||||
|
type = context.Substring(startIndex + 1, endIndex - startIndex - 1).ToTypeOfString();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 尝试获取下标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context"></param>
|
||||||
|
/// <param name="strIndexKey">文本形式的key/索引</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryGetIndex(string context,out string elementName, out string strIndexKey)
|
||||||
|
{
|
||||||
|
int startIndex = context.IndexOf('[');
|
||||||
|
int endIndex = context.IndexOf(']');
|
||||||
|
if (startIndex < 0 || endIndex < 0 || startIndex > endIndex)
|
||||||
|
{
|
||||||
|
strIndexKey = null;
|
||||||
|
elementName = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
elementName = context.Substring(0,startIndex);
|
||||||
|
strIndexKey = context.Substring(startIndex + 1, endIndex - startIndex - 1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ using System.Data;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -63,38 +64,48 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
throw new ArgumentException("Invalid expression format.");
|
throw new ArgumentException("Invalid expression format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var operation = parts[0].ToLower();
|
var operation = parts[0];
|
||||||
var operand = parts[1][0] == '.' ? parts[1].Substring(1) : parts[1];
|
var operand = parts[1][0] == '.' ? parts[1].Substring(1) : parts[1];
|
||||||
object result;
|
object result;
|
||||||
isChange = false;
|
isChange = false;
|
||||||
|
|
||||||
//if (operation == "@num")
|
//if (operation == "@num")
|
||||||
//{
|
//{
|
||||||
// result = ComputedNumber(targetObJ, operand);
|
// result = ComputedNumber(targetObJ, operand);
|
||||||
//}
|
//}
|
||||||
if (operation == "@call")
|
|
||||||
{
|
if (operation.Equals("@get",StringComparison.OrdinalIgnoreCase))
|
||||||
result = InvokeMethod(targetObJ, operand);
|
|
||||||
}
|
|
||||||
else if (operation == "@get")
|
|
||||||
{
|
{
|
||||||
isChange = true;
|
isChange = true;
|
||||||
|
if (operand[0].Equals('#'))
|
||||||
|
{
|
||||||
|
// 存在全局变量表达式
|
||||||
|
var strIndex = operand.IndexOf('#',1);
|
||||||
|
var globalDataKeyName = operand.Substring(1, strIndex - 1);
|
||||||
|
targetObJ = SereinEnv.GetFlowGlobalData(globalDataKeyName);
|
||||||
|
if(strIndex == operand.Length - 1)
|
||||||
|
{
|
||||||
|
return targetObJ;
|
||||||
|
}
|
||||||
|
operand = operand.Substring(strIndex+1);
|
||||||
|
}
|
||||||
|
|
||||||
result = GetMember(targetObJ, operand);
|
result = GetMember(targetObJ, operand);
|
||||||
}
|
}
|
||||||
else if (operation == "@set")
|
else if (operation.Equals("@dtc", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
|
||||||
isChange = true;
|
|
||||||
result = SetMember(targetObJ, operand);
|
|
||||||
}
|
|
||||||
else if (operation == "@dtc")
|
|
||||||
{
|
{
|
||||||
isChange = true;
|
isChange = true;
|
||||||
result = DataTypeConversion(targetObJ, operand);
|
result = DataTypeConversion(targetObJ, operand);
|
||||||
}
|
}
|
||||||
else if (operation == "@data")
|
else if (operation.Equals("@call", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
isChange = true;
|
result = InvokeMethod(targetObJ, operand);
|
||||||
result = GetGlobleData(targetObJ, operand);
|
|
||||||
}
|
}
|
||||||
|
//else if (operation.Equals("@set",StringComparison.OrdinalIgnoreCase))
|
||||||
|
//{
|
||||||
|
// isChange = true;
|
||||||
|
// result = SetMember(targetObJ, operand);
|
||||||
|
//}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"Operation {operation} is not supported.");
|
throw new NotSupportedException($"Operation {operation} is not supported.");
|
||||||
@@ -151,59 +162,49 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
private static object GetMember(object target, string memberPath)
|
private static object GetMember(object target, string memberPath)
|
||||||
{
|
{
|
||||||
if (target is null) return null;
|
if (target is null) return null;
|
||||||
|
|
||||||
|
|
||||||
// 分割成员路径,按 '.' 处理多级访问
|
// 分割成员路径,按 '.' 处理多级访问
|
||||||
var members = memberPath.Split('.');
|
var members = memberPath.Split('.');
|
||||||
|
|
||||||
foreach (var member in members)
|
foreach (var member in members)
|
||||||
{
|
{
|
||||||
|
var hasType = SereinExpressionExtension.TryGetType(member, out var memberName, out var type);
|
||||||
|
|
||||||
|
// 检查成员是否包含数组索引,例如 "array[0]" "dict[key]"
|
||||||
|
var hasIndex = SereinExpressionExtension.TryGetIndex(member, out var elementName, out var strIndexKey);
|
||||||
|
|
||||||
// 检查成员是否包含数组索引,例如 "cars[0]"
|
// 检查成员是否包含数组索引,例如 "cars[0]"
|
||||||
var arrayIndexStart = member.IndexOf('[');
|
if (hasIndex)
|
||||||
if (arrayIndexStart != -1)
|
|
||||||
{
|
{
|
||||||
// 解析数组/集合名与索引部分
|
// 解析数组/集合名与索引部分
|
||||||
var arrayName = member.Substring(0, arrayIndexStart);
|
|
||||||
var arrayIndexEnd = member.IndexOf(']');
|
|
||||||
if (arrayIndexEnd == -1 || arrayIndexEnd <= arrayIndexStart + 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid array syntax for member {member}");
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetType = target?.GetType(); // 目标对象的类型
|
var targetType = target?.GetType(); // 目标对象的类型
|
||||||
#region 处理键值对
|
#region 处理键值对
|
||||||
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
||||||
{
|
{
|
||||||
|
|
||||||
var typetmp = target.GetType().FullName;
|
|
||||||
// 目标是键值对
|
// 目标是键值对
|
||||||
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
|
|
||||||
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
|
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
|
||||||
if (method != null)
|
if (method != null)
|
||||||
{
|
{
|
||||||
var result = method.Invoke(target, new object[] { indexStr });
|
target = method.Invoke(target, new object[] { strIndexKey });
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
target = result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
#region 表达式处理集合对象
|
#region 表达式处理集合对象
|
||||||
// 获取数组或集合对象
|
// 获取数组或集合对象
|
||||||
|
|
||||||
// 如果arrayName为空,说明target可能是数组,而不需要再获取属性了
|
// 如果arrayName为空,说明target可能是数组,而不需要再获取属性了
|
||||||
if (!string.IsNullOrEmpty(arrayName))
|
if (!string.IsNullOrEmpty(elementName))
|
||||||
{
|
{
|
||||||
var arrayProperty = target?.GetType().GetProperty(arrayName);
|
var arrayProperty = target?.GetType().GetProperty(elementName);
|
||||||
if (arrayProperty is null)
|
if (arrayProperty is null)
|
||||||
{
|
{
|
||||||
var arrayField = target?.GetType().GetField(arrayName);
|
var arrayField = target?.GetType().GetField(elementName);
|
||||||
if (arrayField is null)
|
if (arrayField is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Member {arrayName} not found on target.");
|
throw new ArgumentException($"Member {elementName} not found on target.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -217,17 +218,16 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 提取数组索引
|
// 提取数组索引
|
||||||
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
|
if (!int.TryParse(strIndexKey, out int index))
|
||||||
if (!int.TryParse(indexStr, out int index))
|
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Invalid array index '{indexStr}' for member {member}");
|
throw new ArgumentException($"Invalid array index '{strIndexKey}' for member {member}");
|
||||||
}
|
}
|
||||||
// 访问数组或集合中的指定索引
|
// 访问数组或集合中的指定索引
|
||||||
if (target is Array array)
|
if (target is Array array)
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= array.Length)
|
if (index < 0 || index >= array.Length)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Index {index} out of bounds for array {arrayName}");
|
throw new ArgumentException($"Index {index} out of bounds for array {elementName}");
|
||||||
}
|
}
|
||||||
target = array.GetValue(index);
|
target = array.GetValue(index);
|
||||||
}
|
}
|
||||||
@@ -235,22 +235,22 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
{
|
{
|
||||||
if (index < 0 || index >= list.Count)
|
if (index < 0 || index >= list.Count)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Index {index} out of bounds for list {arrayName}");
|
throw new ArgumentException($"Index {index} out of bounds for list {elementName}");
|
||||||
}
|
}
|
||||||
target = list[index];
|
target = list[index];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Member {arrayName} is not an array or list.");
|
throw new ArgumentException($"Member {elementName} is not an array or list.");
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 处理非数组情况的属性或字段
|
// 处理非数组情况的属性或字段
|
||||||
var property = target?.GetType().GetProperty(member);
|
|
||||||
|
var property = target?.GetType().GetProperty(hasType ? memberName : member);
|
||||||
if (property is null)
|
if (property is null)
|
||||||
{
|
{
|
||||||
var field = target?.GetType().GetField(member);
|
var field = target?.GetType().GetField(member);
|
||||||
@@ -268,6 +268,13 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
target = property.GetValue(target);
|
target = property.GetValue(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasType)
|
||||||
|
{
|
||||||
|
target = target.ToConvert(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
@@ -404,6 +411,37 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据类型转换
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="expression"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static object DataTypeConversion(object value, string expression)
|
||||||
|
{
|
||||||
|
// 使用方法
|
||||||
|
// @dtc <int>value
|
||||||
|
// @dtc <int>flowObj
|
||||||
|
if(!SereinExpressionExtension.TryGetType(expression,out var elementName, out var type))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"无法获取类型:{expression}");
|
||||||
|
}
|
||||||
|
|
||||||
|
int endIndex = expression.IndexOf('>');
|
||||||
|
if(endIndex == expression.Length -1)
|
||||||
|
{
|
||||||
|
return value.ToConvert(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string valueStr = expression.Substring(endIndex + 1, expression.Length - endIndex - 1);
|
||||||
|
return valueStr.ToValueData(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算数学简单表达式
|
/// 计算数学简单表达式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -414,108 +452,22 @@ namespace Serein.Library.Utils.SereinExpression
|
|||||||
{
|
{
|
||||||
return ComputedNumber<decimal>(value, expression);
|
return ComputedNumber<decimal>(value, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算数学公式
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="expression"></param>
|
||||||
|
/// <returns></returns>
|
||||||
private static T ComputedNumber<T>(object value, string expression) where T : struct, IComparable<T>
|
private static T ComputedNumber<T>(object value, string expression) where T : struct, IComparable<T>
|
||||||
{
|
{
|
||||||
T result = value.ToConvert<T>();
|
T result = value.ToConvert<T>();
|
||||||
return SerinArithmeticExpressionEvaluator<T>.Evaluate(expression, result);
|
return SerinArithmeticExpressionEvaluator<T>.Evaluate(expression, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 数据类型转换
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="expression"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static object DataTypeConversion(object value, string expression)
|
|
||||||
{
|
|
||||||
Type tempType;
|
|
||||||
|
|
||||||
int typeStartIndex = expression.IndexOf('<');
|
|
||||||
int typeEndIndex = expression.IndexOf('>');
|
|
||||||
string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1)
|
|
||||||
.Trim().ToLower(); // 手动置顶的类型
|
|
||||||
string valueStr = expression.Substring(typeEndIndex + 1, expression.Length - typeEndIndex - 1);
|
|
||||||
switch (typeStr)
|
|
||||||
{
|
|
||||||
case "bool":
|
|
||||||
tempType = typeof(bool);
|
|
||||||
break;
|
|
||||||
case "float":
|
|
||||||
tempType = typeof(float);
|
|
||||||
break;
|
|
||||||
case "decimal":
|
|
||||||
tempType = typeof(decimal);
|
|
||||||
break;
|
|
||||||
case "double":
|
|
||||||
tempType = typeof(double);
|
|
||||||
break;
|
|
||||||
case "sbyte":
|
|
||||||
tempType = typeof(sbyte);
|
|
||||||
break;
|
|
||||||
case "byte":
|
|
||||||
tempType = typeof(byte);
|
|
||||||
break;
|
|
||||||
case "short":
|
|
||||||
tempType = typeof(short);
|
|
||||||
break;
|
|
||||||
case "ushort":
|
|
||||||
tempType = typeof(ushort);
|
|
||||||
break;
|
|
||||||
case "int":
|
|
||||||
tempType = typeof(int);
|
|
||||||
break;
|
|
||||||
case "uint":
|
|
||||||
tempType = typeof(uint);
|
|
||||||
break;
|
|
||||||
case "long":
|
|
||||||
tempType = typeof(long);
|
|
||||||
break;
|
|
||||||
case "ulong":
|
|
||||||
tempType = typeof(ulong);
|
|
||||||
break;
|
|
||||||
// 如果需要支持 nint 和 nuint
|
|
||||||
// case "nint":
|
|
||||||
// tempType = typeof(nint);
|
|
||||||
// break;
|
|
||||||
// case "nuint":
|
|
||||||
// tempType = typeof(nuint);
|
|
||||||
// break;
|
|
||||||
case "string":
|
|
||||||
tempType = typeof(string);
|
|
||||||
break;
|
|
||||||
case "datetime":
|
|
||||||
if(valueStr.Equals("now", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return DateTime.Now;
|
|
||||||
}
|
|
||||||
tempType = typeof(DateTime);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tempType = Type.GetType(typeStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempType.IsValueType)
|
|
||||||
{
|
|
||||||
return valueStr.ToValueData(tempType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取全局数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="expression"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private static object GetGlobleData(object value, string expression)
|
|
||||||
{
|
|
||||||
var keyName = expression;
|
|
||||||
return SereinEnv.GetFlowGlobalData(keyName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,6 +387,25 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
await nextNodes[i].StartFlowAsync(context); // 启动执行触发器后继分支的节点
|
await nextNodes[i].StartFlowAsync(context); // 启动执行触发器后继分支的节点
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nextNodes = singleFlipFlopNode.SuccessorNodes[ConnectionInvokeType.Upstream];
|
||||||
|
for (int i = nextNodes.Count - 1; i >= 0 && !_flipFlopCts.IsCancellationRequested; i--)
|
||||||
|
{
|
||||||
|
// 筛选出启用的节点
|
||||||
|
if (!nextNodes[i].DebugSetting.IsEnable)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.SetPreviousNode(nextNodes[i], singleFlipFlopNode);
|
||||||
|
if (nextNodes[i].DebugSetting.IsInterrupt) // 执行触发前
|
||||||
|
{
|
||||||
|
var cancelType = await nextNodes[i].DebugSetting.GetInterruptTask();
|
||||||
|
await Console.Out.WriteLineAsync($"[{nextNodes[i].MethodDetails.MethodName}]中断已{cancelType},开始执行后继分支");
|
||||||
|
}
|
||||||
|
await nextNodes[i].StartFlowAsync(context); // 启动执行触发器后继分支的节点
|
||||||
|
}
|
||||||
|
|
||||||
context.Exit();
|
context.Exit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -146,10 +146,11 @@ namespace Serein.NodeFlow.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool judgmentResult = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var isPass = SereinConditionParser.To(parameter, Expression);
|
judgmentResult = SereinConditionParser.To(parameter, Expression);
|
||||||
context.NextOrientation = isPass ? ConnectionInvokeType.IsSucceed : ConnectionInvokeType.IsFail;
|
context.NextOrientation = judgmentResult ? ConnectionInvokeType.IsSucceed : ConnectionInvokeType.IsFail;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -158,7 +159,8 @@ namespace Serein.NodeFlow.Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
SereinEnv.WriteLine(InfoType.INFO, $"{result} {Expression} -> " + context.NextOrientation);
|
SereinEnv.WriteLine(InfoType.INFO, $"{result} {Expression} -> " + context.NextOrientation);
|
||||||
return result;
|
//return result;
|
||||||
|
return judgmentResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serein.Library;
|
using Serein.Library;
|
||||||
|
using Serein.Library.Utils;
|
||||||
|
using Serein.Library.Utils.SereinExpression;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
|
||||||
namespace Serein.Workbench
|
namespace Serein.Workbench
|
||||||
{
|
{
|
||||||
//public class A
|
#if DEBUG
|
||||||
//{
|
public class A
|
||||||
// public object Data { get; set; }
|
{
|
||||||
//}
|
public string Data { get; set; } = "1234";
|
||||||
|
public bool Data2 { get; set; }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26,10 +32,31 @@ namespace Serein.Workbench
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (1 == 1)
|
if (1 == 1)
|
||||||
{
|
{
|
||||||
//var A = new A();
|
//object Data = "false";
|
||||||
//A.Data = true;
|
//var expression = "== false";
|
||||||
//var expression = ".Data<bool> == True";
|
//var pass = Serein.Library.Utils.SereinExpression.SereinConditionParser.To(Data, expression);
|
||||||
//var pass = Serein.Library.Utils.SereinExpression.SereinConditionParser.To(A, expression);
|
|
||||||
|
|
||||||
|
//string[] objects = new string[]
|
||||||
|
//{
|
||||||
|
// "124",
|
||||||
|
// "true",
|
||||||
|
// "0.42"
|
||||||
|
//};
|
||||||
|
//Dictionary<string, object> keyValuePairs = new Dictionary<string, object>
|
||||||
|
//{
|
||||||
|
// {"value", objects }
|
||||||
|
//};
|
||||||
|
|
||||||
|
|
||||||
|
//var data = SerinExpressionEvaluator.Evaluate("@Get .[value].[0]<int>", keyValuePairs, out _);
|
||||||
|
//data = SerinExpressionEvaluator.Evaluate("@Get .[value].[1]<bool>", keyValuePairs, out _);
|
||||||
|
//data = SerinExpressionEvaluator.Evaluate("@Dtc <bool>", data, out _);
|
||||||
|
//var result = SereinConditionParser.To(data, "== True");
|
||||||
|
|
||||||
|
|
||||||
|
//SereinEnv.AddOrUpdateFlowGlobalData("My", A);
|
||||||
|
//var data = SerinExpressionEvaluator.Evaluate("@Get #My#",null,out _);
|
||||||
|
|
||||||
|
|
||||||
// 这里是我自己的测试代码,你可以删除
|
// 这里是我自己的测试代码,你可以删除
|
||||||
|
|||||||
@@ -593,7 +593,8 @@ namespace Serein.Workbench
|
|||||||
eventArgs.ArgIndex,
|
eventArgs.ArgIndex,
|
||||||
eventArgs.ConnectionArgSourceType,
|
eventArgs.ConnectionArgSourceType,
|
||||||
startJunction,
|
startJunction,
|
||||||
endJunction
|
endJunction,
|
||||||
|
IToJunction
|
||||||
);
|
);
|
||||||
Connections.Add(connection);
|
Connections.Add(connection);
|
||||||
fromNodeControl.AddCnnection(connection);
|
fromNodeControl.AddCnnection(connection);
|
||||||
|
|||||||
@@ -30,5 +30,15 @@ namespace Serein.Workbench.Node
|
|||||||
/// 返回值控制点
|
/// 返回值控制点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
JunctionControlBase ReturnDataJunction { get; }
|
JunctionControlBase ReturnDataJunction { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取目标参数控制点,用于防止wpf释放资源导致找不到目标节点,返回-1,-1的坐标
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
JunctionControlBase GetJunctionOfArgData(int index)
|
||||||
|
{
|
||||||
|
return ArgDataJunction[index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ namespace Serein.Workbench.Node.View
|
|||||||
InitElementPoint(isDotted, isTop);
|
InitElementPoint(isDotted, isTop);
|
||||||
InvalidateVisual(); // 触发重绘
|
InvalidateVisual(); // 触发重绘
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void InitElementPoint(bool isDotted , bool isTop = false)
|
public void InitElementPoint(bool isDotted , bool isTop = false)
|
||||||
{
|
{
|
||||||
hitVisiblePen = new Pen(Brushes.Transparent, 1.0); // 初始化碰撞检测线
|
hitVisiblePen = new Pen(Brushes.Transparent, 1.0); // 初始化碰撞检测线
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ namespace Serein.Workbench.Node.View
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class ParamsArgControl: Shape
|
public class ParamsArgControl: Shape
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public ParamsArgControl()
|
public ParamsArgControl()
|
||||||
{
|
{
|
||||||
this.MouseDown += ParamsArg_OnMouseDown; // 增加或删除
|
this.MouseDown += ParamsArg_OnMouseDown; // 增加或删除
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ namespace Serein.Workbench.Node.View
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ConnectionInvokeType InvokeType { get; }
|
public ConnectionInvokeType InvokeType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标节点控制点
|
||||||
|
/// </summary>
|
||||||
|
private INodeJunction EndNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取参数类型,第几个参数
|
/// 获取参数类型,第几个参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -138,6 +143,8 @@ namespace Serein.Workbench.Node.View
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private ConnectionLineShape BezierLine;
|
private ConnectionLineShape BezierLine;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private LineType LineType;
|
private LineType LineType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -168,7 +175,8 @@ namespace Serein.Workbench.Node.View
|
|||||||
int argIndex,
|
int argIndex,
|
||||||
ConnectionArgSourceType argSourceType,
|
ConnectionArgSourceType argSourceType,
|
||||||
JunctionControlBase Start,
|
JunctionControlBase Start,
|
||||||
JunctionControlBase End)
|
JunctionControlBase End,
|
||||||
|
INodeJunction nodeJunction)
|
||||||
{
|
{
|
||||||
this.LineType = LineType;
|
this.LineType = LineType;
|
||||||
this.Canvas = Canvas;
|
this.Canvas = Canvas;
|
||||||
@@ -176,6 +184,7 @@ namespace Serein.Workbench.Node.View
|
|||||||
this.ArgSourceType = argSourceType;
|
this.ArgSourceType = argSourceType;
|
||||||
this.Start = Start;
|
this.Start = Start;
|
||||||
this.End = End;
|
this.End = End;
|
||||||
|
this.EndNode = nodeJunction;
|
||||||
InitElementPoint();
|
InitElementPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +251,10 @@ namespace Serein.Workbench.Node.View
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void RefreshLine()
|
public void RefreshLine()
|
||||||
{
|
{
|
||||||
|
if(ArgIndex > -1)
|
||||||
|
{
|
||||||
|
End = EndNode.GetJunctionOfArgData(ArgIndex);
|
||||||
|
}
|
||||||
(Point startPoint, Point endPoint) = RefreshPoint(Canvas, Start, End);
|
(Point startPoint, Point endPoint) = RefreshPoint(Canvas, Start, End);
|
||||||
BezierLine.UpdatePoints(startPoint, endPoint);
|
BezierLine.UpdatePoints(startPoint, endPoint);
|
||||||
}
|
}
|
||||||
@@ -255,7 +268,6 @@ namespace Serein.Workbench.Node.View
|
|||||||
|
|
||||||
private (Point startPoint, Point endPoint) RefreshPoint(Canvas canvas, FrameworkElement startElement, FrameworkElement endElement)
|
private (Point startPoint, Point endPoint) RefreshPoint(Canvas canvas, FrameworkElement startElement, FrameworkElement endElement)
|
||||||
{
|
{
|
||||||
|
|
||||||
var startPoint = startElement.TranslatePoint(rightCenterOfStartLocation, canvas); // 获取起始节点的中心位置
|
var startPoint = startElement.TranslatePoint(rightCenterOfStartLocation, canvas); // 获取起始节点的中心位置
|
||||||
var endPoint = endElement.TranslatePoint(leftCenterOfEndLocation, canvas); // 计算终点位置
|
var endPoint = endElement.TranslatePoint(leftCenterOfEndLocation, canvas); // 计算终点位置
|
||||||
return (startPoint, endPoint);
|
return (startPoint, endPoint);
|
||||||
|
|||||||
Reference in New Issue
Block a user