From 91da92b11fdbfbf156a688b5961a8904e161f370 Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Mon, 24 Apr 2023 13:17:39 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=AE=9E=E4=BD=93API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/CodeFirstExtensions.cs | 35 ++++ FreeSql/Internal/DynamicCompileBuilder.cs | 233 ++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 FreeSql/Extensions/CodeFirstExtensions.cs create mode 100644 FreeSql/Internal/DynamicCompileBuilder.cs diff --git a/FreeSql/Extensions/CodeFirstExtensions.cs b/FreeSql/Extensions/CodeFirstExtensions.cs new file mode 100644 index 00000000..f70f3bd7 --- /dev/null +++ b/FreeSql/Extensions/CodeFirstExtensions.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; +using FreeSql.Internal; + +namespace FreeSql.Extensions +{ +#if net40 || NETSTANDARD2_0 + //不支持 +#else + public static class CodeFirstExtensions + { + /// + /// 动态创建Class Type + /// + /// + public static DynamicCompileBuilder DynamicBuilder(this ICodeFirst codeFirst) + { + return new DynamicCompileBuilder(); + } + + /// + /// 根据动态构建的Class生成实例并进行属性赋值 + /// + /// + /// + /// + public static object CreateObjectByType(this ICodeFirst codeFirst, Type type, + Dictionary porpertys) + { + return DynamicCompileBuilder.CreateObjectByType(type, porpertys); + } + } +#endif +} diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs new file mode 100644 index 00000000..16673161 --- /dev/null +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -0,0 +1,233 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Reflection.Emit; + +namespace FreeSql.Internal +{ +#if net40 || NETSTANDARD2_0 + +#else + public class DynamicCompileBuilder + { + private string _className = string.Empty; + private TableAttribute _tableAttribute = null; + private List _properties = new List(); + + /// + /// 配置Class + /// + /// 类名 + /// 类标记的特性[Table(Name = "xxx")] + /// + public DynamicCompileBuilder SetClass(string className, TableAttribute tableAttribute) + { + _className = className; + _tableAttribute = tableAttribute; + return this; + } + + /// + /// 配置属性 + /// + /// 属性名称 + /// 属性类型 + /// 属性标记的特性[Column(IsPrimary = true)] + /// + public DynamicCompileBuilder SetProperty(string propertyName, Type propertyType, ColumnAttribute columnAttribute) + { + _properties.Add(new DynamicPropertyInfo() + { + PropertyName = propertyName, + PropertyType = propertyType, + ColumnAttribute = columnAttribute + }); + return this; + } + + private void SetTableAttribute(ref TypeBuilder typeBuilder) + { + var classCtorInfo = typeof(TableAttribute).GetConstructor(new Type[] { }); + var propertyInfos = typeof(TableAttribute).GetProperties().Where(p => p.CanWrite == true).ToArray(); + if (_tableAttribute == null) + { + return; + } + + var propertyValues = new ArrayList(); + foreach (var propertyInfo in _tableAttribute.GetType().GetProperties().Where(p => p.CanWrite == true)) + { + propertyValues.Add(propertyInfo.GetValue(_tableAttribute)); + } + + var customAttributeBuilder = + new CustomAttributeBuilder(classCtorInfo, new object[0], propertyInfos, propertyValues.ToArray()); + typeBuilder.SetCustomAttribute(customAttributeBuilder); + } + + private void SetPropertys(ref TypeBuilder typeBuilder) + { + foreach (var pinfo in _properties) + { + var propertyName = pinfo.PropertyName; + var propertyType = pinfo?.PropertyType ?? typeof(object); + //设置字段 + var field = typeBuilder.DefineField($"_{FirstCharToLower(propertyName)}", propertyType, + FieldAttributes.Private); + var firstCharToUpper = FirstCharToUpper(propertyName); + //设置属性方法 + var methodGet = typeBuilder.DefineMethod($"Get{firstCharToUpper}", MethodAttributes.Public, + propertyType, null); + var methodSet = typeBuilder.DefineMethod($"Set{firstCharToUpper}", MethodAttributes.Public, null, + new Type[] { propertyType }); + + var ilOfGet = methodGet.GetILGenerator(); + ilOfGet.Emit(OpCodes.Ldarg_0); + ilOfGet.Emit(OpCodes.Ldfld, field); + ilOfGet.Emit(OpCodes.Ret); + + var ilOfSet = methodSet.GetILGenerator(); + ilOfSet.Emit(OpCodes.Ldarg_0); + ilOfSet.Emit(OpCodes.Ldarg_1); + ilOfSet.Emit(OpCodes.Stfld, field); + ilOfSet.Emit(OpCodes.Ret); + + //设置属性 + var propertyBuilder = + typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); + propertyBuilder.SetGetMethod(methodGet); + propertyBuilder.SetSetMethod(methodSet); + + //设置特性 + SetColumnAttribute(ref propertyBuilder, pinfo?.ColumnAttribute); + } + } + + private void SetColumnAttribute(ref PropertyBuilder propertyBuilder, ColumnAttribute columnAttribute = null) + { + if (columnAttribute == null) + return; + + var propertyValues = new ArrayList(); + foreach (var propertyInfo in columnAttribute.GetType().GetProperties().Where(p => p.CanWrite == true)) + { + propertyValues.Add(propertyInfo.GetValue(columnAttribute)); + } + + var propertyInfos = typeof(ColumnAttribute).GetProperties().Where(p => p.CanWrite == true).ToArray(); + var constructor = typeof(ColumnAttribute).GetConstructor(new Type[] { }); + var customAttributeBuilder = + new CustomAttributeBuilder(constructor, new object[0], propertyInfos, propertyValues.ToArray()); + propertyBuilder.SetCustomAttribute(customAttributeBuilder); + } + + /// + /// Emit动态创建出Class - Type + /// + /// + public Type Build() + { + //初始化AssemblyName的一个实例 + var assemblyName = new AssemblyName("FreeSql.DynamicCompileBuilder"); + //设置程序集的名称 + var defineDynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); + //动态在程序集内创建一个模块 + var defineDynamicModule = defineDynamicAssembly.DefineDynamicModule("FreeSql.DynamicCompileBuilder.Dynamics"); + //动态的在模块内创建一个类 + var typeBuilder = defineDynamicModule.DefineType(_className, TypeAttributes.Public | TypeAttributes.Class); + + //设置TableAttribute + SetTableAttribute(ref typeBuilder); + + //设置属性 + SetPropertys(ref typeBuilder); + + //创建类的Type对象 + return typeBuilder.CreateType(); + } + + //委托缓存 + private static ConcurrentDictionary + _delegateCache = new ConcurrentDictionary(); + + //设置动态对象的属性值 + public static object CreateObjectByType(Type type, Dictionary porpertys) + { + if (type == null) + return null; + object istance = Activator.CreateInstance(type); + if (istance == null) + return null; + //根据字典中的key确定缓存 + var cacheKey = string.Join("-", porpertys.Keys.OrderBy(s => s)); + var dynamicDelegate = _delegateCache.GetOrAdd(cacheKey, key => + { + //表达式目录树构建委托 + var typeParam = Expression.Parameter(type); + var dicParamType = typeof(Dictionary); + var dicParam = Expression.Parameter(dicParamType); + var exps = new List(); + var tempRef = Expression.Variable(typeof(object)); + foreach (var pinfo in porpertys) + { + var propertyInfo = type.GetProperty(pinfo.Key); + if (propertyInfo == null) + continue; + var propertyName = Expression.Constant(pinfo.Key, typeof(string)); + exps.Add(Expression.Call(dicParam, dicParamType.GetMethod("TryGetValue"), propertyName, tempRef)); + exps.Add(Expression.Assign(Expression.MakeMemberAccess(typeParam, propertyInfo), + Expression.Convert(tempRef, propertyInfo.PropertyType))); + exps.Add(Expression.Assign(tempRef, Expression.Default(typeof(object)))); + } + + var returnTarget = Expression.Label(type); + exps.Add(Expression.Return(returnTarget, typeParam)); + exps.Add(Expression.Label(returnTarget, Expression.Default(type))); + var block = Expression.Block(new[] { tempRef }, exps); + var @delegate = Expression.Lambda(block, typeParam, dicParam).Compile(); + return @delegate; + }); + var dynamicInvoke = dynamicDelegate.DynamicInvoke(istance, porpertys); + return dynamicInvoke; + } + + /// + /// 首字母小写 + /// + /// + /// + private string FirstCharToLower(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + string str = input.First().ToString().ToLower() + input.Substring(1); + return str; + } + + /// + /// 首字母大写 + /// + /// + /// + private string FirstCharToUpper(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + string str = input.First().ToString().ToUpper() + input.Substring(1); + return str; + } + } +#endif + internal class DynamicPropertyInfo + { + public string PropertyName { get; set; } = string.Empty; + public Type PropertyType { get; set; } = null; + public ColumnAttribute ColumnAttribute { get; set; } = null; + } +} + From 43a8e8bee9836ad5d12a6bcdc9696cd7eb0202fc Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Mon, 24 Apr 2023 14:28:45 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=AE=9E=E4=BD=93API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/CodeFirstExtensions.cs | 7 ++-- FreeSql/FreeSql.xml | 51 +++++++++++++++++++++++ FreeSql/Internal/DynamicCompileBuilder.cs | 33 ++++++++------- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/FreeSql/Extensions/CodeFirstExtensions.cs b/FreeSql/Extensions/CodeFirstExtensions.cs index f70f3bd7..e7f14b58 100644 --- a/FreeSql/Extensions/CodeFirstExtensions.cs +++ b/FreeSql/Extensions/CodeFirstExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using FreeSql.DataAnnotations; using FreeSql.Internal; namespace FreeSql.Extensions @@ -14,9 +15,9 @@ namespace FreeSql.Extensions /// 动态创建Class Type /// /// - public static DynamicCompileBuilder DynamicBuilder(this ICodeFirst codeFirst) + public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, TableAttribute tableAttribute) { - return new DynamicCompileBuilder(); + return new DynamicCompileBuilder().SetClass(className, tableAttribute); } /// @@ -25,7 +26,7 @@ namespace FreeSql.Extensions /// /// /// - public static object CreateObjectByType(this ICodeFirst codeFirst, Type type, + public static object CreateDynamicEntityInstance(this Type type, Dictionary porpertys) { return DynamicCompileBuilder.CreateObjectByType(type, porpertys); diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 5323d7da..fef3c125 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1073,6 +1073,20 @@ + + + 动态创建Class Type + + + + + + 根据动态构建的Class生成实例并进行属性赋值 + + + + + 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null @@ -4248,6 +4262,43 @@ Dict:key=属性名,value=注释 + + + 配置Class + + 类名 + 类标记的特性[Table(Name = "xxx")] + + + + + 配置属性 + + 属性名称 + 属性类型 + 属性标记的特性[Column(IsPrimary = true)] + + + + + Emit动态创建出Class - Type + + + + + + 首字母小写 + + + + + + + 首字母大写 + + + + 更新实体的元数据 diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs index 16673161..99939f16 100644 --- a/FreeSql/Internal/DynamicCompileBuilder.cs +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -11,7 +11,7 @@ using System.Reflection.Emit; namespace FreeSql.Internal { #if net40 || NETSTANDARD2_0 - + #else public class DynamicCompileBuilder { @@ -37,15 +37,15 @@ namespace FreeSql.Internal /// /// 属性名称 /// 属性类型 - /// 属性标记的特性[Column(IsPrimary = true)] + /// 属性标记的特性[Column(IsPrimary = true)] /// - public DynamicCompileBuilder SetProperty(string propertyName, Type propertyType, ColumnAttribute columnAttribute) + public DynamicCompileBuilder Property(string propertyName, Type propertyType, params Attribute [] attributes) { _properties.Add(new DynamicPropertyInfo() { PropertyName = propertyName, - PropertyType = propertyType, - ColumnAttribute = columnAttribute + PropertyType = propertyType, + Attributes = attributes }); return this; } @@ -103,24 +103,27 @@ namespace FreeSql.Internal propertyBuilder.SetGetMethod(methodGet); propertyBuilder.SetSetMethod(methodSet); - //设置特性 - SetColumnAttribute(ref propertyBuilder, pinfo?.ColumnAttribute); + foreach (var pinfoAttribute in pinfo.Attributes) + { + //设置特性 + SetPropertyAttribute(ref propertyBuilder, pinfoAttribute); + } } } - private void SetColumnAttribute(ref PropertyBuilder propertyBuilder, ColumnAttribute columnAttribute = null) + private void SetPropertyAttribute(ref PropertyBuilder propertyBuilder, T tAttribute) { - if (columnAttribute == null) + if (tAttribute == null) return; var propertyValues = new ArrayList(); - foreach (var propertyInfo in columnAttribute.GetType().GetProperties().Where(p => p.CanWrite == true)) + foreach (var propertyInfo in tAttribute.GetType().GetProperties().Where(p => p.CanWrite == true)) { - propertyValues.Add(propertyInfo.GetValue(columnAttribute)); + propertyValues.Add(propertyInfo.GetValue(tAttribute)); } - var propertyInfos = typeof(ColumnAttribute).GetProperties().Where(p => p.CanWrite == true).ToArray(); - var constructor = typeof(ColumnAttribute).GetConstructor(new Type[] { }); + var propertyInfos = tAttribute.GetType().GetProperties().Where(p => p.CanWrite == true).ToArray(); + var constructor = tAttribute.GetType().GetConstructor(new Type[] { }); var customAttributeBuilder = new CustomAttributeBuilder(constructor, new object[0], propertyInfos, propertyValues.ToArray()); propertyBuilder.SetCustomAttribute(customAttributeBuilder); @@ -226,8 +229,8 @@ namespace FreeSql.Internal internal class DynamicPropertyInfo { public string PropertyName { get; set; } = string.Empty; - public Type PropertyType { get; set; } = null; - public ColumnAttribute ColumnAttribute { get; set; } = null; + public Type PropertyType { get; set; } + public Attribute [] Attributes { get; set; } } } From 958b6c220891b7abeca4a6f946602253e5406fae Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Mon, 24 Apr 2023 14:41:20 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E7=9B=B8=E5=85=B3=E7=9A=84API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/CodeFirstExtensions.cs | 4 ++-- FreeSql/FreeSql.xml | 2 +- FreeSql/Internal/DynamicCompileBuilder.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FreeSql/Extensions/CodeFirstExtensions.cs b/FreeSql/Extensions/CodeFirstExtensions.cs index e7f14b58..6ccf08c5 100644 --- a/FreeSql/Extensions/CodeFirstExtensions.cs +++ b/FreeSql/Extensions/CodeFirstExtensions.cs @@ -12,7 +12,7 @@ namespace FreeSql.Extensions public static class CodeFirstExtensions { /// - /// 动态创建Class Type + /// 动态构建Class Type /// /// public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, TableAttribute tableAttribute) @@ -21,7 +21,7 @@ namespace FreeSql.Extensions } /// - /// 根据动态构建的Class生成实例并进行属性赋值 + /// 根据动态构建的Class Type生成实例并进行属性赋值 /// /// /// diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index fef3c125..f8ee6bd1 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1079,7 +1079,7 @@ - + 根据动态构建的Class生成实例并进行属性赋值 diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs index 99939f16..4c93cdac 100644 --- a/FreeSql/Internal/DynamicCompileBuilder.cs +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -37,7 +37,7 @@ namespace FreeSql.Internal /// /// 属性名称 /// 属性类型 - /// 属性标记的特性[Column(IsPrimary = true)] + /// 属性标记的特性-支持多个 /// public DynamicCompileBuilder Property(string propertyName, Type propertyType, params Attribute [] attributes) { From 39feb6464631a51b3e477bb4fa67309b1636082b Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:26:18 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Type=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/TypeExtensions.cs | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 FreeSql/Extensions/TypeExtensions.cs diff --git a/FreeSql/Extensions/TypeExtensions.cs b/FreeSql/Extensions/TypeExtensions.cs new file mode 100644 index 00000000..a5b75fd8 --- /dev/null +++ b/FreeSql/Extensions/TypeExtensions.cs @@ -0,0 +1,40 @@ +using FreeSql.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace DynamicBuilder +{ +#if net40 || NETSTANDARD2_0 +#else + public static class TypeExtensions + { + /// + /// 根据动态构建的Class Type生成实例并进行属性赋值 + /// + /// + /// + /// + public static object CreateDynamicEntityInstance(this Type type, IFreeSql fsql, + Dictionary porpertys) + { + return DynamicCompileBuilder.CreateObjectByTypeByCodeFirst(fsql, type, porpertys); + } + + /// + /// 设置对象属性值 + /// + /// + /// + public static void SetPropertyValue(this Type type, IFreeSql fsql, ref object obj, string propertyName, + object propertyValue) + { + var table = fsql.CodeFirst.GetTableByEntity(obj.GetType()); + table.ColumnsByCs[propertyName].SetValue(obj, propertyValue); + } + } +#endif +} From c012c166d80b49dbf0751504455f5a82761b4d2e Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:26:39 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E8=B0=83=E6=95=B4CodeFirst=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Extensions/CodeFirstExtensions.cs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/FreeSql/Extensions/CodeFirstExtensions.cs b/FreeSql/Extensions/CodeFirstExtensions.cs index 6ccf08c5..818be04c 100644 --- a/FreeSql/Extensions/CodeFirstExtensions.cs +++ b/FreeSql/Extensions/CodeFirstExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Text; using FreeSql.DataAnnotations; using FreeSql.Internal; @@ -7,30 +8,19 @@ using FreeSql.Internal; namespace FreeSql.Extensions { #if net40 || NETSTANDARD2_0 - //不支持 #else - public static class CodeFirstExtensions + public static class CodeFirstExtensions { /// /// 动态构建Class Type /// /// - public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, TableAttribute tableAttribute) + public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, + TableAttribute tableAttribute) { return new DynamicCompileBuilder().SetClass(className, tableAttribute); } - /// - /// 根据动态构建的Class Type生成实例并进行属性赋值 - /// - /// - /// - /// - public static object CreateDynamicEntityInstance(this Type type, - Dictionary porpertys) - { - return DynamicCompileBuilder.CreateObjectByType(type, porpertys); - } } #endif -} +} \ No newline at end of file From 1753a51b427744e33bc58f53ddeb9f6a3fa0fc1f Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:27:09 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E8=B5=8B=E5=80=BC=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Internal/DynamicCompileBuilder.cs | 54 ++++++++++++++++++----- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs index 4c93cdac..c857eb74 100644 --- a/FreeSql/Internal/DynamicCompileBuilder.cs +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -7,13 +7,15 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; +using System.Security.Cryptography; +using FreeSql.Internal.Model; +using System.Text; namespace FreeSql.Internal { #if net40 || NETSTANDARD2_0 - #else - public class DynamicCompileBuilder + public class DynamicCompileBuilder { private string _className = string.Empty; private TableAttribute _tableAttribute = null; @@ -39,12 +41,12 @@ namespace FreeSql.Internal /// 属性类型 /// 属性标记的特性-支持多个 /// - public DynamicCompileBuilder Property(string propertyName, Type propertyType, params Attribute [] attributes) + public DynamicCompileBuilder Property(string propertyName, Type propertyType, params Attribute[] attributes) { _properties.Add(new DynamicPropertyInfo() { PropertyName = propertyName, - PropertyType = propertyType, + PropertyType = propertyType, Attributes = attributes }); return this; @@ -140,7 +142,8 @@ namespace FreeSql.Internal //设置程序集的名称 var defineDynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); //动态在程序集内创建一个模块 - var defineDynamicModule = defineDynamicAssembly.DefineDynamicModule("FreeSql.DynamicCompileBuilder.Dynamics"); + var defineDynamicModule = + defineDynamicAssembly.DefineDynamicModule("FreeSql.DynamicCompileBuilder.Dynamics"); //动态的在模块内创建一个类 var typeBuilder = defineDynamicModule.DefineType(_className, TypeAttributes.Public | TypeAttributes.Class); @@ -158,7 +161,25 @@ namespace FreeSql.Internal private static ConcurrentDictionary _delegateCache = new ConcurrentDictionary(); - //设置动态对象的属性值 + //设置动态对象的属性值 使用FreeSql自带功能 + public static object CreateObjectByTypeByCodeFirst(IFreeSql fsql, Type type, + Dictionary porpertys) + { + if (type == null) + return null; + object istance = Activator.CreateInstance(type); + if (istance == null) + return null; + var table = fsql.CodeFirst.GetTableByEntity(type); + foreach (var kv in porpertys) + { + table.ColumnsByCs[kv.Key].SetValue(istance, kv.Value); + } + + return istance; + } + + //设置动态对象的属性值,使用表达式目录树 public static object CreateObjectByType(Type type, Dictionary porpertys) { if (type == null) @@ -167,7 +188,8 @@ namespace FreeSql.Internal if (istance == null) return null; //根据字典中的key确定缓存 - var cacheKey = string.Join("-", porpertys.Keys.OrderBy(s => s)); + var cacheKeyStr = string.Join("-", porpertys.Keys.OrderBy(s => s)); + var cacheKey = Md5Encryption(cacheKeyStr); var dynamicDelegate = _delegateCache.GetOrAdd(cacheKey, key => { //表达式目录树构建委托 @@ -224,13 +246,25 @@ namespace FreeSql.Internal string str = input.First().ToString().ToUpper() + input.Substring(1); return str; } + + private static string Md5Encryption(string inputStr) + { + var result = string.Empty; + //32位大写 + using (var md5 = MD5.Create()) + { + var resultBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(inputStr)); + result = BitConverter.ToString(resultBytes); + } + + return result; + } } #endif internal class DynamicPropertyInfo { public string PropertyName { get; set; } = string.Empty; public Type PropertyType { get; set; } - public Attribute [] Attributes { get; set; } + public Attribute[] Attributes { get; set; } } -} - +} \ No newline at end of file From 8bd85ebe22d7fa3e3a600892d9580a14fdd835e7 Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:28:19 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E7=9B=B8=E5=85=B3=E7=9A=84API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/FreeSql.xml | 51 --------------------------------------------- 1 file changed, 51 deletions(-) diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index f8ee6bd1..5323d7da 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1073,20 +1073,6 @@ - - - 动态创建Class Type - - - - - - 根据动态构建的Class生成实例并进行属性赋值 - - - - - 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null @@ -4262,43 +4248,6 @@ Dict:key=属性名,value=注释 - - - 配置Class - - 类名 - 类标记的特性[Table(Name = "xxx")] - - - - - 配置属性 - - 属性名称 - 属性类型 - 属性标记的特性[Column(IsPrimary = true)] - - - - - Emit动态创建出Class - Type - - - - - - 首字母小写 - - - - - - - 首字母大写 - - - - 更新实体的元数据 From 5046907e4f06776998e04623ce34356696685aa1 Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:29:08 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E8=A1=A8=E7=BB=93=E6=9E=84=E7=9B=B8=E5=85=B3=E7=9A=84API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Internal/DynamicCompileBuilder.cs | 80 +++++++++++------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs index c857eb74..7c6feba8 100644 --- a/FreeSql/Internal/DynamicCompileBuilder.cs +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -179,47 +179,47 @@ namespace FreeSql.Internal return istance; } - //设置动态对象的属性值,使用表达式目录树 - public static object CreateObjectByType(Type type, Dictionary porpertys) - { - if (type == null) - return null; - object istance = Activator.CreateInstance(type); - if (istance == null) - return null; - //根据字典中的key确定缓存 - var cacheKeyStr = string.Join("-", porpertys.Keys.OrderBy(s => s)); - var cacheKey = Md5Encryption(cacheKeyStr); - var dynamicDelegate = _delegateCache.GetOrAdd(cacheKey, key => - { - //表达式目录树构建委托 - var typeParam = Expression.Parameter(type); - var dicParamType = typeof(Dictionary); - var dicParam = Expression.Parameter(dicParamType); - var exps = new List(); - var tempRef = Expression.Variable(typeof(object)); - foreach (var pinfo in porpertys) - { - var propertyInfo = type.GetProperty(pinfo.Key); - if (propertyInfo == null) - continue; - var propertyName = Expression.Constant(pinfo.Key, typeof(string)); - exps.Add(Expression.Call(dicParam, dicParamType.GetMethod("TryGetValue"), propertyName, tempRef)); - exps.Add(Expression.Assign(Expression.MakeMemberAccess(typeParam, propertyInfo), - Expression.Convert(tempRef, propertyInfo.PropertyType))); - exps.Add(Expression.Assign(tempRef, Expression.Default(typeof(object)))); - } + ////设置动态对象的属性值,使用表达式目录树 + //public static object CreateObjectByType(Type type, Dictionary porpertys) + //{ + // if (type == null) + // return null; + // object istance = Activator.CreateInstance(type); + // if (istance == null) + // return null; + // //根据字典中的key确定缓存 + // var cacheKeyStr = string.Join("-", porpertys.Keys.OrderBy(s => s)); + // var cacheKey = Md5Encryption(cacheKeyStr); + // var dynamicDelegate = _delegateCache.GetOrAdd(cacheKey, key => + // { + // //表达式目录树构建委托 + // var typeParam = Expression.Parameter(type); + // var dicParamType = typeof(Dictionary); + // var dicParam = Expression.Parameter(dicParamType); + // var exps = new List(); + // var tempRef = Expression.Variable(typeof(object)); + // foreach (var pinfo in porpertys) + // { + // var propertyInfo = type.GetProperty(pinfo.Key); + // if (propertyInfo == null) + // continue; + // var propertyName = Expression.Constant(pinfo.Key, typeof(string)); + // exps.Add(Expression.Call(dicParam, dicParamType.GetMethod("TryGetValue"), propertyName, tempRef)); + // exps.Add(Expression.Assign(Expression.MakeMemberAccess(typeParam, propertyInfo), + // Expression.Convert(tempRef, propertyInfo.PropertyType))); + // exps.Add(Expression.Assign(tempRef, Expression.Default(typeof(object)))); + // } - var returnTarget = Expression.Label(type); - exps.Add(Expression.Return(returnTarget, typeParam)); - exps.Add(Expression.Label(returnTarget, Expression.Default(type))); - var block = Expression.Block(new[] { tempRef }, exps); - var @delegate = Expression.Lambda(block, typeParam, dicParam).Compile(); - return @delegate; - }); - var dynamicInvoke = dynamicDelegate.DynamicInvoke(istance, porpertys); - return dynamicInvoke; - } + // var returnTarget = Expression.Label(type); + // exps.Add(Expression.Return(returnTarget, typeParam)); + // exps.Add(Expression.Label(returnTarget, Expression.Default(type))); + // var block = Expression.Block(new[] { tempRef }, exps); + // var @delegate = Expression.Lambda(block, typeParam, dicParam).Compile(); + // return @delegate; + // }); + // var dynamicInvoke = dynamicDelegate.DynamicInvoke(istance, porpertys); + // return dynamicInvoke; + //} /// /// 首字母小写 From f8866f2479b5ed4843c6360ad77057480578750d Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Tue, 25 Apr 2023 10:29:24 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E8=A1=A8=E7=BB=93=E6=9E=84=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Internal/DynamicCompileBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeSql/Internal/DynamicCompileBuilder.cs b/FreeSql/Internal/DynamicCompileBuilder.cs index 7c6feba8..9dfdd0cf 100644 --- a/FreeSql/Internal/DynamicCompileBuilder.cs +++ b/FreeSql/Internal/DynamicCompileBuilder.cs @@ -179,7 +179,7 @@ namespace FreeSql.Internal return istance; } - ////设置动态对象的属性值,使用表达式目录树 + ////设置动态对象的属性值,使用表达式目录树 //public static object CreateObjectByType(Type type, Dictionary porpertys) //{ // if (type == null)