From bb1fd88f79dfbfb3efcd1f1bd6bc2e03175aa1c4 Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Mon, 15 May 2023 10:53:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?-=20=E5=9F=BA=E7=B1=BB=E5=B1=9E=E6=80=A7abs?= =?UTF-8?q?tract/virtual=E6=94=AF=E6=8C=81override?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DynamicEntity/DynamicEntityTest.cs | 131 +++++++++++++++++- FreeSql/Extensions/DynamicEntityExtensions.cs | 110 ++++++++++++++- FreeSql/FreeSql.xml | 78 ----------- 3 files changed, 233 insertions(+), 86 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs b/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs index c1385540..3c988ea8 100644 --- a/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs @@ -33,12 +33,14 @@ namespace FreeSql.Tests.DynamicEntity //根据Type生成表 fsql.CodeFirst.SyncStructure(table.Type); fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); } [Fact] public void AttributeTest() { - var table = fsql.CodeFirst.DynamicEntity("AttributeUsers", new TableAttribute() { Name = "T_Attribute_User" }, + var table = fsql.CodeFirst.DynamicEntity("AttributeUsers", + new TableAttribute() { Name = "T_Attribute_User" }, new IndexAttribute("Name_Index1", "Name", false)) .Property("Id", typeof(int), new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) @@ -80,9 +82,122 @@ namespace FreeSql.Tests.DynamicEntity //根据Type生成表 fsql.CodeFirst.SyncStructure(table.Type); fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); + } + + [Fact] + public void SuperClassVirtualOverrideTest() + { + var table = fsql.CodeFirst.DynamicEntity("Role_VirtualOverride", + new TableAttribute() { Name = "T_Role_VirtualOverride" }, + new IndexAttribute("Name_Index2", "Name", false)) + .Extend(typeof(BaseModelOverride)) + .Property("Id", typeof(int), + new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) + .Property("Name", typeof(string), + new ColumnAttribute() { StringLength = 20, Position = 2 }) + .Property("Operators", typeof(string), true) //重写 virtual 属性 + .Build(); + var dict = new Dictionary + { + ["Name"] = "系统管理员", + ["UpdateTime"] = DateTime.Now, + ["UpdatePerson"] = "admin", + ["Operators"] = "manager" + }; + var instance = table.CreateInstance(dict); + //根据Type生成表 + fsql.CodeFirst.SyncStructure(table.Type); + fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); + } + + [Fact] + public void SuperClassBaseModelAbstractTest() + { + var table = fsql.CodeFirst.DynamicEntity("Role_AbstractOverride", + new TableAttribute() { Name = "T_Role_AbstractOverride" }, + new IndexAttribute("Name_Index2", "Name", false)) + .Extend(typeof(BaseModelOverride)) + .Property("Id", typeof(int), + new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) + .Property("Name", typeof(string), + new ColumnAttribute() { StringLength = 20, Position = 2 }) + .Property("Operators", typeof(string), true) //重写 abstract 属性 + .Build(); + var dict = new Dictionary + { + ["Name"] = "系统管理员", + ["UpdateTime"] = DateTime.Now, + ["UpdatePerson"] = "admin", + ["Operators"] = "manager" + }; + var instance = table.CreateInstance(dict); + //根据Type生成表 + fsql.CodeFirst.SyncStructure(table.Type); + fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); + } + + [Fact] + public void SuperClassBaseModelAbstractAndVirtualTest() + { + var table = fsql.CodeFirst.DynamicEntity("Role_AbstractAndVirtualOverride", + new TableAttribute() { Name = "Role_AbstractAndVirtualOverride" }, + new IndexAttribute("Name_Index2", "Name", false)) + .Extend(typeof(BaseModelOverride)) + .Property("Id", typeof(int), + new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) + .Property("Name", typeof(string), + new ColumnAttribute() { StringLength = 20, Position = 2 }) + .Property("Operators", typeof(string), true) //重写 abstract 属性 + .Property("Operators2", typeof(string), true) //重写 virtual 属性 + .Build(); + var dict = new Dictionary + { + ["Name"] = "系统管理员", + ["UpdateTime"] = DateTime.Now, + ["UpdatePerson"] = "admin", + ["Operators"] = "manager", + ["Operators2"] = "manager2" + }; + var instance = table.CreateInstance(dict); + //根据Type生成表 + fsql.CodeFirst.SyncStructure(table.Type); + fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); } } + public class BaseModel + { + [Column(Position = 99)] public DateTime UpdateTime { get; set; } + + [Column(Position = 100, StringLength = 20)] + public string UpdatePerson { get; set; } + } + + public class BaseModelOverride + { + [Column(Position = 99)] public DateTime UpdateTime { get; set; } + + [Column(Position = 100, StringLength = 20)] + public string UpdatePerson { get; set; } + + public virtual string Operators { get; set; } + } + + public abstract class BaseModelAbstract + { + [Column(Position = 99)] public DateTime UpdateTime { get; set; } + + [Column(Position = 100, StringLength = 20)] + public string UpdatePerson { get; set; } + + public abstract string Operators { get; set; } + } + + public abstract class BaseModelAbstractAndVirtual { [Column(Position = 99)] public DateTime UpdateTime @@ -95,5 +210,17 @@ namespace FreeSql.Tests.DynamicEntity { get; set; } + + public abstract string Operators + { + get; set; + } + + + public virtual string Operators2 + { + get; set; + } } -} \ No newline at end of file +} + diff --git a/FreeSql/Extensions/DynamicEntityExtensions.cs b/FreeSql/Extensions/DynamicEntityExtensions.cs index f4659e1e..0ae32e0e 100644 --- a/FreeSql/Extensions/DynamicEntityExtensions.cs +++ b/FreeSql/Extensions/DynamicEntityExtensions.cs @@ -1,7 +1,7 @@ // by: Daily #if net40 || NETSTANDARD2_0 -# else +#else using FreeSql; using FreeSql.DataAnnotations; @@ -23,7 +23,8 @@ public static class FreeSqlGlobalDynamicEntityExtensions /// 动态构建Class Type /// /// - public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, params Attribute[] attributes) + public static DynamicCompileBuilder DynamicEntity(this ICodeFirst codeFirst, string className, + params Attribute[] attributes) { return new DynamicCompileBuilder((codeFirst as CodeFirstProvider)._orm, className, attributes); } @@ -43,8 +44,10 @@ public static class FreeSqlGlobalDynamicEntityExtensions if (dict.ContainsKey(key) == false) continue; table.ColumnsByCs[key].SetValue(instance, dict[key]); } + return instance; } + /// /// 根据实体对象,创建 table 对应的字典 /// @@ -94,12 +97,59 @@ namespace FreeSql.Extensions.DynamicEntity /// 属性类型 /// 属性标记的特性-支持多个 /// - 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, + DefaultValue = null, + Attributes = attributes + }); + return this; + } + + /// + /// 配置属性 + /// + /// 属性名称 + /// 属性类型 + /// 该属性是否重写父类属性 + /// 属性标记的特性-支持多个 + /// + public DynamicCompileBuilder Property(string propertyName, Type propertyType, bool isOverride, + params Attribute[] attributes) + { + _properties.Add(new DynamicPropertyInfo() + { + PropertyName = propertyName, + PropertyType = propertyType, + DefaultValue = null, + IsOverride = isOverride, + Attributes = attributes + }); + return this; + } + + /// + /// 配置属性 + /// + /// 属性名称 + /// 属性类型 + /// 该属性是否重写父类属性 + /// 属性默认值 + /// 属性标记的特性-支持多个 + /// + public DynamicCompileBuilder Property(string propertyName, Type propertyType, bool isOverride, + object defaultValue, params Attribute[] attributes) + { + _properties.Add(new DynamicPropertyInfo() + { + PropertyName = propertyName, + PropertyType = propertyType, + DefaultValue = null, + IsOverride = isOverride, Attributes = attributes }); return this; @@ -162,10 +212,17 @@ namespace FreeSql.Extensions.DynamicEntity var field = typeBuilder.DefineField($"_{FirstCharToLower(propertyName)}", propertyType, FieldAttributes.Private); var firstCharToUpper = FirstCharToUpper(propertyName); + + MethodAttributes maAttributes = MethodAttributes.Public; + + if (pinfo.IsOverride) + { + maAttributes = MethodAttributes.Public | MethodAttributes.Virtual; + } + //设置属性方法 - var methodGet = typeBuilder.DefineMethod($"Get{firstCharToUpper}", MethodAttributes.Public, - propertyType, null); - var methodSet = typeBuilder.DefineMethod($"Set{firstCharToUpper}", MethodAttributes.Public, null, + var methodGet = typeBuilder.DefineMethod($"get_{firstCharToUpper}", maAttributes, propertyType, null); + var methodSet = typeBuilder.DefineMethod($"set_{firstCharToUpper}", maAttributes, null, new Type[] { propertyType }); var ilOfGet = methodGet.GetILGenerator(); @@ -179,12 +236,27 @@ namespace FreeSql.Extensions.DynamicEntity ilOfSet.Emit(OpCodes.Stfld, field); ilOfSet.Emit(OpCodes.Ret); + + //是否重写 + if (pinfo.IsOverride) + { + //重写Get、Set方法 + OverrideProperty(ref typeBuilder, methodGet, PropertyMethodEnum.GET, pinfo.PropertyName); + OverrideProperty(ref typeBuilder, methodSet, PropertyMethodEnum.SET, pinfo.PropertyName); + } + //设置属性 var propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); propertyBuilder.SetGetMethod(methodGet); propertyBuilder.SetSetMethod(methodSet); + //设置默认值 + if (pinfo.DefaultValue != null) + { + propertyBuilder.SetConstant(pinfo.DefaultValue); + } + foreach (var pinfoAttribute in pinfo.Attributes) { //设置特性 @@ -208,6 +280,23 @@ namespace FreeSql.Extensions.DynamicEntity propertyBuilder.SetCustomAttribute(customAttributeBuilder); } + /// + /// Override属性 + /// + /// + private void OverrideProperty(ref TypeBuilder typeBuilder, MethodBuilder methodBuilder, + PropertyMethodEnum methodEnum, + string propertyName) + { + //查找父类的属性信息 + var propertyInfo = typeBuilder.BaseType.GetProperty(propertyName); + if (propertyInfo == null) return; + var pm = methodEnum == PropertyMethodEnum.GET ? propertyInfo.GetGetMethod() : propertyInfo.GetSetMethod(); + //重写父类GET SET 方法 + typeBuilder.DefineMethodOverride(methodBuilder, pm); + } + + /// /// Emit动态创建出Class - Type /// @@ -233,6 +322,7 @@ namespace FreeSql.Extensions.DynamicEntity //创建类的Type对象 var type = typeBuilder.CreateType(); + return _fsql.CodeFirst.GetTableByEntity(type); } @@ -279,8 +369,16 @@ namespace FreeSql.Extensions.DynamicEntity { public string PropertyName { get; set; } = string.Empty; public Type PropertyType { get; set; } + public object DefaultValue { get; set; } + public bool IsOverride { get; set; } = false; public Attribute[] Attributes { get; set; } } + + enum PropertyMethodEnum + { + GET, + SET + } } } #endif \ No newline at end of file diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index aaffe163..5323d7da 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -6208,81 +6208,3 @@ -ew{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 查询数据 - - - - - - - 查询数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 删除数据 - - - - - - - 删除数据,传入动态条件,如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1} - - - 主键值、主键值集合、实体、实体集合、匿名对象、匿名对象集合 - - - - - 开启事务(不支持异步) - v1.5.0 关闭了线程事务超时自动提交的机制 - - 事务体 () => {} - - - - 开启事务(不支持异步) - v1.5.0 关闭了线程事务超时自动提交的机制 - - - 事务体 () => {} - - - - 数据库访问对象 - - - - - 所有拦截方法都在这里 - - - - - CodeFirst 模式开发相关方法 - - - - - DbFirst 模式开发相关方法 - - - - - 全局过滤设置,可默认附加为 Select/Update/Delete 条件 - - - - From 4732ccde87e725dc14efabb517db1a85f8022cdf Mon Sep 17 00:00:00 2001 From: d4ilys <963922242@qq.com> Date: Mon, 15 May 2023 16:34:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?-=20=E5=9F=BA=E7=B1=BB=E5=B1=9E=E6=80=A7abs?= =?UTF-8?q?tract/virtual=E6=94=AF=E6=8C=81override=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B1=9E=E6=80=A7=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DynamicEntity/DynamicEntityTest.cs | 55 ++++++---- FreeSql/Extensions/DynamicEntityExtensions.cs | 100 +++++++++++++++--- FreeSql/FreeSql.xml | 98 +++++++++++++++++ 3 files changed, 219 insertions(+), 34 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs b/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs index 3c988ea8..ec135fcb 100644 --- a/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/DynamicEntity/DynamicEntityTest.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using FreeSql.DataAnnotations; using FreeSql.Extensions.DynamicEntity; +using Newtonsoft.Json; using Xunit; namespace FreeSql.Tests.DynamicEntity @@ -118,7 +119,7 @@ namespace FreeSql.Tests.DynamicEntity var table = fsql.CodeFirst.DynamicEntity("Role_AbstractOverride", new TableAttribute() { Name = "T_Role_AbstractOverride" }, new IndexAttribute("Name_Index2", "Name", false)) - .Extend(typeof(BaseModelOverride)) + .Extend(typeof(BaseModelAbstract)) .Property("Id", typeof(int), new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) .Property("Name", typeof(string), @@ -145,7 +146,7 @@ namespace FreeSql.Tests.DynamicEntity var table = fsql.CodeFirst.DynamicEntity("Role_AbstractAndVirtualOverride", new TableAttribute() { Name = "Role_AbstractAndVirtualOverride" }, new IndexAttribute("Name_Index2", "Name", false)) - .Extend(typeof(BaseModelOverride)) + .Extend(typeof(BaseModelAbstractAndVirtual)) .Property("Id", typeof(int), new ColumnAttribute() { IsPrimary = true, IsIdentity = true, Position = 1 }) .Property("Name", typeof(string), @@ -167,6 +168,32 @@ namespace FreeSql.Tests.DynamicEntity fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); var objects = fsql.Select().AsType(table.Type).ToList(); } + + [Fact] + public void DefaultValueTest() + { + var table = fsql.CodeFirst.DynamicEntity("NormalUsers") + .Property("Id", typeof(string)) + .Property("Age", typeof(int), false, 12) + .Property("Longs", typeof(long), false, 16666) + .Property("Dates", typeof(DateTime), false, "2023-05-15") + .Property("Name", typeof(char), false, '我') + .Property("Address", typeof(bool), false, false) //设置默认值 + .Property("Money", typeof(double), false, 265421.02) //设置默认值 + .Property("MoneyFloat", typeof(float), false, 26543.02) //设置默认值 + .Property("MoneyDecimal", typeof(decimal), true, 2663.12560) //设置默认值 + .Build(); + + var dict = new Dictionary + { + ["Id"] = Guid.NewGuid().ToString() + }; + var instance = table.CreateInstance(dict); + //根据Type生成表 + fsql.CodeFirst.SyncStructure(table.Type); + fsql.Insert().AsType(table.Type).AppendData(instance).ExecuteAffrows(); + var objects = fsql.Select().AsType(table.Type).ToList(); + } } public class BaseModel @@ -199,28 +226,14 @@ namespace FreeSql.Tests.DynamicEntity public abstract class BaseModelAbstractAndVirtual { - [Column(Position = 99)] - public DateTime UpdateTime - { - get; set; - } + [Column(Position = 99)] public DateTime UpdateTime { get; set; } [Column(Position = 100, StringLength = 20)] - public string UpdatePerson - { - get; set; - } + public string UpdatePerson { get; set; } - public abstract string Operators - { - get; set; - } + public abstract string Operators { get; set; } - public virtual string Operators2 - { - get; set; - } + public virtual string Operators2 { get; set; } } -} - +} \ No newline at end of file diff --git a/FreeSql/Extensions/DynamicEntityExtensions.cs b/FreeSql/Extensions/DynamicEntityExtensions.cs index 0ae32e0e..45873720 100644 --- a/FreeSql/Extensions/DynamicEntityExtensions.cs +++ b/FreeSql/Extensions/DynamicEntityExtensions.cs @@ -11,11 +11,15 @@ using FreeSql.Internal.Model; using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Net.NetworkInformation; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.Serialization; using System.Security.Cryptography; using System.Text; +using System.Xml.Serialization; public static class FreeSqlGlobalDynamicEntityExtensions { @@ -39,6 +43,12 @@ public static class FreeSqlGlobalDynamicEntityExtensions { if (table == null || dict == null) return null; var instance = table.Type.CreateInstanceGetDefaultValue(); + //加载默认值 + var defaultValueInit = table.Type.GetMethod("DefaultValueInit"); + if (defaultValueInit != null) + { + defaultValueInit.Invoke(instance, new object[0]); + } foreach (var key in table.ColumnsByCs.Keys) { if (dict.ContainsKey(key) == false) continue; @@ -148,7 +158,7 @@ namespace FreeSql.Extensions.DynamicEntity { PropertyName = propertyName, PropertyType = propertyType, - DefaultValue = null, + DefaultValue = defaultValue, IsOverride = isOverride, Attributes = attributes }); @@ -176,7 +186,7 @@ namespace FreeSql.Extensions.DynamicEntity if (tableAttribute == null) continue; - var classCtorInfo = tableAttribute.GetType().GetConstructor(new Type[] { }); + var classCtorInfo = tableAttribute.GetType().GetConstructor(Type.EmptyTypes); var propertyInfos = tableAttribute.GetType().GetProperties().Where(p => p.CanWrite == true).ToArray(); @@ -202,6 +212,7 @@ namespace FreeSql.Extensions.DynamicEntity private void SetPropertys(ref TypeBuilder typeBuilder) { + var defaultValues = new Dictionary(); foreach (var pinfo in _properties) { if (pinfo == null) @@ -210,11 +221,12 @@ namespace FreeSql.Extensions.DynamicEntity var propertyType = pinfo.PropertyType; //设置字段 var field = typeBuilder.DefineField($"_{FirstCharToLower(propertyName)}", propertyType, - FieldAttributes.Private); + FieldAttributes.Private | FieldAttributes.HasDefault); var firstCharToUpper = FirstCharToUpper(propertyName); MethodAttributes maAttributes = MethodAttributes.Public; + //是否重写 if (pinfo.IsOverride) { maAttributes = MethodAttributes.Public | MethodAttributes.Virtual; @@ -251,33 +263,95 @@ namespace FreeSql.Extensions.DynamicEntity propertyBuilder.SetGetMethod(methodGet); propertyBuilder.SetSetMethod(methodSet); - //设置默认值 - if (pinfo.DefaultValue != null) - { - propertyBuilder.SetConstant(pinfo.DefaultValue); - } - foreach (var pinfoAttribute in pinfo.Attributes) { //设置特性 SetPropertyAttribute(ref propertyBuilder, pinfoAttribute); } + + if (pinfo.DefaultValue != null) + { + defaultValues.Add(field, pinfo.DefaultValue); + } + } + + //动态构建方法,设置默认值 + var methodDefaultValue = typeBuilder.DefineMethod($"DefaultValueInit", MethodAttributes.Public, null, null); + var methodDefaultValueLlGenerator = methodDefaultValue.GetILGenerator(); + foreach (var kv in defaultValues) + { + methodDefaultValueLlGenerator.Emit(OpCodes.Ldarg_0); + OpCodesAdapter(ref methodDefaultValueLlGenerator, kv.Key, kv.Value); + methodDefaultValueLlGenerator.Emit(OpCodes.Stfld, kv.Key); + } + + methodDefaultValueLlGenerator.Emit(OpCodes.Ret); + } + + //IL命令类型适配 + private void OpCodesAdapter(ref ILGenerator generator, FieldInfo info, object value) + { + var fieldTypeName = info.FieldType.Name; + switch (fieldTypeName) + { + case "Int32": + generator.Emit(OpCodes.Ldc_I4, Convert.ToInt32(value)); + break; + case "Boolean": + generator.Emit(OpCodes.Ldc_I4, Convert.ToInt32(value)); + break; + case "Char": + generator.Emit(OpCodes.Ldc_I4, Convert.ToChar(value)); + break; + case "String": + generator.Emit(OpCodes.Ldstr, Convert.ToString(value)); + break; + case "DateTime": + generator.Emit(OpCodes.Ldstr, Convert.ToString(value)); + generator.Emit(OpCodes.Call, typeof(DateTime).GetMethod("Parse", new[] { typeof(string) })); + break; + case "Int64": + generator.Emit(OpCodes.Ldc_I4, Convert.ToString(value)); + generator.Emit(OpCodes.Conv_I8); + break; + case "Double": + generator.Emit(OpCodes.Ldc_R8, Convert.ToDouble(value)); + break; + case "Single": + generator.Emit(OpCodes.Ldc_R4, Convert.ToSingle(value)); + break; + case "Decimal": + Console.WriteLine(Convert.ToString(value)); + generator.Emit(OpCodes.Ldstr, Convert.ToString(value)); + generator.Emit(OpCodes.Call, typeof(Decimal).GetMethod("Parse", new[] { typeof(string) })); + break; } } private void SetPropertyAttribute(ref PropertyBuilder propertyBuilder, T tAttribute) { if (tAttribute == null) return; - var propertyInfos = tAttribute.GetType().GetProperties().Where(p => p.CanWrite == true).ToArray(); - var constructor = tAttribute.GetType().GetConstructor(new Type[] { }); + var constructor = tAttribute.GetType().GetConstructor(Type.EmptyTypes); var propertyValues = new ArrayList(); foreach (var propertyInfo in propertyInfos) propertyValues.Add(propertyInfo.GetValue(tAttribute)); - var customAttributeBuilder = - new CustomAttributeBuilder(constructor, new object[0], propertyInfos, propertyValues.ToArray()); + //可能存在有参构造 + //if (constructor == null) + //{ + // var constructorTypes = propertyInfos.Select(p => p.PropertyType).ToList(); + // constructor = tAttribute.GetType().GetConstructor(constructorTypes.ToArray()); + // var customAttributeBuilder = new CustomAttributeBuilder(constructor, constructorTypes.ToArray(), + // propertyInfos, propertyValues.ToArray()); + // propertyBuilder.SetCustomAttribute(customAttributeBuilder); + //} + //else + //{ + var customAttributeBuilder = new CustomAttributeBuilder(constructor, new object[0], propertyInfos, + propertyValues.ToArray()); propertyBuilder.SetCustomAttribute(customAttributeBuilder); + // } } /// diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 5323d7da..8cd7ad2d 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1073,6 +1073,82 @@ + + + 动态创建实体类型 + + + + + 配置Class + + 类名 + 类标记的特性[Table(Name = "xxx")] [Index(xxxx)] + + + + + 配置属性 + + 属性名称 + 属性类型 + 属性标记的特性-支持多个 + + + + + 配置属性 + + 属性名称 + 属性类型 + 该属性是否重写父类属性 + 属性标记的特性-支持多个 + + + + + 配置属性 + + 属性名称 + 属性类型 + 该属性是否重写父类属性 + 属性默认值 + 属性标记的特性-支持多个 + + + + + 配置父类 + + 父类类型 + + + + + Override属性 + + + + + + Emit动态创建出Class - Type + + + + + + 首字母小写 + + + + + + + 首字母大写 + + + + 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null @@ -5692,6 +5768,28 @@ 请使用 fsql.InsertDict(dict) 方法插入字典数据 + + + 动态构建Class Type + + + + + + 根据字典,创建 table 对应的实体对象 + + + + + + + + 根据实体对象,创建 table 对应的字典 + + + + + C#: that >= between && that <= and