mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
通过Emit优化Script脚本的解释执行;出于后期更新的方向,暂时隐藏表达式节点、条件表达式节点、全局数据节点;流程图转c#代码新增对于Script脚本的支持,Script脚本现在可以原生导出为C#代码。
This commit is contained in:
@@ -210,7 +210,310 @@ namespace Serein.Library.Utils
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建字段 Getter 委托:Func<object, object>
|
||||
/// </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<object, object>
|
||||
/// </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<object, object>
|
||||
/// </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<object, object>
|
||||
/// </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<object, object, object>
|
||||
/// </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<object, object, object>
|
||||
/// </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>));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
//}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user