修复了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
+8 -8
View File
@@ -200,16 +200,16 @@ namespace Serein.NodeFlow.Model
var dataType = data is null ? typeof(object) : data.GetType();
if (expression[0..4].Equals("@get", StringComparison.CurrentCultureIgnoreCase))
{
expression = expression[4..];
getValueExpression = expression[4..];
// 表达式默认包含 “.”
expression = $"return {dataName}{expression};";
getValueExpression = $"return {dataName}{expression};";
}
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},
});
@@ -239,18 +239,18 @@ namespace Serein.NodeFlow.Model
conditionExpression = expression;
conditionScript = new SereinScript();
var dataType = data is null ? typeof(object) : data.GetType();
expression = expression.Trim();
conditionExpression = expression.Trim();
if (expression[0] == '.')
{
// 对象取值
expression = $"return {dataName}{expression};";
conditionExpression = $"return {dataName}{expression};";
}
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},
});
+55
View File
@@ -134,6 +134,61 @@ https://space.bilibili.com/33526379
* 参数描述:Type,触发状态描述(External外部触发,Overtime超时触发),当你在代码中的其他地方主动触发了触发器,则该次触发类型为External,当你在创建触发器后超过了指定时间(创建触发器时会要求声明超时时间),则会自动触发,但触发类型为Overtime,触发参数未你在创建触发器时指定的值)
* 参数描述:Value,触发时传递的参数。
* 使用场景:配合 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 - 自定义控件**
* 入参:默认使用上一节点返回值。
* 返回值:IEmbeddedContent 接口
+6 -92
View File
@@ -261,7 +261,12 @@ namespace Serein.Script
if (!ASTDelegateDetails.TryGetValue(memberFunctionCallNode, out DelegateDetails? delegateDetails))
{
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}\"");
delegateDetails = new DelegateDetails(methodInfo);
ASTDelegateDetails[memberFunctionCallNode] = delegateDetails;
@@ -468,52 +473,6 @@ namespace Serein.Script
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>
@@ -545,51 +504,6 @@ namespace Serein.Script
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
}