通过Emit优化Script脚本的解释执行;出于后期更新的方向,暂时隐藏表达式节点、条件表达式节点、全局数据节点;流程图转c#代码新增对于Script脚本的支持,Script脚本现在可以原生导出为C#代码。

This commit is contained in:
fengjiayi
2025-07-26 19:36:54 +08:00
parent 9a8de6b571
commit 29f2be5c80
32 changed files with 2175 additions and 432 deletions

View File

@@ -210,7 +210,310 @@ namespace Serein.Library.Utils
};
}
}
/// <summary>
/// 创建字段 Getter 委托Func&lt;object, object&gt;
/// </summary>
public static Func<object, object> CreateFieldGetter(FieldInfo fieldInfo)
{
if (fieldInfo == null)
throw new ArgumentNullException(nameof(fieldInfo));
var method = new DynamicMethod(
fieldInfo.Name + "_Get",
typeof(object),
new[] { typeof(object) },
fieldInfo.DeclaringType,
true);
ILGenerator il = method.GetILGenerator();
if (!fieldInfo.IsStatic)
{
// 加载实例
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
il.Emit(OpCodes.Ldfld, fieldInfo);
}
else
{
il.Emit(OpCodes.Ldsfld, fieldInfo);
}
// 如果是值类型,装箱
if (fieldInfo.FieldType.IsValueType)
il.Emit(OpCodes.Box, fieldInfo.FieldType);
il.Emit(OpCodes.Ret);
return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
}
/// <summary>
/// 创建字段 Setter 委托Action&lt;object, object&gt;
/// </summary>
public static Action<object, object> CreateFieldSetter(FieldInfo fieldInfo)
{
if (fieldInfo == null)
throw new ArgumentNullException(nameof(fieldInfo));
if (fieldInfo.IsInitOnly)
throw new InvalidOperationException($"字段 {fieldInfo.Name} 是只读字段,无法设置值。");
var method = new DynamicMethod(
fieldInfo.Name + "_Set",
null,
new[] { typeof(object), typeof(object) },
fieldInfo.DeclaringType,
true);
ILGenerator il = method.GetILGenerator();
if (!fieldInfo.IsStatic)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, fieldInfo.DeclaringType);
}
// 加载值
il.Emit(OpCodes.Ldarg_1);
if (fieldInfo.FieldType.IsValueType)
il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
else
il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
if (fieldInfo.IsStatic)
il.Emit(OpCodes.Stsfld, fieldInfo);
else
il.Emit(OpCodes.Stfld, fieldInfo);
il.Emit(OpCodes.Ret);
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
}
/// <summary>
/// 创建属性 Getter 委托Func&lt;object, object&gt;
/// </summary>
public static Func<object, object> CreatePropertyGetter(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
throw new ArgumentNullException(nameof(propertyInfo));
var getMethod = propertyInfo.GetGetMethod(true);
if (getMethod == null)
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Getter。");
var method = new DynamicMethod(
propertyInfo.Name + "_Get",
typeof(object),
new[] { typeof(object) },
propertyInfo.DeclaringType,
true);
ILGenerator il = method.GetILGenerator();
if (!getMethod.IsStatic)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
il.EmitCall(OpCodes.Callvirt, getMethod, null);
}
else
{
il.EmitCall(OpCodes.Call, getMethod, null);
}
// 装箱
if (propertyInfo.PropertyType.IsValueType)
il.Emit(OpCodes.Box, propertyInfo.PropertyType);
il.Emit(OpCodes.Ret);
return (Func<object, object>)method.CreateDelegate(typeof(Func<object, object>));
}
/// <summary>
/// 创建属性 Setter 委托Action&lt;object, object&gt;
/// </summary>
public static Action<object, object> CreatePropertySetter(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
throw new ArgumentNullException(nameof(propertyInfo));
var setMethod = propertyInfo.GetSetMethod(true);
if (setMethod == null)
throw new InvalidOperationException($"属性 {propertyInfo.Name} 没有可用的 Setter。");
var method = new DynamicMethod(
propertyInfo.Name + "_Set",
null,
new[] { typeof(object), typeof(object) },
propertyInfo.DeclaringType,
true);
ILGenerator il = method.GetILGenerator();
if (!setMethod.IsStatic)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
}
// 加载值
il.Emit(OpCodes.Ldarg_1);
if (propertyInfo.PropertyType.IsValueType)
il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
else
il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
if (setMethod.IsStatic)
il.EmitCall(OpCodes.Call, setMethod, null);
else
il.EmitCall(OpCodes.Callvirt, setMethod, null);
il.Emit(OpCodes.Ret);
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
}
/// <summary>
/// 创建集合赋值委托Action&lt;object, object, object&gt;
/// </summary>
/// <param name="collectionType"></param>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
public static Action<object, object, object> CreateCollectionSetter(Type collectionType)
{
DynamicMethod dm = new DynamicMethod(
"SetCollectionValue",
null,
new[] { typeof(object), typeof(object), typeof(object) },
typeof(EmitHelper).Module,
true);
ILGenerator il = dm.GetILGenerator();
if (collectionType.IsArray)
{
// (object array, object index, object value) => ((T[])array)[(int)index] = (T)value;
var elementType = collectionType.GetElementType()!;
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, collectionType); // 转为真实数组类型
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Unbox_Any, typeof(int)); // index
il.Emit(OpCodes.Ldarg_2);
if (elementType.IsValueType)
il.Emit(OpCodes.Unbox_Any, elementType);
else
il.Emit(OpCodes.Castclass, elementType);
il.Emit(OpCodes.Stelem, elementType); // 设置数组元素
il.Emit(OpCodes.Ret);
}
else
{
// 尝试获取 set_Item 方法
MethodInfo? setItem = collectionType.GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
if (setItem == null)
throw new NotSupportedException($"类型 {collectionType} 不支持 set_Item。");
var parameters = setItem.GetParameters();
var indexType = parameters[0].ParameterType;
var valueType = parameters[1].ParameterType;
// (object collection, object index, object value) => ((CollectionType)collection)[(IndexType)index] = (ValueType)value;
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, collectionType);
il.Emit(OpCodes.Ldarg_1);
if (indexType.IsValueType)
il.Emit(OpCodes.Unbox_Any, indexType);
else
il.Emit(OpCodes.Castclass, indexType);
il.Emit(OpCodes.Ldarg_2);
if (valueType.IsValueType)
il.Emit(OpCodes.Unbox_Any, valueType);
else
il.Emit(OpCodes.Castclass, valueType);
il.Emit(OpCodes.Callvirt, setItem);
il.Emit(OpCodes.Ret);
}
return (Action<object, object, object>)dm.CreateDelegate(typeof(Action<object, object, object>));
}
/// <summary>
/// 创建集合获取委托Func&lt;object, object, object&gt;
/// </summary>
/// <param name="collectionType"></param>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
public static Func<object, object, object> CreateCollectionGetter(Type collectionType)
{
DynamicMethod dm = new DynamicMethod(
"GetCollectionValue",
typeof(object),
new[] { typeof(object), typeof(object) },
typeof(EmitHelper).Module,
true);
ILGenerator il = dm.GetILGenerator();
if (collectionType.IsArray)
{
// (object array, object index) => ((T[])array)[(int)index]
var elementType = collectionType.GetElementType()!;
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, collectionType); // 转为真实数组类型
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Unbox_Any, typeof(int)); // index
il.Emit(OpCodes.Ldelem, elementType); // 取值
if (elementType.IsValueType)
il.Emit(OpCodes.Box, elementType); // 装箱
il.Emit(OpCodes.Ret);
}
else
{
// 调用 get_Item 方法
MethodInfo? getItem = collectionType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
if (getItem == null)
throw new NotSupportedException($"类型 {collectionType} 不支持 get_Item。");
var parameters = getItem.GetParameters();
var indexType = parameters[0].ParameterType;
var returnType = getItem.ReturnType;
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, collectionType);
il.Emit(OpCodes.Ldarg_1);
if (indexType.IsValueType)
il.Emit(OpCodes.Unbox_Any, indexType);
else
il.Emit(OpCodes.Castclass, indexType);
il.Emit(OpCodes.Callvirt, getItem);
if (returnType.IsValueType)
il.Emit(OpCodes.Box, returnType);
il.Emit(OpCodes.Ret);
}
return (Func<object, object, object>)dm.CreateDelegate(typeof(Func<object, object, object>));
}
}
}

View File

@@ -36,6 +36,16 @@ namespace Serein.Library.Utils.SereinExpression
}
}
/// <summary>
/// 连接字符串数组的指定部分
/// </summary>
/// <param name="parts"></param>
/// <param name="startIndex"></param>
/// <param name="count"></param>
/// <param name="separator"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static string JoinStrings(string[] parts, int startIndex, int count, char separator)
{
if (parts == null)
@@ -51,14 +61,21 @@ namespace Serein.Library.Utils.SereinExpression
// 使用 string.Join 连接
return string.Join(separator.ToString(), subArray);
}
}
/// <summary>
/// 条件解析器生成IL进行判断
/// 格式: data.[propertyName] [operator] [value]
/// </summary>
public class SereinConditionParser
{
/// <summary>
/// 条件表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <param name="expression"></param>
/// <returns></returns>
public static bool To<T>(T data, string expression)
{
try
@@ -67,8 +84,8 @@ namespace Serein.Library.Utils.SereinExpression
{
return false;
}
var parse = ConditionParse(data, expression);
var result = parse.Evaluate(data);
var parse = ConditionParse(data, expression); // 解析条件
var result = parse.Evaluate(data); // 执行判断
return result;
}
@@ -79,15 +96,23 @@ namespace Serein.Library.Utils.SereinExpression
}
}
public static SereinConditionResolver ConditionParse(object data, string expression)
/// <summary>
/// 解析条件
/// </summary>
/// <param name="data"></param>
/// <param name="expression"></param>
/// <returns></returns>
private static SereinConditionResolver ConditionParse(object data, string expression)
{
//ReadOnlySpan<char> expSpan = expression.AsSpan();
if (expression[0] == '.') // 表达式前缀属于从上一个节点数据对象获取成员值
{
return ParseObjectExpression(data, expression);
return ParseObjectExpression(data, expression); // 对象表达式解析
}
else
{
return ParseSimpleExpression(data, expression);
return ParseSimpleExpression(data, expression); // 简单表达式解析
}
@@ -115,6 +140,7 @@ namespace Serein.Library.Utils.SereinExpression
return null;
}
/// <summary>
/// 获取对象指定名称的成员
/// </summary>
@@ -505,42 +531,7 @@ namespace Serein.Library.Utils.SereinExpression
}
}
//public static T ValueParse<T>(object value) where T : struct, IComparable<T>
//{
// return (T)ValueParse(typeof(T), value);
//}
//public static object ValueParse(Type type, object value)
//{
// string? valueStr = value.ToString();
// if (string.IsNullOrEmpty(valueStr))
// {
// throw new ArgumentException("value is null");
// }
// object result = type switch
// {
// Type t when t.IsEnum => Enum.Parse(type, valueStr),
// Type t when t == typeof(bool) => bool.Parse(valueStr),
// Type t when t == typeof(float) => float.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(decimal) => decimal.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(double) => double.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(sbyte) => sbyte.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(byte) => byte.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(short) => short.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(ushort) => ushort.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(int) => int.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(uint) => uint.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(long) => long.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(ulong) => ulong.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(nint) => nint.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(nuint) => nuint.Parse(valueStr, CultureInfo.InvariantCulture),
// _ => throw new ArgumentException("非预期值类型")
// };
// return result;
//}
/// <summary>
/// 数值操作类型
@@ -648,3 +639,41 @@ namespace Serein.Library.Utils.SereinExpression
}
}
//public static T ValueParse<T>(object value) where T : struct, IComparable<T>
//{
// return (T)ValueParse(typeof(T), value);
//}
//public static object ValueParse(Type type, object value)
//{
// string? valueStr = value.ToString();
// if (string.IsNullOrEmpty(valueStr))
// {
// throw new ArgumentException("value is null");
// }
// object result = type switch
// {
// Type t when t.IsEnum => Enum.Parse(type, valueStr),
// Type t when t == typeof(bool) => bool.Parse(valueStr),
// Type t when t == typeof(float) => float.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(decimal) => decimal.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(double) => double.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(sbyte) => sbyte.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(byte) => byte.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(short) => short.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(ushort) => ushort.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(int) => int.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(uint) => uint.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(long) => long.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(ulong) => ulong.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(nint) => nint.Parse(valueStr, CultureInfo.InvariantCulture),
// Type t when t == typeof(nuint) => nuint.Parse(valueStr, CultureInfo.InvariantCulture),
// _ => throw new ArgumentException("非预期值类型")
// };
// return result;
//}