diff --git a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicBuilderHelper.cs b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicBuilderHelper.cs new file mode 100644 index 000000000..a97e30299 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/DynamicBuilderHelper.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public static class DynamicBuilderHelper + { + public static Type CreateDynamicClass(string className, List properties, TypeAttributes attributes = TypeAttributes.Public, List classCustomAttributes = null, Type baseType = null, Type[] interfaces = null) + { + TypeBuilder typeBuilder = EmitTool.CreateTypeBuilder(className, attributes, baseType, interfaces); + + if (classCustomAttributes != null) + { + foreach (var attributeBuilder in classCustomAttributes) + { + typeBuilder.SetCustomAttribute(attributeBuilder); + } + } + + foreach (PropertyMetadata property in properties) + { + EmitTool.CreateProperty(typeBuilder, property.Name, property.Type, property.CustomAttributes); + } + + Type dynamicType = typeBuilder.CreateTypeInfo().AsType(); + + return dynamicType; + } + } +} diff --git a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/EmitTool.cs b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/EmitTool.cs new file mode 100644 index 000000000..44e03a269 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/EmitTool.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + internal class EmitTool + { + internal static ModuleBuilder CreateModuleBuilder() + { + AssemblyBuilder assemblyBuilder = CreateAssembly(); + ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule"); + return moduleBuilder; + } + + internal static AssemblyBuilder CreateAssembly() + { + AssemblyName assemblyName = new AssemblyName($"DynamicAssembly_{Guid.NewGuid():N}"); + AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect); + return assemblyBuilder; + } + + internal static TypeBuilder CreateTypeBuilder(string className, TypeAttributes attributes, Type baseType, Type[] interfaces) + { + ModuleBuilder moduleBuilder = EmitTool.CreateModuleBuilder(); + TypeBuilder typeBuilder = moduleBuilder.DefineType(className, attributes, baseType, interfaces); + return typeBuilder; + } + internal static PropertyBuilder CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType, IEnumerable propertyCustomAttributes = null) + { + FieldBuilder fieldBuilder = typeBuilder.DefineField($"_{propertyName}", propertyType, FieldAttributes.Private); + + PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); + + MethodBuilder getterBuilder = typeBuilder.DefineMethod($"get_{propertyName}", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); + ILGenerator getterIL = getterBuilder.GetILGenerator(); + getterIL.Emit(OpCodes.Ldarg_0); + getterIL.Emit(OpCodes.Ldfld, fieldBuilder); + getterIL.Emit(OpCodes.Ret); + + MethodBuilder setterBuilder = typeBuilder.DefineMethod($"set_{propertyName}", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType }); + ILGenerator setterIL = setterBuilder.GetILGenerator(); + setterIL.Emit(OpCodes.Ldarg_0); + setterIL.Emit(OpCodes.Ldarg_1); + setterIL.Emit(OpCodes.Stfld, fieldBuilder); + setterIL.Emit(OpCodes.Ret); + + propertyBuilder.SetGetMethod(getterBuilder); + propertyBuilder.SetSetMethod(setterBuilder); + + if (propertyCustomAttributes != null) + { + foreach (var attributeBuilder in propertyCustomAttributes) + { + propertyBuilder.SetCustomAttribute(attributeBuilder); + } + } + + return propertyBuilder; + } + + } +} diff --git a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Helper.cs b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Helper.cs new file mode 100644 index 000000000..c3f215c8f --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Helper.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class DynamicBuilder + { + private CustomAttributeBuilder GetEntity(SugarTable sugarTable) + { + Type attributeType = typeof(SugarTable); + ConstructorInfo attributeCtor = attributeType.GetConstructor(new Type[] { typeof(string) }); + CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(attributeCtor, new object[] { "" }, + new PropertyInfo[] { + attributeType.GetProperty(nameof(SugarTable.TableName)), + attributeType.GetProperty(nameof(SugarTable.TableDescription)) , + attributeType.GetProperty(nameof(SugarTable.IsDisabledUpdateAll)) , + attributeType.GetProperty(nameof(SugarTable.IsDisabledDelete)) + } + , new object[] { + sugarTable.TableName, + sugarTable.TableDescription , + sugarTable.IsDisabledUpdateAll, + sugarTable.IsDisabledDelete + }); + return attributeBuilder; + } + private CustomAttributeBuilder GetProperty(SugarColumn sugarTable) + { + Type attributeType = typeof(SugarColumn); + ConstructorInfo attributeCtor = attributeType.GetConstructor(new Type[] { }); + CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(attributeCtor, new object[] { }, + new PropertyInfo[] { + attributeType.GetProperty(nameof(SugarColumn.IsPrimaryKey)), + attributeType.GetProperty(nameof(SugarColumn.IsIdentity)), + attributeType.GetProperty(nameof(SugarColumn.DefaultValue)), + attributeType.GetProperty(nameof(SugarColumn.Length)), + attributeType.GetProperty(nameof(SugarColumn.DecimalDigits)), + attributeType.GetProperty(nameof(SugarColumn.ColumnDataType)), + attributeType.GetProperty(nameof(SugarColumn.IsNullable)), + attributeType.GetProperty(nameof(SugarColumn.ColumnDescription)), + attributeType.GetProperty(nameof(SugarColumn.OracleSequenceName)), + attributeType.GetProperty(nameof(SugarColumn.IsIgnore)), + attributeType.GetProperty(nameof(SugarColumn.IsJson)), + attributeType.GetProperty(nameof(SugarColumn.IsOnlyIgnoreInsert)), + attributeType.GetProperty(nameof(SugarColumn.IsOnlyIgnoreUpdate)), + attributeType.GetProperty(nameof(SugarColumn.OldColumnName)), + attributeType.GetProperty(nameof(SugarColumn.SqlParameterDbType)), + attributeType.GetProperty(nameof(SugarColumn.SqlParameterSize)), + attributeType.GetProperty(nameof(SugarColumn.IsArray)) + } + , new object[] { + sugarTable.IsPrimaryKey, + sugarTable.IsIdentity, + sugarTable.DefaultValue, + sugarTable.Length, + sugarTable.DecimalDigits, + sugarTable.ColumnDataType, + sugarTable.IsNullable, + sugarTable.ColumnDescription, + sugarTable.OracleSequenceName, + sugarTable.IsIgnore, + sugarTable.IsJson, + sugarTable.IsOnlyIgnoreInsert, + sugarTable.IsOnlyIgnoreUpdate, + sugarTable.OldColumnName, + sugarTable.SqlParameterDbType, + sugarTable.SqlParameterSize, + sugarTable.IsArray + }); + return attributeBuilder; + } + } +} diff --git a/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Master.cs b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Master.cs new file mode 100644 index 000000000..f5a158dfb --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Master.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class DynamicBuilder + { + List propertyAttr = new List(); + List entityAttr = new List(); + string entityName { get; set; } + Type baseType = null; + Type[] interfaces = null; + private SqlSugarProvider context; + + public DynamicBuilder(SqlSugarProvider context) + { + this.context = context; + } + + public DynamicBuilder CreateClass(string entityName, SugarTable table, Type baseType = null, Type[] interfaces = null) + { + this.baseType = baseType; + this.interfaces = interfaces; + this.entityName = entityName; + this.entityAttr = new List() { GetEntity(table) }; + return this; + } + public DynamicBuilder CreateProperty(string propertyName, Type properyType, SugarColumn table) + { + PropertyMetadata addItem = new PropertyMetadata(); + addItem.Name = propertyName; + addItem.Type = properyType; + addItem.CustomAttributes = new List() { GetProperty(table) }; + this.propertyAttr.Add(addItem); + return this; + } + + public Type BuilderType() + { + return DynamicBuilderHelper.CreateDynamicClass(this.entityName, propertyAttr, TypeAttributes.Public, this.entityAttr, baseType, interfaces); + } + } +} diff --git a/Src/Asp.Net/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs b/Src/Asp.Net/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs index 8a41be8fe..8116f7b61 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs @@ -155,6 +155,10 @@ namespace SqlSugar { return ""; } + if (entityType.Assembly.IsDynamic&& entityType.Assembly.FullName.StartsWith("Dynamic")) + { + return null; + } var path = entityType.Assembly.Location; if (string.IsNullOrEmpty(path)) { diff --git a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarProvider.cs index e1527135b..46b28d59e 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarProvider.cs @@ -1624,6 +1624,10 @@ namespace SqlSugar #endregion #region Other + public DynamicBuilder DynamicBuilder() + { + return new DynamicBuilder(this.Context); + } public void Tracking(T data) where T : class, new() { if (data != null) diff --git a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarScopeProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarScopeProvider.cs index 643169806..4d86f8228 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarScopeProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/SugarProvider/SqlSugarScopeProvider.cs @@ -786,6 +786,10 @@ namespace SqlSugar { return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig)); } + public DynamicBuilder DynamicBuilder() + { + return ScopedContext.DynamicBuilder(); + } public void Tracking(T data) where T : class, new() { ScopedContext.Tracking(data); diff --git a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs index b7c44cfe5..966973dc5 100644 --- a/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs +++ b/Src/Asp.Net/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs @@ -8,7 +8,7 @@ namespace SqlSugar { [AttributeUsage(AttributeTargets.Class, Inherited = true)] public class SugarTable : Attribute { - private SugarTable() { } + public SugarTable() { } public string TableName { get; set; } public string TableDescription { get; set; } public bool IsDisabledDelete { get; set; } diff --git a/Src/Asp.Net/SqlSugar/Entities/PropertyMetadata.cs b/Src/Asp.Net/SqlSugar/Entities/PropertyMetadata.cs new file mode 100644 index 000000000..530e99a53 --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Entities/PropertyMetadata.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class PropertyMetadata + { + public string Name { get; set; } + public Type Type { get; set; } + public IEnumerable CustomAttributes { get; set; } + } +} diff --git a/Src/Asp.Net/SqlSugar/Interface/ISqlSugarClient.cs b/Src/Asp.Net/SqlSugar/Interface/ISqlSugarClient.cs index 1abe5f9fc..1baacb819 100644 --- a/Src/Asp.Net/SqlSugar/Interface/ISqlSugarClient.cs +++ b/Src/Asp.Net/SqlSugar/Interface/ISqlSugarClient.cs @@ -45,6 +45,7 @@ namespace SqlSugar #endregion #region Other methods + DynamicBuilder DynamicBuilder(); void Tracking(T data) where T : class, new(); void Tracking(List data) where T : class, new(); SqlSugarClient CopyNew(); diff --git a/Src/Asp.Net/SqlSugar/SqlSugar.csproj b/Src/Asp.Net/SqlSugar/SqlSugar.csproj index b5e574926..740d6cc04 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugar.csproj +++ b/Src/Asp.Net/SqlSugar/SqlSugar.csproj @@ -88,6 +88,9 @@ + + + @@ -140,6 +143,7 @@ + @@ -424,6 +428,7 @@ + diff --git a/Src/Asp.Net/SqlSugar/SqlSugarClient.cs b/Src/Asp.Net/SqlSugar/SqlSugarClient.cs index b2699ecc0..4ffffd753 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugarClient.cs +++ b/Src/Asp.Net/SqlSugar/SqlSugarClient.cs @@ -1156,6 +1156,10 @@ namespace SqlSugar #endregion #region Other method + public DynamicBuilder DynamicBuilder() + { + return this.Context.DynamicBuilder(); + } public void Tracking(T data) where T : class, new() { this.Context.Tracking(data); diff --git a/Src/Asp.Net/SqlSugar/SqlSugarScope.cs b/Src/Asp.Net/SqlSugar/SqlSugarScope.cs index 9b85db903..2ee4e1460 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugarScope.cs +++ b/Src/Asp.Net/SqlSugar/SqlSugarScope.cs @@ -835,6 +835,10 @@ namespace SqlSugar { return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig)); } + public DynamicBuilder DynamicBuilder() + { + return ScopedContext.DynamicBuilder(); + } public void Tracking(T data) where T : class, new() { ScopedContext.Tracking(data);