修复了Serein.Script调用对象方法时无法匹配重载方法

This commit is contained in:
fengjiayi
2025-07-28 20:21:50 +08:00
parent 69a32831b9
commit a6d6790d31
3 changed files with 69 additions and 100 deletions

View File

@@ -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},
}); });

View File

@@ -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 接口

View File

@@ -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
} }