mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
修复了Serein.Script调用对象方法时无法匹配重载方法
This commit is contained in:
@@ -200,16 +200,16 @@ namespace Serein.NodeFlow.Model
|
|||||||
var dataType = data is null ? typeof(object) : data.GetType();
|
var dataType = data is null ? typeof(object) : data.GetType();
|
||||||
if (expression[0..4].Equals("@get", StringComparison.CurrentCultureIgnoreCase))
|
if (expression[0..4].Equals("@get", StringComparison.CurrentCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
expression = expression[4..];
|
getValueExpression = expression[4..];
|
||||||
// 表达式默认包含 “.”
|
// 表达式默认包含 “.”
|
||||||
expression = $"return {dataName}{expression};";
|
getValueExpression = $"return {dataName}{expression};";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 表达式默认包含 “.”
|
// 表达式默认包含 “.”
|
||||||
expression = $"return {expression};";
|
getValueExpression = $"return {getValueExpression};";
|
||||||
}
|
}
|
||||||
var resultType = getValueScript.ParserScript(expression, new Dictionary<string, Type>
|
var resultType = getValueScript.ParserScript(getValueExpression, new Dictionary<string, Type>
|
||||||
{
|
{
|
||||||
{ dataName, dataType},
|
{ dataName, dataType},
|
||||||
});
|
});
|
||||||
@@ -239,18 +239,18 @@ namespace Serein.NodeFlow.Model
|
|||||||
conditionExpression = expression;
|
conditionExpression = expression;
|
||||||
conditionScript = new SereinScript();
|
conditionScript = new SereinScript();
|
||||||
var dataType = data is null ? typeof(object) : data.GetType();
|
var dataType = data is null ? typeof(object) : data.GetType();
|
||||||
expression = expression.Trim();
|
conditionExpression = expression.Trim();
|
||||||
if (expression[0] == '.')
|
if (expression[0] == '.')
|
||||||
{
|
{
|
||||||
// 对象取值
|
// 对象取值
|
||||||
expression = $"return {dataName}{expression};";
|
conditionExpression = $"return {dataName}{expression};";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 直接表达式
|
// 直接表达式
|
||||||
expression = $"return {dataName}{expression};";
|
conditionExpression = $"return {dataName}.{expression};";
|
||||||
}
|
}
|
||||||
_ = conditionScript.ParserScript(expression, new Dictionary<string, Type>
|
var resultType = conditionScript.ParserScript(conditionExpression, new Dictionary<string, Type>
|
||||||
{
|
{
|
||||||
{ dataName, dataType},
|
{ dataName, dataType},
|
||||||
});
|
});
|
||||||
|
|||||||
55
README.md
55
README.md
@@ -134,6 +134,61 @@ https://space.bilibili.com/33526379
|
|||||||
* 参数描述:Type,触发状态描述(External外部触发,Overtime超时触发),当你在代码中的其他地方主动触发了触发器,则该次触发类型为External,当你在创建触发器后超过了指定时间(创建触发器时会要求声明超时时间),则会自动触发,但触发类型为Overtime,触发参数未你在创建触发器时指定的值)
|
* 参数描述:Type,触发状态描述(External外部触发,Overtime超时触发),当你在代码中的其他地方主动触发了触发器,则该次触发类型为External,当你在创建触发器后超过了指定时间(创建触发器时会要求声明超时时间),则会自动触发,但触发类型为Overtime,触发参数未你在创建触发器时指定的值)
|
||||||
* 参数描述:Value,触发时传递的参数。
|
* 参数描述:Value,触发时传递的参数。
|
||||||
* 使用场景:配合 FlowTrigger`<TEnum>` 使用,例如定时从PLC中获取状态,当某个变量发生改变时,会通知相应的触发器,如果需要,可以传递对应的数据。
|
* 使用场景:配合 FlowTrigger`<TEnum>` 使用,例如定时从PLC中获取状态,当某个变量发生改变时,会通知相应的触发器,如果需要,可以传递对应的数据。
|
||||||
|
|
||||||
|
* * **ExpOp- 表达式节点**
|
||||||
|
* 入参: 自定义的表达式。
|
||||||
|
* 取值表达式:@Get
|
||||||
|
* 描述:有时节点返回了object,但下一个节点只需要对象中某个属性,而非整个对象。如果修改节点的定义,有可能破坏了代码的封装,为了解决这个痛点,于是增加了表达式节点。
|
||||||
|
* 使用方法:
|
||||||
|
1. 获取对象的属性成员:
|
||||||
|
~~~~
|
||||||
|
@Get .[property]/[field]
|
||||||
|
~~~~
|
||||||
|
2. 获取对象的数组成员中下标为22的项:
|
||||||
|
~~~~
|
||||||
|
@Get .array[22]
|
||||||
|
~~~~
|
||||||
|
3. 获取对象的字典成员中键为“zhangsan”的值:
|
||||||
|
~~~
|
||||||
|
@Get .dict["zhangsan"]
|
||||||
|
~~~
|
||||||
|
* **ExpCondition - 条件表达式节点**
|
||||||
|
* 入参: 自定义。
|
||||||
|
* 描述:与表达式节点不同,条件表达式节点是判断条件是否成立,如果成立,返回true,否则返回false,如果表达式执行失败,而进入 error 分支。
|
||||||
|
* 使用方式:
|
||||||
|
* 入参说明:默认从上一节点获取,也可以显式设定值,也可以参考表达式节点,使用“@Get .[property]/[field]”的方式重新定义入参数据,用以条件表达式判断。
|
||||||
|
* 条件表达式:默认“PASS”,代表跳过判断直接进入下一个分支。
|
||||||
|
* 条件表达式格式“.[property]/[field]< type> [op] value”,注意,开头必须使用“.”符号,这有助于显然的表达需要从入参对象中取内部某个值。
|
||||||
|
* 表达式符号说明:
|
||||||
|
* [property] /[field] : 属性/字段
|
||||||
|
* [op] : 操作符
|
||||||
|
1. bool表达式:==
|
||||||
|
2. 数值表达式 :==、>=、 <=、in a-b (表示判断是否在a至b的数值范围内), !in a-b(取反);
|
||||||
|
3. 文本表达式:==/equals(等于)、!=/notequals(不等于)、c/contains(出现过)、nc/doesnotcontain(没有出现过)、sw/startswith(开头等于)、ew/endswith(结尾等于)
|
||||||
|
* < type> :指定需要转换为某个类型,可不选。
|
||||||
|
* [value] : 条件值
|
||||||
|
* 使用示例:
|
||||||
|
~~~
|
||||||
|
场景1:上一个节点传入了该对象(伪代码):
|
||||||
|
class Data
|
||||||
|
{
|
||||||
|
string Name; // 性能
|
||||||
|
string Age; // 年龄,外部传入了文本类型
|
||||||
|
string IdentityCardNumber; // 身份证号
|
||||||
|
|
||||||
|
}
|
||||||
|
需求:需要判断年龄是否在某个区间,例如需要大于18岁,小于35岁。
|
||||||
|
条件表达式:.Age<int> in 18-35
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
需求:需要判断是否是北京身份证(开头为”1100”)。
|
||||||
|
条件表达式:.IdentityCardNumber sw 1100
|
||||||
|
另一种方法:
|
||||||
|
入参使用表达式:@Get .IdentityCardNumber
|
||||||
|
条件表达式:sw 1100
|
||||||
|
|
||||||
|
~~~
|
||||||
* **UI - 自定义控件**
|
* **UI - 自定义控件**
|
||||||
* 入参:默认使用上一节点返回值。
|
* 入参:默认使用上一节点返回值。
|
||||||
* 返回值:IEmbeddedContent 接口
|
* 返回值:IEmbeddedContent 接口
|
||||||
|
|||||||
@@ -261,7 +261,12 @@ namespace Serein.Script
|
|||||||
if (!ASTDelegateDetails.TryGetValue(memberFunctionCallNode, out DelegateDetails? delegateDetails))
|
if (!ASTDelegateDetails.TryGetValue(memberFunctionCallNode, out DelegateDetails? delegateDetails))
|
||||||
{
|
{
|
||||||
var methodName = memberFunctionCallNode.FunctionName;
|
var methodName = memberFunctionCallNode.FunctionName;
|
||||||
var methodInfo = memberFunctionCallNode.Arguments.Count == 0 ? target?.GetType().GetMethod(methodName, []) : target?.GetType().GetMethod(methodName);// 获取参数列表的类型
|
var argTypes = (memberFunctionCallNode.Arguments.Count == 0) switch
|
||||||
|
{
|
||||||
|
true => [],
|
||||||
|
false => memberFunctionCallNode.Arguments.Select(arg => symbolInfos[arg]).ToArray()
|
||||||
|
};
|
||||||
|
var methodInfo = target?.GetType().GetMethod(methodName, argTypes); // 获取参数列表的类型
|
||||||
if (methodInfo is null) throw new SereinSciptParserException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
|
if (methodInfo is null) throw new SereinSciptParserException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
|
||||||
delegateDetails = new DelegateDetails(methodInfo);
|
delegateDetails = new DelegateDetails(methodInfo);
|
||||||
ASTDelegateDetails[memberFunctionCallNode] = delegateDetails;
|
ASTDelegateDetails[memberFunctionCallNode] = delegateDetails;
|
||||||
@@ -468,52 +473,6 @@ namespace Serein.Script
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if false
|
|
||||||
|
|
||||||
// 解析数组/集合名与索引部分
|
|
||||||
var targetType = collectionValue.GetType(); // 目标对象的类型
|
|
||||||
#region 处理键值对
|
|
||||||
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
|
||||||
{
|
|
||||||
// 目标是键值对
|
|
||||||
var methodInfo = targetType.GetMethod("set_Item", BindingFlags.Public | BindingFlags.Instance);
|
|
||||||
if (methodInfo is not null)
|
|
||||||
{
|
|
||||||
|
|
||||||
methodInfo.Invoke(collectionValue, [indexValue, valueValue]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#region 处理集合对象
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (indexValue is int index)
|
|
||||||
{
|
|
||||||
// 获取数组或集合对象
|
|
||||||
// 访问数组或集合中的指定索引
|
|
||||||
if (collectionValue is Array array)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= array.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
|
|
||||||
}
|
|
||||||
array.SetValue(valueValue, index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (collectionValue is IList<object> list)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= list.Count)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
|
|
||||||
}
|
|
||||||
list[index] = valueValue;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
throw new ArgumentException($"解析异常, {collectionValue} 并非有效集合。");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -545,51 +504,6 @@ namespace Serein.Script
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if false
|
|
||||||
// 解析数组/集合名与索引部分
|
|
||||||
var targetType = collectionValue.GetType(); // 目标对象的类型
|
|
||||||
#region 处理键值对
|
|
||||||
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
|
|
||||||
{
|
|
||||||
// 目标是键值对
|
|
||||||
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
|
|
||||||
if (method is not null)
|
|
||||||
{
|
|
||||||
var value = method.Invoke(collectionValue, [indexValue]);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#region 处理集合对象
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (indexValue is int index)
|
|
||||||
{
|
|
||||||
// 获取数组或集合对象
|
|
||||||
// 访问数组或集合中的指定索引
|
|
||||||
if (collectionValue is Array array)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= array.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.GetValue(index);
|
|
||||||
}
|
|
||||||
else if (collectionValue is IList<object> list)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= list.Count)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
|
|
||||||
}
|
|
||||||
return list[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
throw new ArgumentException($"解析{collectionValue}节点时,左值并非有效集合。");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user