Synchronization code

This commit is contained in:
sunkaixuan
2023-03-21 15:58:43 +08:00
parent 19f940b784
commit b8ebf07460
13 changed files with 340 additions and 1 deletions

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace SqlSugar
{
public class DynamicProperyBuilder
{
private bool IsCache = false;
public static DynamicProperyBuilder CopyNew()
{
return new DynamicProperyBuilder();
}
public DynamicBuilder baseBuilder;
public DynamicProperyBuilder CreateProperty(string propertyName, Type properyType, SugarColumn table)
{
PropertyMetadata addItem = new PropertyMetadata();
addItem.Name = propertyName;
addItem.Type = properyType;
addItem.CustomAttributes = new List<CustomAttributeBuilder>() { baseBuilder.GetProperty(table) };
baseBuilder.propertyAttr.Add(addItem);
return this;
}
public DynamicProperyBuilder WithCache(bool isCache=true)
{
IsCache = isCache;
return this;
}
public Type BuilderType()
{
if (IsCache)
{
var key = baseBuilder.entityName + string.Join("_", baseBuilder.propertyAttr.Select(it => it.Name + it.Type.Name));
return new ReflectionInoCacheService().GetOrCreate(key,() =>
{
var result = DynamicBuilderHelper.CreateDynamicClass(baseBuilder.entityName, baseBuilder.propertyAttr, TypeAttributes.Public, baseBuilder.entityAttr, baseBuilder.baseType, baseBuilder.interfaces);
return result;
});
}
else
{
var result = DynamicBuilderHelper.CreateDynamicClass(baseBuilder.entityName, baseBuilder.propertyAttr, TypeAttributes.Public, baseBuilder.entityAttr, baseBuilder.baseType, baseBuilder.interfaces);
return result;
}
}
}
}

View 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;
}
}
}

View 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
{
internal 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;
}
internal 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;
}
}
}

View 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;
using System.Security.AccessControl;
namespace SqlSugar
{
public partial class DynamicBuilder
{
internal List<PropertyMetadata> propertyAttr = new List<PropertyMetadata>();
internal List<CustomAttributeBuilder> entityAttr = new List<CustomAttributeBuilder>();
internal string entityName { get; set; }
internal Type baseType = null;
internal Type[] interfaces = null;
internal SqlSugarProvider context;
public DynamicBuilder(SqlSugarProvider context)
{
this.context = context;
}
public DynamicProperyBuilder 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 new DynamicProperyBuilder() { baseBuilder=this};
}
public object CreateObjectByType(Type type, Dictionary<string, object> dict)
{
// 创建一个默认的空对象
object obj = Activator.CreateInstance(type);
// 遍历字典中的每个 key-value 对
foreach (KeyValuePair<string, object> pair in dict)
{
// 获取对象中的属性
PropertyInfo propertyInfo = type.GetProperty(pair.Key);
if (propertyInfo != null)
{
// 如果找到了该属性,则将其值设置为字典中对应的值
propertyInfo.SetValue(obj, Convert.ChangeType(pair.Value, propertyInfo.PropertyType));
}
}
// 返回创建的对象
return obj;
}
public List<object> CreateObjectByType(Type type, List<Dictionary<string, object>> dictList)
{
List<object> result = new List<object>();
foreach (var item in dictList)
{
result.Add(CreateObjectByType(type, item));
}
return result;
}
}
}

View File

@@ -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))
{

View File

@@ -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)

View File

@@ -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);

View File

@@ -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; }

View 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; }
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);