DynamicClassHelper.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using System.Reflection;
  2. using System.Reflection.Emit;
  3. using Hotline.Share.Dtos;
  4. using Hotline.Share.Dtos.Order;
  5. using MiniExcelLibs.Attributes;
  6. using XF.Domain.Extensions;
  7. namespace Hotline.Tools;
  8. public class DynamicClassHelper
  9. {
  10. public static Type CreateDynamicClass(List<ColumnInfo> propInfos)
  11. {
  12. string className = "DynamicClass";
  13. AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
  14. AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  15. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
  16. TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
  17. foreach (var property in propInfos.OrderBy(d => d.Sort).ToList())
  18. {
  19. var propertyName = property.Prop.Trim().ToPascalCase();
  20. var propertyType = typeof(string);
  21. FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
  22. PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
  23. MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
  24. MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes);
  25. ILGenerator getIL = getMethodBuilder.GetILGenerator();
  26. getIL.Emit(OpCodes.Ldarg_0);
  27. getIL.Emit(OpCodes.Ldfld, fieldBuilder);
  28. getIL.Emit(OpCodes.Ret);
  29. MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType });
  30. ILGenerator setIL = setMethodBuilder.GetILGenerator();
  31. setIL.Emit(OpCodes.Ldarg_0);
  32. setIL.Emit(OpCodes.Ldarg_1);
  33. setIL.Emit(OpCodes.Stfld, fieldBuilder);
  34. setIL.Emit(OpCodes.Ret);
  35. propertyBuilder.SetGetMethod(getMethodBuilder);
  36. propertyBuilder.SetSetMethod(setMethodBuilder);
  37. var columnNameCtorInfo = typeof(ExcelColumnNameAttribute).GetConstructor(new Type[] { typeof(string), typeof(string[]) });
  38. var attributeBuilder = new CustomAttributeBuilder(columnNameCtorInfo, new object[] { property.Name, null });
  39. propertyBuilder.SetCustomAttribute(attributeBuilder);
  40. }
  41. Type generatedType = typeBuilder.CreateType();
  42. return generatedType;
  43. }
  44. public static Type CreateDynamicClass<TSource>(List<ColumnInfo> propInfos)
  45. {
  46. string className = "DynamicClass";
  47. AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
  48. AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  49. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
  50. TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
  51. var sourceProps = typeof(TSource).GetProperties();
  52. InitTypeBuilder(propInfos, sourceProps, typeBuilder);
  53. Type generatedType = typeBuilder.CreateType();
  54. return generatedType;
  55. }
  56. public static Type CreateDynamicClass(List<ColumnInfo> propInfos, Type tSource)
  57. {
  58. string className = "DynamicClass";
  59. AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
  60. AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  61. ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
  62. TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
  63. var sourceProps = tSource.GetProperties();
  64. InitTypeBuilder(propInfos, sourceProps, typeBuilder);
  65. Type generatedType = typeBuilder.CreateType();
  66. return generatedType;
  67. }
  68. private static void InitTypeBuilder(List<ColumnInfo> propInfos, PropertyInfo[] sourceProps, TypeBuilder typeBuilder)
  69. {
  70. foreach (var property in propInfos.OrderBy(d => d.Sort).ToList())
  71. {
  72. var propertyName = property.Prop.Trim().ToPascalCase();
  73. //var propertyType = sourceProps.FirstOrDefault(d => d.Name == propertyName)?.PropertyType ?? typeof(string);
  74. var propertyType = GetPropertyType(property.Prop, sourceProps);
  75. FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
  76. PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
  77. MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
  78. MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes);
  79. ILGenerator getIL = getMethodBuilder.GetILGenerator();
  80. getIL.Emit(OpCodes.Ldarg_0);
  81. getIL.Emit(OpCodes.Ldfld, fieldBuilder);
  82. getIL.Emit(OpCodes.Ret);
  83. MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType });
  84. ILGenerator setIL = setMethodBuilder.GetILGenerator();
  85. setIL.Emit(OpCodes.Ldarg_0);
  86. setIL.Emit(OpCodes.Ldarg_1);
  87. setIL.Emit(OpCodes.Stfld, fieldBuilder);
  88. setIL.Emit(OpCodes.Ret);
  89. propertyBuilder.SetGetMethod(getMethodBuilder);
  90. propertyBuilder.SetSetMethod(setMethodBuilder);
  91. var columnNameCtorInfo = typeof(ExcelColumnNameAttribute).GetConstructor(new Type[] { typeof(string), typeof(string[]) });
  92. var attributeBuilder = new CustomAttributeBuilder(columnNameCtorInfo, new object[] { property.Name, null });
  93. propertyBuilder.SetCustomAttribute(attributeBuilder);
  94. if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
  95. {
  96. var columnExcelFormatCtorInfo = typeof(ExcelFormatAttribute).GetConstructor(new Type[] { typeof(string) });
  97. var excelFormatAttributeBuilder = new CustomAttributeBuilder(columnExcelFormatCtorInfo, new object[] { "yyyy-MM-dd HH:mm:ss" });
  98. propertyBuilder.SetCustomAttribute(excelFormatAttributeBuilder);
  99. }
  100. }
  101. }
  102. private static Type GetPropertyType(string propName, PropertyInfo[] sourceProps)
  103. {
  104. var propNameArray = propName.Split('.', StringSplitOptions.TrimEntries)
  105. .Select(d => d.ToPascalCase())
  106. .ToList();
  107. if (propNameArray.Count == 1)
  108. {
  109. return sourceProps.FirstOrDefault(d => d.Name == propNameArray[0])?.PropertyType ?? typeof(string);
  110. }
  111. else
  112. {
  113. var prop = sourceProps.FirstOrDefault(d => d.Name == propNameArray[0]);
  114. if (prop == null)
  115. return typeof(string);
  116. return GetPropertyType(string.Join(".", propNameArray.Skip(1)), prop.PropertyType.GetProperties());
  117. }
  118. }
  119. }