1- using FreeSql . DataAnnotations ;
2- using System ;
1+ using System ;
32using System . Collections ;
4- using System . Collections . Concurrent ;
53using System . Collections . Generic ;
64using System . Linq ;
7- using System . Linq . Expressions ;
85using System . Reflection ;
96using System . Reflection . Emit ;
107using System . Security . Cryptography ;
11- using FreeSql . Internal . Model ;
128using System . Text ;
139
14- namespace FreeSql . Internal
10+ namespace FreeSql . Extensions . DynamicEntity
1511{
16- #if net40 || NETSTANDARD2_0
17- #else
12+ /// <summary>
13+ /// 动态创建实体类型
14+ /// </summary>
1815 public class DynamicCompileBuilder
1916 {
2017 private string _className = string . Empty ;
2118 private Attribute [ ] _tableAttributes = null ;
2219 private List < DynamicPropertyInfo > _properties = new List < DynamicPropertyInfo > ( ) ;
20+ private Type _superClass = null ;
2321
2422 /// <summary>
2523 /// 配置Class
2624 /// </summary>
2725 /// <param name="className">类名</param>
28- /// <param name="attributes">类标记的特性[Table(Name = "xxx")]</param>
26+ /// <param name="attributes">类标记的特性[Table(Name = "xxx")] [Index(xxxx)] </param>
2927 /// <returns></returns>
30- public DynamicCompileBuilder ( string className , params Attribute [ ] attributes )
28+ public DynamicCompileBuilder Class ( string className , params Attribute [ ] attributes )
3129 {
3230 _className = className ;
3331 _tableAttributes = attributes ;
32+ return this ;
3433 }
3534
3635 /// <summary>
@@ -51,31 +50,59 @@ public DynamicCompileBuilder Property(string propertyName, Type propertyType, pa
5150 return this ;
5251 }
5352
53+ /// <summary>
54+ /// 配置父类
55+ /// </summary>
56+ /// <param name="superClass">父类类型</param>
57+ /// <returns></returns>
58+ public DynamicCompileBuilder Extend ( Type superClass )
59+ {
60+ _superClass = superClass ;
61+ return this ;
62+ }
63+
5464 private void SetTableAttribute ( ref TypeBuilder typeBuilder )
5565 {
5666 if ( _tableAttributes == null ) return ;
5767
58- var propertyValues = new ArrayList ( ) ;
5968 foreach ( var tableAttribute in _tableAttributes )
6069 {
70+ var propertyValues = new ArrayList ( ) ;
71+
6172 if ( tableAttribute == null ) continue ;
6273
6374 var classCtorInfo = tableAttribute . GetType ( ) . GetConstructor ( new Type [ ] { } ) ;
75+
6476 var propertyInfos = tableAttribute . GetType ( ) . GetProperties ( ) . Where ( p => p . CanWrite == true ) . ToArray ( ) ;
77+
6578 foreach ( var propertyInfo in propertyInfos )
6679 propertyValues . Add ( propertyInfo . GetValue ( tableAttribute ) ) ;
67-
68- var customAttributeBuilder = new CustomAttributeBuilder ( classCtorInfo , new object [ 0 ] , propertyInfos , propertyValues . ToArray ( ) ) ;
69- typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
80+
81+ //可能存在有参构造
82+ if ( classCtorInfo == null )
83+ {
84+ var constructorTypes = propertyInfos . Select ( p => p . PropertyType ) ;
85+ classCtorInfo = tableAttribute . GetType ( ) . GetConstructor ( constructorTypes . ToArray ( ) ) ;
86+ var customAttributeBuilder = new CustomAttributeBuilder ( classCtorInfo , propertyValues . ToArray ( ) ) ;
87+ typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
88+ }
89+ else
90+ {
91+ var customAttributeBuilder = new CustomAttributeBuilder ( classCtorInfo , new object [ 0 ] , propertyInfos ,
92+ propertyValues . ToArray ( ) ) ;
93+ typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
94+ }
7095 }
7196 }
7297
7398 private void SetPropertys ( ref TypeBuilder typeBuilder )
7499 {
75100 foreach ( var pinfo in _properties )
76101 {
102+ if ( pinfo == null )
103+ continue ;
77104 var propertyName = pinfo . PropertyName ;
78- var propertyType = pinfo ? . PropertyType ?? typeof ( object ) ;
105+ var propertyType = pinfo . PropertyType ;
79106 //设置字段
80107 var field = typeBuilder . DefineField ( $ "_{ FirstCharToLower ( propertyName ) } ", propertyType ,
81108 FieldAttributes . Private ) ;
@@ -98,7 +125,8 @@ private void SetPropertys(ref TypeBuilder typeBuilder)
98125 ilOfSet . Emit ( OpCodes . Ret ) ;
99126
100127 //设置属性
101- var propertyBuilder = typeBuilder . DefineProperty ( propertyName , PropertyAttributes . None , propertyType , null ) ;
128+ var propertyBuilder =
129+ typeBuilder . DefineProperty ( propertyName , PropertyAttributes . None , propertyType , null ) ;
102130 propertyBuilder . SetGetMethod ( methodGet ) ;
103131 propertyBuilder . SetSetMethod ( methodSet ) ;
104132
@@ -120,7 +148,8 @@ private void SetPropertyAttribute<T>(ref PropertyBuilder propertyBuilder, T tAtt
120148 foreach ( var propertyInfo in propertyInfos )
121149 propertyValues . Add ( propertyInfo . GetValue ( tAttribute ) ) ;
122150
123- var customAttributeBuilder = new CustomAttributeBuilder ( constructor , new object [ 0 ] , propertyInfos , propertyValues . ToArray ( ) ) ;
151+ var customAttributeBuilder =
152+ new CustomAttributeBuilder ( constructor , new object [ 0 ] , propertyInfos , propertyValues . ToArray ( ) ) ;
124153 propertyBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
125154 }
126155
@@ -138,7 +167,8 @@ public Type Build()
138167 var defineDynamicModule =
139168 defineDynamicAssembly . DefineDynamicModule ( "FreeSql.DynamicCompileBuilder.Dynamics" ) ;
140169 //动态的在模块内创建一个类
141- var typeBuilder = defineDynamicModule . DefineType ( _className , TypeAttributes . Public | TypeAttributes . Class ) ;
170+ var typeBuilder =
171+ defineDynamicModule . DefineType ( _className , TypeAttributes . Public | TypeAttributes . Class , _superClass ) ;
142172
143173 //设置TableAttribute
144174 SetTableAttribute ( ref typeBuilder ) ;
@@ -150,70 +180,6 @@ public Type Build()
150180 return typeBuilder . CreateType ( ) ;
151181 }
152182
153- //委托缓存
154- private static ConcurrentDictionary < string , Delegate >
155- _delegateCache = new ConcurrentDictionary < string , Delegate > ( ) ;
156-
157- //设置动态对象的属性值 使用FreeSql自带功能
158- public static object CreateObjectByTypeByCodeFirst ( IFreeSql fsql , Type type ,
159- Dictionary < string , object > porpertys )
160- {
161- if ( type == null )
162- return null ;
163- object istance = Activator . CreateInstance ( type ) ;
164- if ( istance == null )
165- return null ;
166- var table = fsql . CodeFirst . GetTableByEntity ( type ) ;
167- foreach ( var kv in porpertys )
168- {
169- table . ColumnsByCs [ kv . Key ] . SetValue ( istance , kv . Value ) ;
170- }
171-
172- return istance ;
173- }
174-
175- ////设置动态对象的属性值,使用表达式目录树
176- //public static object CreateObjectByType(Type type, Dictionary<string, object> porpertys)
177- //{
178- // if (type == null)
179- // return null;
180- // object istance = Activator.CreateInstance(type);
181- // if (istance == null)
182- // return null;
183- // //根据字典中的key确定缓存
184- // var cacheKeyStr = string.Join("-", porpertys.Keys.OrderBy(s => s));
185- // var cacheKey = Md5Encryption(cacheKeyStr);
186- // var dynamicDelegate = _delegateCache.GetOrAdd(cacheKey, key =>
187- // {
188- // //表达式目录树构建委托
189- // var typeParam = Expression.Parameter(type);
190- // var dicParamType = typeof(Dictionary<string, object>);
191- // var dicParam = Expression.Parameter(dicParamType);
192- // var exps = new List<Expression>();
193- // var tempRef = Expression.Variable(typeof(object));
194- // foreach (var pinfo in porpertys)
195- // {
196- // var propertyInfo = type.GetProperty(pinfo.Key);
197- // if (propertyInfo == null)
198- // continue;
199- // var propertyName = Expression.Constant(pinfo.Key, typeof(string));
200- // exps.Add(Expression.Call(dicParam, dicParamType.GetMethod("TryGetValue"), propertyName, tempRef));
201- // exps.Add(Expression.Assign(Expression.MakeMemberAccess(typeParam, propertyInfo),
202- // Expression.Convert(tempRef, propertyInfo.PropertyType)));
203- // exps.Add(Expression.Assign(tempRef, Expression.Default(typeof(object))));
204- // }
205-
206- // var returnTarget = Expression.Label(type);
207- // exps.Add(Expression.Return(returnTarget, typeParam));
208- // exps.Add(Expression.Label(returnTarget, Expression.Default(type)));
209- // var block = Expression.Block(new[] { tempRef }, exps);
210- // var @delegate = Expression.Lambda(block, typeParam, dicParam).Compile();
211- // return @delegate;
212- // });
213- // var dynamicInvoke = dynamicDelegate.DynamicInvoke(istance, porpertys);
214- // return dynamicInvoke;
215- //}
216-
217183 /// <summary>
218184 /// 首字母小写
219185 /// </summary>
@@ -260,5 +226,4 @@ class DynamicPropertyInfo
260226 public Attribute [ ] Attributes { get ; set ; }
261227 }
262228 }
263- #endif
264229}
0 commit comments