123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- using System.Reflection;
- using System.Reflection.Emit;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.Order;
- using MiniExcelLibs.Attributes;
- using XF.Domain.Extensions;
- namespace Hotline.Tools;
- public class DynamicClassHelper
- {
- public static Type CreateDynamicClass(List<ColumnInfo> propInfos)
- {
- string className = "DynamicClass";
- AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
- TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
- foreach (var property in propInfos.OrderBy(d => d.Sort).ToList())
- {
- var propertyName = property.Prop.Trim().ToPascalCase();
- var propertyType = typeof(string);
- FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
- PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
- MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
- MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes);
- ILGenerator getIL = getMethodBuilder.GetILGenerator();
- getIL.Emit(OpCodes.Ldarg_0);
- getIL.Emit(OpCodes.Ldfld, fieldBuilder);
- getIL.Emit(OpCodes.Ret);
- MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType });
- ILGenerator setIL = setMethodBuilder.GetILGenerator();
- setIL.Emit(OpCodes.Ldarg_0);
- setIL.Emit(OpCodes.Ldarg_1);
- setIL.Emit(OpCodes.Stfld, fieldBuilder);
- setIL.Emit(OpCodes.Ret);
- propertyBuilder.SetGetMethod(getMethodBuilder);
- propertyBuilder.SetSetMethod(setMethodBuilder);
- var columnNameCtorInfo = typeof(ExcelColumnNameAttribute).GetConstructor(new Type[] { typeof(string), typeof(string[]) });
- var attributeBuilder = new CustomAttributeBuilder(columnNameCtorInfo, new object[] { property.Name, null });
- propertyBuilder.SetCustomAttribute(attributeBuilder);
- }
- Type generatedType = typeBuilder.CreateType();
- return generatedType;
- }
- public static Type CreateDynamicClass<TSource>(List<ColumnInfo> propInfos)
- {
- string className = "DynamicClass";
- AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
- TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
- var sourceProps = typeof(TSource).GetProperties();
- InitTypeBuilder(propInfos, sourceProps, typeBuilder);
- Type generatedType = typeBuilder.CreateType();
- return generatedType;
- }
- public static Type CreateDynamicClass(List<ColumnInfo> propInfos, Type tSource)
- {
- string className = "DynamicClass";
- AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
- AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
- TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);
- var sourceProps = tSource.GetProperties();
- InitTypeBuilder(propInfos, sourceProps, typeBuilder);
- Type generatedType = typeBuilder.CreateType();
- return generatedType;
- }
- private static void InitTypeBuilder(List<ColumnInfo> propInfos, PropertyInfo[] sourceProps, TypeBuilder typeBuilder)
- {
- foreach (var property in propInfos.OrderBy(d => d.Sort).ToList())
- {
- var propertyName = property.Prop.Trim().ToPascalCase();
- //var propertyType = sourceProps.FirstOrDefault(d => d.Name == propertyName)?.PropertyType ?? typeof(string);
- var propertyType = GetPropertyType(property.Prop, sourceProps);
- FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
- PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
- MethodAttributes getSetAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
- MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, getSetAttributes, propertyType, Type.EmptyTypes);
- ILGenerator getIL = getMethodBuilder.GetILGenerator();
- getIL.Emit(OpCodes.Ldarg_0);
- getIL.Emit(OpCodes.Ldfld, fieldBuilder);
- getIL.Emit(OpCodes.Ret);
- MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, getSetAttributes, null, new Type[] { propertyType });
- ILGenerator setIL = setMethodBuilder.GetILGenerator();
- setIL.Emit(OpCodes.Ldarg_0);
- setIL.Emit(OpCodes.Ldarg_1);
- setIL.Emit(OpCodes.Stfld, fieldBuilder);
- setIL.Emit(OpCodes.Ret);
- propertyBuilder.SetGetMethod(getMethodBuilder);
- propertyBuilder.SetSetMethod(setMethodBuilder);
- var columnNameCtorInfo = typeof(ExcelColumnNameAttribute).GetConstructor(new Type[] { typeof(string), typeof(string[]) });
- var attributeBuilder = new CustomAttributeBuilder(columnNameCtorInfo, new object[] { property.Name, null });
- propertyBuilder.SetCustomAttribute(attributeBuilder);
- if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
- {
- var columnExcelFormatCtorInfo = typeof(ExcelFormatAttribute).GetConstructor(new Type[] { typeof(string) });
- var excelFormatAttributeBuilder = new CustomAttributeBuilder(columnExcelFormatCtorInfo, new object[] { "yyyy-MM-dd HH:mm:ss" });
- propertyBuilder.SetCustomAttribute(excelFormatAttributeBuilder);
- }
- }
- }
- private static Type GetPropertyType(string propName, PropertyInfo[] sourceProps)
- {
- var propNameArray = propName.Split('.', StringSplitOptions.TrimEntries)
- .Select(d => d.ToPascalCase())
- .ToList();
- if (propNameArray.Count == 1)
- {
- return sourceProps.FirstOrDefault(d => d.Name == propNameArray[0])?.PropertyType ?? typeof(string);
- }
- else
- {
- var prop = sourceProps.FirstOrDefault(d => d.Name == propNameArray[0]);
- if (prop == null)
- return typeof(string);
- return GetPropertyType(string.Join(".", propNameArray.Skip(1)), prop.PropertyType.GetProperties());
- }
- }
- }
|