暂时实现了简陋的脚本AST分析解释,后面再绑定到控件上

This commit is contained in:
fengjiayi
2024-12-20 23:39:29 +08:00
parent 114e81424b
commit ef119e11e3
52 changed files with 3175 additions and 261 deletions

View File

@@ -66,6 +66,95 @@ namespace Serein.Library.Utils
}
public static Type CreateTypeWithProperties(IDictionary<string, Type> properties, string typeName)
{
// 如果类型已经缓存,直接返回缓存的类型
if (typeCache.ContainsKey(typeName))
{
return typeCache[typeName];
}
// 定义动态程序集和模块
var assemblyName = new AssemblyName("DynamicAssembly");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
// 定义动态类型
var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
// 为每个属性名和值添加相应的属性到动态类型中
foreach (var kvp in properties)
{
string propName = kvp.Key;
object propValue = kvp.Value;
Type propType;
if (propValue is IList<Dictionary<string, Type>>) // 处理数组类型
{
var nestedPropValue = (propValue as IList<Dictionary<string, Type>>)[0];
var nestedType = CreateTypeWithProperties(nestedPropValue, $"{propName}Element");
propType = nestedType.GetType().MakeArrayType(); // 创建数组类型
}
else if (propValue is Dictionary<string, Type> nestedProperties)
{
// 如果值是嵌套的字典,递归创建嵌套类型
propType = CreateTypeWithProperties(nestedProperties, $"{typeName}_{propName}").GetType();
}
else if (propValue is Type type)
{
// 如果是普通类型,使用值的类型
propType = type ?? typeof(object);
}
else
{
throw new Exception($"无法解析的类型:{propValue}");
}
// 定义私有字段和公共属性
var fieldBuilder = typeBuilder.DefineField("_" + propName, propType, FieldAttributes.Private);
var propertyBuilder = typeBuilder.DefineProperty(propName, PropertyAttributes.HasDefault, propType, null);
// 定义 getter 方法
var getMethodBuilder = typeBuilder.DefineMethod(
"get_" + propName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
propType,
Type.EmptyTypes);
var getIL = getMethodBuilder.GetILGenerator();
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, fieldBuilder);
getIL.Emit(OpCodes.Ret);
// 定义 setter 方法
var setMethodBuilder = typeBuilder.DefineMethod(
"set_" + propName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
null,
new Type[] { propType });
var setIL = setMethodBuilder.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, fieldBuilder);
setIL.Emit(OpCodes.Ret);
// 将 getter 和 setter 方法添加到属性
propertyBuilder.SetGetMethod(getMethodBuilder);
propertyBuilder.SetSetMethod(setMethodBuilder);
}
// 创建类型并缓存
var dynamicType = typeBuilder.CreateType();
typeCache[typeName] = dynamicType;
// 创建对象实例
return dynamicType;
}
#region
// 方法 1: 创建动态类型及其对象实例
public static object CreateObjectWithProperties(IDictionary<string, object> properties, string typeName)
@@ -298,6 +387,7 @@ namespace Serein.Library.Utils
return false;
}
#endregion
}
}

View File

@@ -14,6 +14,20 @@ namespace Serein.Library.Utils
/// </summary>
public class EmitHelper
{
public class EmitMethodInfo
{
public Type DeclaringType { get; set; }
/// <summary>
/// 是异步方法
/// </summary>
public bool IsTask { get; set; }
/// <summary>
/// 是静态的
/// </summary>
public bool IsStatic { get; set; }
}
public enum EmitMethodType
{
/// <summary>
@@ -28,6 +42,15 @@ namespace Serein.Library.Utils
/// 有返回值的异步方法
/// </summary>
HasResultTask,
/// <summary>
/// 普通的方法。如果方法返回void时将会返回null。
/// </summary>
StaticFunc,
/// <summary>
/// 无返回值的异步方法
/// </summary>
StaticTask,
}
public static bool IsGenericTask(Type returnType, out Type taskResult)
@@ -60,17 +83,19 @@ namespace Serein.Library.Utils
/// <param name="methodInfo"></param>
/// <param name="delegate"></param>
/// <returns></returns>
public static EmitMethodType CreateDynamicMethod(MethodInfo methodInfo,out Delegate @delegate)
public static EmitMethodInfo CreateDynamicMethod(MethodInfo methodInfo,out Delegate @delegate)
{
EmitMethodInfo emitMethodInfo = new EmitMethodInfo();
bool IsTask = IsGenericTask(methodInfo.ReturnType, out var taskGenericsType);
bool IsTaskGenerics = taskGenericsType != null;
DynamicMethod dynamicMethod;
Type returnType;
if (!IsTask)
{
// 普通方法
returnType = typeof(object);
}
else
{
@@ -96,10 +121,19 @@ namespace Serein.Library.Utils
var il = dynamicMethod.GetILGenerator();
// 加载实例 (this)
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, methodInfo.DeclaringType); // 将 ISocketControlBase 转换为目标类类型
// 判断是否为静态方法
bool isStatic = methodInfo.IsStatic;
if (isStatic)
{
// 如果是静态方法直接跳过实例不加载Ldarg_0
}
else
{
// 加载实例 (this) 对于非静态方法
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, methodInfo.DeclaringType); // 将 ISocketControlBase 转换为目标类类型
}
// 加载方法参数
var methodParams = methodInfo.GetParameters();
for (int i = 0; i < methodParams.Length; i++)
@@ -122,11 +156,17 @@ namespace Serein.Library.Utils
il.Emit(OpCodes.Castclass, paramType);
}
}
// 调用方法
il.Emit(OpCodes.Callvirt, methodInfo);
// 调用方法:静态方法使用 Call实例方法使用 Callvirt
if (isStatic)
{
il.Emit(OpCodes.Call, methodInfo); // 对于静态方法,使用 Call
}
else
{
il.Emit(OpCodes.Callvirt, methodInfo); // 对于实例方法,使用 Callvirt
}
//// 处理返回值如果没有返回值则返回null
if (methodInfo.ReturnType == typeof(void))
@@ -139,27 +179,28 @@ namespace Serein.Library.Utils
}
// 处理返回值如果没有返回值则返回null
il.Emit(OpCodes.Ret); // 返回
EmitMethodType emitMethodType;
if (IsTask)
{
if (IsTaskGenerics)
{
emitMethodType = EmitMethodType.HasResultTask;
@delegate = dynamicMethod.CreateDelegate(typeof(Func<object, object[], Task<object>>));
}
else
{
emitMethodType = EmitMethodType.Task;
@delegate = dynamicMethod.CreateDelegate(typeof(Func<object, object[], Task>));
}
}
else
{
emitMethodType = EmitMethodType.Func;
@delegate = dynamicMethod.CreateDelegate(typeof(Func<object, object[], object>));
}
return emitMethodType;
return new EmitMethodInfo
{
DeclaringType = methodInfo.DeclaringType,
IsTask = IsTask,
IsStatic = isStatic
};
}

View File

@@ -15,6 +15,8 @@ namespace Serein.Library.Utils
/// </summary>
public class SereinIOC/* : ISereinIOC*/
{
/// <summary>
/// 类型集合,暂放待实例化的类型,完成实例化之后移除
/// </summary>