修改了http服务器无法正确处理post请求入参;添加了modbus tcp客户端支持。

This commit is contained in:
fengjiayi
2025-07-23 15:57:57 +08:00
parent acf0b87ad0
commit 4e20e816ae
24 changed files with 2466 additions and 189 deletions

View File

@@ -39,7 +39,7 @@ namespace Serein.Script.Node
public CollectionIndexNode Collection { get; }
/// <summary>
/// 索引来源
/// 赋值值来源
/// </summary>
public ASTNode Value { get; }

View File

@@ -19,6 +19,10 @@
<None Remove="Tool\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Node\ExpressionNode.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Library\Serein.Library.csproj" />
</ItemGroup>

View File

@@ -1,4 +1,5 @@
using Serein.Library;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Serein.Library;
using Serein.Library.Api;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
@@ -22,7 +23,7 @@ namespace Serein.Script
/// <summary>
/// 类型分析
/// </summary>
public SereinScriptTypeAnalysis TypeAnalysis { get; set; } = new SereinScriptTypeAnalysis();
public SereinScriptTypeAnalysis TypeAnalysis { get; } = new SereinScriptTypeAnalysis();
@@ -34,7 +35,7 @@ namespace Serein.Script
SereinScriptParser parser = new SereinScriptParser();
SereinScriptTypeAnalysis analysis = new SereinScriptTypeAnalysis();
var programNode = parser.Parse(script);
analysis.NodeSymbolInfos.Clear(); // 清空符号表
analysis.Reset();
if (argTypes is not null) analysis.LoadSymbol(argTypes); // 提前加载脚本节点定义的符号
analysis.Analysis(programNode); // 分析节点类型
SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(analysis.NodeSymbolInfos);
@@ -61,6 +62,14 @@ namespace Serein.Script
return returnType; // 脚本返回类型
}
/// <summary>
/// 执行脚本
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public async Task<object?> InterpreterAsync(IScriptInvokeContext context)
{
if(programNode is null)
@@ -73,6 +82,35 @@ namespace Serein.Script
}
/// <summary>
/// 转换为c#代码
/// </summary>
/// <param name="script">脚本</param>
/// <param name="argTypes">挂载的变量</param>
/// <returns></returns>
public string ConvertCSharpCode(string mehtodName, Dictionary<string, Type>? argTypes = null)
{
if (string.IsNullOrWhiteSpace(mehtodName)) return string.Empty;
if (programNode is null) return string.Empty;
SereinScriptToCsharpScript tool = new SereinScriptToCsharpScript(TypeAnalysis);
return tool.CompileToCSharp(mehtodName, programNode, argTypes);
}
/// <summary>
/// 编译为 IL 代码
/// </summary>
/// <param name="script">脚本</param>
/// <param name="argTypes">挂载的变量</param>
/// <returns></returns>
[Obsolete("因为暂未想到如何支持异步方法,所以暂时废弃生成", true)]
private Delegate CompilerIL(string dynamicMethodName, ProgramNode programNode, Dictionary<string, Type>? argTypes = null)
{
SereinScriptILCompiler compiler = new SereinScriptILCompiler(TypeAnalysis.NodeSymbolInfos);
var @delegate = compiler.Compiler(dynamicMethodName, programNode, argTypes); // 编译脚本
return @delegate;
}
@@ -96,10 +134,10 @@ namespace Serein.Script
/// <summary>
/// 挂载的函数调用的对象(用于解决函数需要实例才能调用的场景)
/// </summary>
public static Dictionary<string, Func<object>> DelegateInstances = new Dictionary<string, Func<object>>();
// public static Dictionary<string, Func<object>> DelegateInstances = new Dictionary<string, Func<object>>();
/// <summary>
/// 挂载静态函数
/// 挂载函数
/// </summary>
/// <param name="functionName"></param>
/// <param name="methodInfo"></param>
@@ -115,7 +153,7 @@ namespace Serein.Script
/// </summary>
/// <param name="functionName">函数名称</param>
/// <param name="methodInfo">方法信息</param>
public static void AddFunction(string functionName, MethodInfo methodInfo, Func<object>? callObj = null)
/*public static void AddFunction(string functionName, MethodInfo methodInfo, Func<object>? callObj = null)
{
if (!methodInfo.IsStatic && callObj is null)
{
@@ -132,7 +170,7 @@ namespace Serein.Script
{
FunctionDelegates[functionName] = new DelegateDetails(methodInfo);
}
}
}*/
/// <summary>
/// 挂载类型

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script
{
internal static class SereinScriptExtension
{ /// <summary>
/// 添加代码
/// </summary>
/// <param name="sb">字符串构建器</param>
/// <param name="retractCount">缩进次数4个空格</param>
/// <param name="code">要添加的代码</param>
/// <returns>字符串构建器本身</returns>
public static StringBuilder AppendCode(this StringBuilder sb,
int retractCount = 0,
string code = null,
bool isWrapping = true)
{
if (!string.IsNullOrWhiteSpace(code))
{
string retract = new string(' ', retractCount * 4);
sb.Append(retract);
if (isWrapping)
{
sb.AppendLine(code);
}
else
{
sb.Append(code);
}
}
return sb;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -42,13 +42,6 @@ namespace Serein.Script
return result; // 返回最后一个节点的结果
}
/*
async Task<object?> InterpreterAsync(IScriptInvokeContext context, ProgramNode node)
{
return null;
}
return await InterpreterAsync(context, node);
*/
private async Task<object?> InterpretAsync(IScriptInvokeContext context, ASTNode node)
{
switch (node)
@@ -243,8 +236,8 @@ namespace Serein.Script
return await InterpreterObjectInstantiationNodeAsync(context, objectInstantiationNode);
case CtorAssignmentNode ctorAssignmentNode:
return default;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
return await InterpretAsync(context, expressionNode.Value); // 直接计算表达式的值
/*case ExpressionNode expressionNode: // 类型表达式(链式调用)
return await InterpretAsync(context, expressionNode.Value); // 直接计算表达式的值*/
case MemberAccessNode memberAccessNode: // 对象成员访问
async Task<object?> InterpreterMemberAccessNodeAsync(IScriptInvokeContext context, MemberAccessNode memberAccessNode)
{
@@ -319,7 +312,7 @@ namespace Serein.Script
if (!SereinScript.FunctionDelegates.TryGetValue(funcName, out DelegateDetails? function))
throw new SereinSciptException(functionCallNode, $"没有挂载方法\"{functionCallNode.FunctionName}\"");
if (!function.EmitMethodInfo.IsStatic)
/* if (!function.EmitMethodInfo.IsStatic)
{
if (!SereinScript.DelegateInstances.TryGetValue(funcName, out var action))
{
@@ -331,7 +324,7 @@ namespace Serein.Script
{
throw new SereinSciptException(functionCallNode, $"函数 {funcName} 尝试获取实例时返回了 null ");
}
}
}*/
var result = await function.InvokeAsync(instance, arguments);
return result;

View File

@@ -0,0 +1,464 @@
using Newtonsoft.Json.Linq;
using Serein.Library;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Serein.Script
{
/// <summary>
/// 将 Serein 脚本转换为 C# 脚本的类
/// </summary>
internal class SereinScriptToCsharpScript
{
/// <summary>
/// 符号表
/// </summary>
private readonly Dictionary<ASTNode, Type> _symbolInfos;
/// <summary>
/// 记录方法节点是否需要异步调用
/// </summary>
private readonly Dictionary<ASTNode, bool> _asyncMethods;
/// <summary>
/// 临时变量表
/// </summary>
private readonly Dictionary<string, Type> _local = [];
private bool _isTaskMain = false;
public SereinScriptToCsharpScript(SereinScriptTypeAnalysis analysis)
{
_symbolInfos = analysis.NodeSymbolInfos;
_asyncMethods = analysis.AsyncMethods;
_isTaskMain = _asyncMethods.Any(kvp => kvp.Value);
}
private readonly StringBuilder _codeBuilder = new StringBuilder();
private int _indentLevel = 0;
private void AppendLine(string code)
{
_codeBuilder.AppendLine(new string(' ', _indentLevel * 4) + code);
}
private void Append(string code)
{
_codeBuilder.Append(code);
}
private void Indent() => _indentLevel++;
private void Unindent() => _indentLevel--;
private List<Action<StringBuilder>> _classDefinitions = new List<Action<StringBuilder>>();
public string CompileToCSharp(string mehtodName, ProgramNode programNode, Dictionary<string, Type>? param)
{
_codeBuilder.Clear();
var sb = _codeBuilder;
var methodResultType = _symbolInfos[programNode];
if(methodResultType == typeof(void))
{
methodResultType = typeof(object);
}
var taskFullName = typeof(Task).FullName;
var returnContent = _isTaskMain ? $"global::{taskFullName}<global::{methodResultType.FullName}>" : $"global::{methodResultType.FullName}";
AppendLine("public class SereinScriptToCsharp");
AppendLine( "{");
Indent();
if(param is null || param.Count == 0)
{
AppendLine($"public static {returnContent} {mehtodName}()");
}
else
{
AppendLine($"public static {returnContent} {mehtodName}({GetMethodParamster(param)})");
}
AppendLine( "{");
Indent();
foreach (var stmt in programNode.Statements)
{
ConvertCode(stmt); // 递归遍历
Append(";");
}
if(!_symbolInfos.Keys.Any(node => node is ReturnNode))
{
AppendLine("return null;");
}
Unindent();
AppendLine("}");
Unindent();
AppendLine("}");
foreach (var cd in _classDefinitions)
{
cd.Invoke(sb);
}
return sb.ToString();
}
private string GetMethodParamster(Dictionary<string, Type> param)
{
var values = param.Select(kvp =>
{
_local[kvp.Key] = kvp.Value;
return $"global::{kvp.Value.FullName} {kvp.Key}";
});
return string.Join(',', values);
}
private void ConvertCode( ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点
break;
case ReturnNode returnNode: // 程序退出节点
void ConvertCodeOfReturnNode(ReturnNode returnNode)
{
if (returnNode.Value is not null)
{
Append($"return ");
ConvertCode(returnNode.Value);
Append(";");
AppendLine(string.Empty);
}
else
{
AppendLine("return defult;");
}
}
ConvertCodeOfReturnNode(returnNode);
break;
#region
case NullNode nullNode: // null
Append("null");
break;
case CharNode charNode: // char字面量
Append($"'{charNode.Value}'");
break;
case StringNode stringNode: // 字符串字面量
Append($"\"{stringNode.Value}\"");
break;
case BooleanNode booleanNode: // 布尔值字面量
Append($"{(booleanNode.Value ? "true" : "false")}");
break;
case NumberIntNode numberIntNode: // int整型数值字面量
Append($"{numberIntNode.Value}");
break;
case NumberLongNode numberLongNode: // long整型数值字面量
Append($"{numberLongNode.Value}");
break;
case NumberFloatNode numberFloatNode: // float浮点数值字面量
Append($"{numberFloatNode.Value}f");
break;
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
Append($"{numberDoubleNode.Value}d");
break;
#endregion
case IdentifierNode identifierNode: // 变量定义
void ConvertCodeOfIdentifierNode(IdentifierNode identifierNode)
{
var varName = identifierNode.Name;
if(_local.TryGetValue(varName, out var type))
{
// 定义过,需要使用变量
Append(varName);
}
else
{
if (_symbolInfos.TryGetValue(identifierNode, out type))
{
// 不存在,定义变量
Append($"global::{type.FullName} {varName}");
_local[varName] = type;
//Append(varName);
}
else
{
throw new Exception($"加载符号表时,无法匹配 IdentifierNode 节点的类型。 name {varName}");
}
}
}
ConvertCodeOfIdentifierNode(identifierNode);
break;
case IfNode ifNode: // if语句结构
void ConvertCodeOfIfNode(IfNode ifNOde)
{
AppendLine("");
Append($"if(");
ConvertCode(ifNOde.Condition); // 解析条件
Append($" == true)");
AppendLine("{");
Indent();
foreach(var item in ifNOde.TrueBranch)
{
ConvertCode(item);
//Append(";");
AppendLine(string.Empty);
}
Unindent();
AppendLine("}");
AppendLine("else");
AppendLine("{");
Indent();
foreach (var item in ifNOde.TrueBranch)
{
ConvertCode(item);
//Append(";");
AppendLine(string.Empty);
}
Unindent();
AppendLine("}");
}
ConvertCodeOfIfNode(ifNode);
break;
case WhileNode whileNode: // while语句结构
void ConvertCodeOfWhileNode(WhileNode whileNode)
{
AppendLine("");
Append($"while(");
ConvertCode(whileNode.Condition); // 解析条件
Append($" == {true})");
AppendLine("{");
Indent();
foreach (var item in whileNode.Body)
{
ConvertCode(item);
Append(";");
AppendLine(string.Empty);
}
Unindent();
AppendLine("}");
}
ConvertCodeOfWhileNode(whileNode);
break;
case AssignmentNode assignmentNode: // 变量赋值语句
void ConvertCodeOfAssignmentNode(AssignmentNode assignmentNode)
{
ConvertCode(assignmentNode.Target);
Append(" = ");
if (assignmentNode.Value is null)
{
Append("null");
}
else
{
ConvertCode(assignmentNode.Value);
}
Append(";");
AppendLine(string.Empty);
}
ConvertCodeOfAssignmentNode(assignmentNode);
break;
case BinaryOperationNode binaryOperationNode: // 二元运算操作
void ConvertCodeOfBinaryOperationNode(BinaryOperationNode binaryOperationNode)
{
Append("(");
ConvertCode(binaryOperationNode.Left); // 左操作数
Append(binaryOperationNode.Operator); // 操作符
ConvertCode(binaryOperationNode.Right); // 左操作数
Append(")");
}
ConvertCodeOfBinaryOperationNode(binaryOperationNode);
break;
case CollectionAssignmentNode collectionAssignmentNode:
void ConvertCodeOfCollectionAssignmentNode(CollectionAssignmentNode collectionAssignmentNode)
{
ConvertCode(collectionAssignmentNode.Collection);
Append(" = ");
ConvertCode(collectionAssignmentNode.Value);
Append(";");
AppendLine(string.Empty);
}
ConvertCodeOfCollectionAssignmentNode(collectionAssignmentNode);
break;
case CollectionIndexNode collectionIndexNode: // 集合类型操作
void ConvertCodeOfCollectionIndexNode(CollectionIndexNode collectionIndexNode)
{
ConvertCode(collectionIndexNode.Collection);
Append("[");
ConvertCode(collectionIndexNode.Index);
Append("]");
}
ConvertCodeOfCollectionIndexNode(collectionIndexNode);
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
void ConvertCodeOfClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
{
_classDefinitions.Add((sb) =>
{
var type = _symbolInfos[classTypeDefinitionNode.ClassType];
AppendLine($"public class {type.FullName}");
AppendLine("{");
Indent();
foreach (var property in classTypeDefinitionNode.Propertys)
{
var propertyName = property.Key;
var propertyType = _symbolInfos[property.Value];
AppendLine($"public global::{propertyType.FullName} {propertyName} {{ get; set; }}");
}
Unindent();
AppendLine("}");
});
}
ConvertCodeOfClassTypeDefinitionNode(classTypeDefinitionNode);
break;
case TypeNode typeNode: // 类型
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
void ConvertCodeOfObjectInstantiationNode(ObjectInstantiationNode objectInstantiationNode)
{
var type = _symbolInfos[objectInstantiationNode.Type];
Append($"new global::{type}");
if (objectInstantiationNode.Arguments.Count > 0)
{
Append("(");
for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++)
{
ConvertCode(objectInstantiationNode.Arguments[i]);
if (i < objectInstantiationNode.Arguments.Count - 1)
{
Append(", ");
}
}
Append(")");
}
else
{
Append("()");
}
if (objectInstantiationNode.CtorAssignments.Count > 0)
{
AppendLine("{");
Indent();
foreach (var assignment in objectInstantiationNode.CtorAssignments)
{
ConvertCode(assignment);
}
Unindent();
AppendLine("}");
}
}
ConvertCodeOfObjectInstantiationNode(objectInstantiationNode);
break;
case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值
void ConvertCodeOfCtorAssignmentNode(CtorAssignmentNode ctorAssignmentNode)
{
var propertyName = ctorAssignmentNode.MemberName;
var value = ctorAssignmentNode.Value;
Append($"{propertyName} = ");
ConvertCode(value);
AppendLine(",");
}
ConvertCodeOfCtorAssignmentNode(ctorAssignmentNode);
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
void ConvertCodeOfMemberAccessNode(MemberAccessNode memberAccessNode)
{
ConvertCode(memberAccessNode.Object);
Append($".{memberAccessNode.MemberName}");
}
ConvertCodeOfMemberAccessNode(memberAccessNode);
break;
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
void ConvertCodeOfMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
ConvertCode(memberAssignmentNode.Object);
Append($".{memberAssignmentNode.MemberName} = ");
ConvertCode(memberAssignmentNode.Value);
Append($";");
AppendLine(string.Empty);
}
ConvertCodeOfMemberAssignmentNode(memberAssignmentNode);
break;
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
void ConvertCodeOfMemberFunctionCallNode(MemberFunctionCallNode memberFunctionCallNode)
{
var isAsync = _asyncMethods.TryGetValue(memberFunctionCallNode, out var isAsyncValue) && isAsyncValue;
if (isAsync)
{
Append($"(await ");
}
ConvertCode(memberFunctionCallNode.Object);
Append($".{memberFunctionCallNode.FunctionName}(");
for (int i = 0; i < memberFunctionCallNode.Arguments.Count; i++)
{
ASTNode? argNode = memberFunctionCallNode.Arguments[i];
ConvertCode(argNode);
if (i < memberFunctionCallNode.Arguments.Count - 1)
{
Append(", ");
}
}
Append($")");
if (isAsync)
{
Append($")");
}
}
ConvertCodeOfMemberFunctionCallNode(memberFunctionCallNode);
break;
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
void ConvertCodeOfFunctionCallNode(FunctionCallNode functionCallNode)
{
var isAsync = _asyncMethods.TryGetValue(functionCallNode, out var isAsyncValue) && isAsyncValue;
if (isAsync)
{
Append($"(await ");
}
var funcName = functionCallNode.FunctionName switch
{
"int" => "@int" ,
"bool" => "@bool" ,
"double" => "@double" ,
"long" => "@long" ,
"decimal" => "@decimal" ,
"float" => "@float" ,
"byte" => "@byte" ,
_ => functionCallNode.FunctionName,
};
Append($"global::Serein.Library.ScriptBaseFunc.{funcName}(");
for (int i = 0; i < functionCallNode.Arguments.Count; i++)
{
ASTNode? argNode = functionCallNode.Arguments[i];
ConvertCode(argNode);
if (i < functionCallNode.Arguments.Count - 1)
{
Append(", ");
}
}
Append($")");
if (isAsync)
{
Append($")");
}
}
ConvertCodeOfFunctionCallNode(functionCallNode);
break;
default: // 未定义的节点类型
break;
}
}
}
}

View File

@@ -5,6 +5,7 @@ using Serein.Script.Node.FlowControl;
using Serein.Script.Symbol;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive;
using System.Reflection;
@@ -27,6 +28,17 @@ namespace Serein.Script
/// </summary>
public Dictionary<ASTNode, Type> NodeSymbolInfos { get; } = new Dictionary<ASTNode, Type>();
/// <summary>
/// 记录方法节点是否需要进行异步调用
/// </summary>
public Dictionary<ASTNode, bool> AsyncMethods { get; } = new Dictionary<ASTNode, bool>();
public void Reset()
{
NodeSymbolInfos.Clear(); // 清空符号表
AsyncMethods.Clear();
}
public void LoadSymbol(Dictionary<string,Type> identifierNodes)
{
foreach(var kvp in identifierNodes)
@@ -74,6 +86,7 @@ namespace Serein.Script
}
}
/// <summary>
/// 类型获取
@@ -293,7 +306,7 @@ namespace Serein.Script
return valueType;
}
return AnalysisCtorAssignmentNode(ctorAssignmentNode);
case ExpressionNode expressionNode: // 类型表达式(链式调用)
/*case ExpressionNode expressionNode: // 类型表达式(链式调用)
Type AnalysisObjectMemberExpressionNode(ExpressionNode expressionNode)
{
// 1. 对象成员获取 MemberAccessNode
@@ -304,7 +317,7 @@ namespace Serein.Script
NodeSymbolInfos[expressionNode] = resultType;
return resultType;
}
return AnalysisObjectMemberExpressionNode(expressionNode);
return AnalysisObjectMemberExpressionNode(expressionNode);*/
case MemberAccessNode memberAccessNode: // 对象成员访问
Type AnalysisMemberAccessNode(MemberAccessNode memberAccessNode)
{
@@ -365,9 +378,12 @@ namespace Serein.Script
Type argType = types[index];
NodeSymbolInfos[argNode] = argType;
}
var isAsync = IsGenericTask(methodInfo.ReturnType, out var taskResult);
var methodReturnType = isAsync ? taskResult : methodInfo.ReturnType;
AsyncMethods[memberFunctionCallNode] = isAsync;
NodeSymbolInfos[memberFunctionCallNode.Object] = objectType;
NodeSymbolInfos[memberFunctionCallNode] = methodInfo.ReturnType;
return methodInfo.ReturnType;
NodeSymbolInfos[memberFunctionCallNode] = methodReturnType;
return methodReturnType;
}
@@ -386,8 +402,11 @@ namespace Serein.Script
Type argType = types[index];
NodeSymbolInfos[argNode] = argType;
}
NodeSymbolInfos[functionCallNode] = methodInfo.ReturnType;
return methodInfo.ReturnType;
var isAsync = IsGenericTask(methodInfo.ReturnType, out var taskResult);
var methodReturnType = isAsync ? taskResult : methodInfo.ReturnType;
AsyncMethods[functionCallNode] = isAsync;
NodeSymbolInfos[functionCallNode] = methodReturnType;
return methodReturnType;
}
return AnalysisFunctionCallNode(functionCallNode);
default: // 未定义的节点类型
@@ -398,7 +417,6 @@ namespace Serein.Script
/// <summary>
/// 类型分析
/// </summary>
@@ -472,9 +490,9 @@ namespace Serein.Script
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Analysis(objectInstantiationNode);
break;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
/* case ExpressionNode expressionNode: // 类型表达式(链式调用)
Analysis(expressionNode.Value);
break;
break;*/
case MemberAccessNode memberAccessNode: // 对象成员访问
Analysis(memberAccessNode);
break;
@@ -497,7 +515,7 @@ namespace Serein.Script
}
private void Analysis2(ASTNode node)
private void ToILCompiler(ASTNode node)
{
switch (node)
{
@@ -541,9 +559,7 @@ namespace Serein.Script
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
break;
case CtorAssignmentNode ctorAssignmentNode:
break;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值
break;
case MemberAccessNode memberAccessNode: // 对象成员访问
break;
@@ -582,8 +598,28 @@ namespace Serein.Script
}
}
private static bool IsGenericTask(Type returnType, out Type taskResult)
{
// 判断是否为 Task 类型或泛型 Task<T>
if (returnType == typeof(Task))
{
taskResult = typeof(void);
return true;
}
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
{
// 获取泛型参数类型
Type genericArgument = returnType.GetGenericArguments()[0];
taskResult = genericArgument;
return true;
}
else
{
taskResult = null;
return false;
}
}
/// <summary>
/// 获取某个集合类型支持的索引参数类型