mirror of
https://gitee.com/dotnetchina/SqlSugar.git
synced 2025-08-24 07:22:57 +08:00
Supports dynamic class creation
This commit is contained in:
parent
6f3d45230b
commit
593708fcff
@ -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<PropertyMetadata> properties, TypeAttributes attributes = TypeAttributes.Public, List<CustomAttributeBuilder> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/EmitTool.cs
Normal file
67
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/EmitTool.cs
Normal file
@ -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<CustomAttributeBuilder> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
78
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Helper.cs
Normal file
78
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Helper.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Master.cs
Normal file
48
Src/Asp.Net/SqlSugar/Abstract/DynamicBuilder/Master.cs
Normal file
@ -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<PropertyMetadata> propertyAttr = new List<PropertyMetadata>();
|
||||||
|
List<CustomAttributeBuilder> entityAttr = new List<CustomAttributeBuilder>();
|
||||||
|
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<CustomAttributeBuilder>() { 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<CustomAttributeBuilder>() { GetProperty(table) };
|
||||||
|
this.propertyAttr.Add(addItem);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type BuilderType()
|
||||||
|
{
|
||||||
|
return DynamicBuilderHelper.CreateDynamicClass(this.entityName, propertyAttr, TypeAttributes.Public, this.entityAttr, baseType, interfaces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -155,6 +155,10 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
if (entityType.Assembly.IsDynamic&& entityType.Assembly.FullName.StartsWith("Dynamic"))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var path = entityType.Assembly.Location;
|
var path = entityType.Assembly.Location;
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
|
@ -1624,6 +1624,10 @@ namespace SqlSugar
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
|
public DynamicBuilder DynamicBuilder()
|
||||||
|
{
|
||||||
|
return new DynamicBuilder(this.Context);
|
||||||
|
}
|
||||||
public void Tracking<T>(T data) where T : class, new()
|
public void Tracking<T>(T data) where T : class, new()
|
||||||
{
|
{
|
||||||
if (data != null)
|
if (data != null)
|
||||||
|
@ -786,6 +786,10 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig));
|
return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig));
|
||||||
}
|
}
|
||||||
|
public DynamicBuilder DynamicBuilder()
|
||||||
|
{
|
||||||
|
return ScopedContext.DynamicBuilder();
|
||||||
|
}
|
||||||
public void Tracking<T>(T data) where T : class, new()
|
public void Tracking<T>(T data) where T : class, new()
|
||||||
{
|
{
|
||||||
ScopedContext.Tracking(data);
|
ScopedContext.Tracking(data);
|
||||||
|
@ -8,7 +8,7 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
|
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
|
||||||
public class SugarTable : Attribute {
|
public class SugarTable : Attribute {
|
||||||
private SugarTable() { }
|
public SugarTable() { }
|
||||||
public string TableName { get; set; }
|
public string TableName { get; set; }
|
||||||
public string TableDescription { get; set; }
|
public string TableDescription { get; set; }
|
||||||
public bool IsDisabledDelete { get; set; }
|
public bool IsDisabledDelete { get; set; }
|
||||||
|
16
Src/Asp.Net/SqlSugar/Entities/PropertyMetadata.cs
Normal file
16
Src/Asp.Net/SqlSugar/Entities/PropertyMetadata.cs
Normal file
@ -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<CustomAttributeBuilder> CustomAttributes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,7 @@ namespace SqlSugar
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other methods
|
#region Other methods
|
||||||
|
DynamicBuilder DynamicBuilder();
|
||||||
void Tracking<T>(T data) where T : class, new();
|
void Tracking<T>(T data) where T : class, new();
|
||||||
void Tracking<T>(List<T> data) where T : class, new();
|
void Tracking<T>(List<T> data) where T : class, new();
|
||||||
SqlSugarClient CopyNew();
|
SqlSugarClient CopyNew();
|
||||||
|
@ -88,6 +88,9 @@
|
|||||||
<Compile Include="Abstract\DeleteProvider\LogicDeleteProvider.cs" />
|
<Compile Include="Abstract\DeleteProvider\LogicDeleteProvider.cs" />
|
||||||
<Compile Include="Abstract\DeleteProvider\SplitTableDeleteByObjectProvider.cs" />
|
<Compile Include="Abstract\DeleteProvider\SplitTableDeleteByObjectProvider.cs" />
|
||||||
<Compile Include="Abstract\DeleteProvider\SplitTableDeleteProvider.cs" />
|
<Compile Include="Abstract\DeleteProvider\SplitTableDeleteProvider.cs" />
|
||||||
|
<Compile Include="Abstract\DynamicBuilder\Helper.cs" />
|
||||||
|
<Compile Include="Abstract\DynamicBuilder\EmitTool.cs" />
|
||||||
|
<Compile Include="Abstract\DynamicBuilder\Master.cs" />
|
||||||
<Compile Include="Abstract\EntityMaintenance\EntityColumnExtension.cs" />
|
<Compile Include="Abstract\EntityMaintenance\EntityColumnExtension.cs" />
|
||||||
<Compile Include="Abstract\EntityMaintenance\EntityMaintenance.cs" />
|
<Compile Include="Abstract\EntityMaintenance\EntityMaintenance.cs" />
|
||||||
<Compile Include="Abstract\ExecuteNavProvider\NavContext.cs" />
|
<Compile Include="Abstract\ExecuteNavProvider\NavContext.cs" />
|
||||||
@ -140,6 +143,7 @@
|
|||||||
<Compile Include="Abstract\UpdateProvider\UpdateMethodInfo.cs" />
|
<Compile Include="Abstract\UpdateProvider\UpdateMethodInfo.cs" />
|
||||||
<Compile Include="Abstract\UpdateProvider\UpdateableHelper.cs" />
|
<Compile Include="Abstract\UpdateProvider\UpdateableHelper.cs" />
|
||||||
<Compile Include="Abstract\UpdateProvider\SplitTableUpdateByObjectProvider.cs" />
|
<Compile Include="Abstract\UpdateProvider\SplitTableUpdateByObjectProvider.cs" />
|
||||||
|
<Compile Include="Entities\PropertyMetadata.cs" />
|
||||||
<Compile Include="Entities\DbFastestProperties.cs" />
|
<Compile Include="Entities\DbFastestProperties.cs" />
|
||||||
<Compile Include="Entities\DefaultCustom.cs" />
|
<Compile Include="Entities\DefaultCustom.cs" />
|
||||||
<Compile Include="Entities\DeleteNavOptions.cs" />
|
<Compile Include="Entities\DeleteNavOptions.cs" />
|
||||||
@ -424,6 +428,7 @@
|
|||||||
<Compile Include="Abstract\SugarProvider\SqlSugarScopeProvider.cs" />
|
<Compile Include="Abstract\SugarProvider\SqlSugarScopeProvider.cs" />
|
||||||
<Compile Include="Utilities\CallContext.cs" />
|
<Compile Include="Utilities\CallContext.cs" />
|
||||||
<Compile Include="Utilities\CallContextAsync.cs" />
|
<Compile Include="Utilities\CallContextAsync.cs" />
|
||||||
|
<Compile Include="Abstract\DynamicBuilder\DynamicBuilderHelper.cs" />
|
||||||
<Compile Include="Utilities\FastCopy.cs" />
|
<Compile Include="Utilities\FastCopy.cs" />
|
||||||
<Compile Include="Utilities\ExpressionBuilderHelper.cs" />
|
<Compile Include="Utilities\ExpressionBuilderHelper.cs" />
|
||||||
<Compile Include="Utilities\CommonExtensions.cs" />
|
<Compile Include="Utilities\CommonExtensions.cs" />
|
||||||
|
@ -1156,6 +1156,10 @@ namespace SqlSugar
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other method
|
#region Other method
|
||||||
|
public DynamicBuilder DynamicBuilder()
|
||||||
|
{
|
||||||
|
return this.Context.DynamicBuilder();
|
||||||
|
}
|
||||||
public void Tracking<T>(T data) where T : class, new()
|
public void Tracking<T>(T data) where T : class, new()
|
||||||
{
|
{
|
||||||
this.Context.Tracking(data);
|
this.Context.Tracking(data);
|
||||||
|
@ -835,6 +835,10 @@ namespace SqlSugar
|
|||||||
{
|
{
|
||||||
return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig));
|
return new SqlSugarClient(UtilMethods.CopyConfig(this.Ado.Context.CurrentConnectionConfig));
|
||||||
}
|
}
|
||||||
|
public DynamicBuilder DynamicBuilder()
|
||||||
|
{
|
||||||
|
return ScopedContext.DynamicBuilder();
|
||||||
|
}
|
||||||
public void Tracking<T>(T data) where T : class, new()
|
public void Tracking<T>(T data) where T : class, new()
|
||||||
{
|
{
|
||||||
ScopedContext.Tracking(data);
|
ScopedContext.Tracking(data);
|
||||||
|
Loading…
Reference in New Issue
Block a user