mirror of
https://gitee.com/dotnetchina/SqlSugar.git
synced 2025-08-23 22:11:36 +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 "";
|
||||
}
|
||||
if (entityType.Assembly.IsDynamic&& entityType.Assembly.FullName.StartsWith("Dynamic"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var path = entityType.Assembly.Location;
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
|
@ -1624,6 +1624,10 @@ namespace SqlSugar
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
public DynamicBuilder DynamicBuilder()
|
||||
{
|
||||
return new DynamicBuilder(this.Context);
|
||||
}
|
||||
public void Tracking<T>(T data) where T : class, new()
|
||||
{
|
||||
if (data != null)
|
||||
|
@ -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>(T data) where T : class, new()
|
||||
{
|
||||
ScopedContext.Tracking(data);
|
||||
|
@ -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; }
|
||||
|
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
|
||||
|
||||
#region Other methods
|
||||
DynamicBuilder DynamicBuilder();
|
||||
void Tracking<T>(T data) where T : class, new();
|
||||
void Tracking<T>(List<T> data) where T : class, new();
|
||||
SqlSugarClient CopyNew();
|
||||
|
@ -88,6 +88,9 @@
|
||||
<Compile Include="Abstract\DeleteProvider\LogicDeleteProvider.cs" />
|
||||
<Compile Include="Abstract\DeleteProvider\SplitTableDeleteByObjectProvider.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\EntityMaintenance.cs" />
|
||||
<Compile Include="Abstract\ExecuteNavProvider\NavContext.cs" />
|
||||
@ -140,6 +143,7 @@
|
||||
<Compile Include="Abstract\UpdateProvider\UpdateMethodInfo.cs" />
|
||||
<Compile Include="Abstract\UpdateProvider\UpdateableHelper.cs" />
|
||||
<Compile Include="Abstract\UpdateProvider\SplitTableUpdateByObjectProvider.cs" />
|
||||
<Compile Include="Entities\PropertyMetadata.cs" />
|
||||
<Compile Include="Entities\DbFastestProperties.cs" />
|
||||
<Compile Include="Entities\DefaultCustom.cs" />
|
||||
<Compile Include="Entities\DeleteNavOptions.cs" />
|
||||
@ -424,6 +428,7 @@
|
||||
<Compile Include="Abstract\SugarProvider\SqlSugarScopeProvider.cs" />
|
||||
<Compile Include="Utilities\CallContext.cs" />
|
||||
<Compile Include="Utilities\CallContextAsync.cs" />
|
||||
<Compile Include="Abstract\DynamicBuilder\DynamicBuilderHelper.cs" />
|
||||
<Compile Include="Utilities\FastCopy.cs" />
|
||||
<Compile Include="Utilities\ExpressionBuilderHelper.cs" />
|
||||
<Compile Include="Utilities\CommonExtensions.cs" />
|
||||
|
@ -1156,6 +1156,10 @@ namespace SqlSugar
|
||||
#endregion
|
||||
|
||||
#region Other method
|
||||
public DynamicBuilder DynamicBuilder()
|
||||
{
|
||||
return this.Context.DynamicBuilder();
|
||||
}
|
||||
public void Tracking<T>(T data) where T : class, new()
|
||||
{
|
||||
this.Context.Tracking(data);
|
||||
|
@ -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>(T data) where T : class, new()
|
||||
{
|
||||
ScopedContext.Tracking(data);
|
||||
|
Loading…
Reference in New Issue
Block a user