目前Fireasy中的實(shí)體模型雖然用CodeBuilder生成,但是還是比較龐大,手工維護(hù)起來(lái)比較吃力,因此一直想使用比較簡(jiǎn)單的一種模型,比如屬性只有 get 和 set,最多加個(gè)ColumnAttribute之類的來(lái)做映射。但這樣做的話,屬性修改這一特性就無(wú)法保持了,即更新實(shí)體時(shí)不知道哪些屬性有改動(dòng)過(guò)。
我們先看一下目前生成的實(shí)體類代碼:
/// <summary> /// 部門 實(shí)體類。 /// </summary> [Serializable] [EntityMapping("TB_DEPT", Description = "部門")] public partial class Dept : EntityObject { #region Static PRoperty Definition /// <summary> /// ID的依賴屬性。 /// </summary> public static readonly IProperty EpId = PropertyUnity.RegisterProperty<Dept>(s => s.Id, new PropertyMapInfo { IsPrimaryKey = true, IsNullable = false, Length = 36, Description = "ID", FieldName = "ID" }); /// <summary> /// 編碼的依賴屬性。 /// </summary> public static readonly IProperty EpNo = PropertyUnity.RegisterProperty<Dept>(s => s.No, new PropertyMapInfo { Length = 50, Description = "編碼", FieldName = "NO" }); /// <summary> /// 名稱的依賴屬性。 /// </summary> public static readonly IProperty EpName = PropertyUnity.RegisterProperty<Dept>(s => s.Name, new PropertyMapInfo { Length = 50, Description = "名稱", FieldName = "NAME" }); /// <summary> /// 排序的依賴屬性。 /// </summary> public static readonly IProperty EpOrderNo = PropertyUnity.RegisterProperty<Dept>(s => s.OrderNo, new PropertyMapInfo { Description = "排序", FieldName = "ORDER_NO" }); #endregion #region Properties /// <summary> /// 獲取或設(shè)置ID。 /// </summary> public string Id { get { return (string)GetValue(EpId); } set { SetValue(EpId, value); } } /// <summary> /// 獲取或設(shè)置編碼。 /// </summary> public string No { get { return (string)GetValue(EpNo); } set { SetValue(EpNo, value); } } /// <summary> /// 獲取或設(shè)置名稱。 /// </summary> public string Name { get { return (string)GetValue(EpName); } set { SetValue(EpName, value); } } /// <summary> /// 獲取或設(shè)置排序。 /// </summary> public int? OrderNo { get { return (int?)GetValue(EpOrderNo); } set { SetValue(EpOrderNo, value); } } #endregion }以上的實(shí)體模型,主要借鑒WPF中的依賴屬性原理,定義一個(gè)靜態(tài)的Field實(shí)現(xiàn)關(guān)系映射,最主要的一點(diǎn),就是在設(shè)置屬性的時(shí)候,交由基類的SetValue方法來(lái)執(zhí)行,它會(huì)把這個(gè)修改過(guò)的屬性記下來(lái),在更新實(shí)體的時(shí)候,達(dá)到只更新修改過(guò)的屬性的目的。
而GetValue和SetValue看似有裝箱和拆箱操作,實(shí)際上屬性的值是以PropertyValue這個(gè)結(jié)構(gòu)存儲(chǔ)的,通過(guò)重載強(qiáng)制轉(zhuǎn)換和顯式轉(zhuǎn)換操作符來(lái)交換數(shù)據(jù),所以這里不用擔(dān)心啦。
那么,實(shí)際上有了EntityObject基類就好辦多了,可以再抽象出一個(gè)類,讓它基于AOP來(lái)創(chuàng)建,在設(shè)置屬性值之后和獲取屬性值之后分別調(diào)用SetValue和GetValue就好了。
Fireasy本來(lái)就提供了AOP,在Fireasy.Common.Aop命名空間中,關(guān)鍵是IInterceptor這個(gè)接口,它通過(guò)InterceptAttribute特性來(lái)綁定要攔截的方法、屬性或是整個(gè)類。
還有一個(gè)接口IAopSupport,它只起到一個(gè)標(biāo)識(shí),在擴(kuò)展方法New中,如果類型實(shí)現(xiàn)了IAopSupport,那么則使用aspectFactory來(lái)創(chuàng)建對(duì)象。
好,接下來(lái)我們定義一個(gè)LighEntityObject 類:
[Intercept(typeof(LighEntityInterceptor))] public abstract class LighEntityObject<TEntity> : EntityObject, IAopSupport, IEntityPropertyInitialize where TEntity : IEntity { /// <summary> /// 構(gòu)造一個(gè)代理對(duì)象。 /// </summary> /// <returns></returns> public static TEntity New() { return typeof(TEntity).New<TEntity>(); } void IEntityPropertyInitialize.Initialize() { var entityType = this.GetType(); foreach (var property in entityType.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (property.DeclaringType == entityType.BaseType) { //定義為 virtual var getMth = property.GetGetMethod(); if (getMth != null && getMth.IsVirtual && !getMth.IsFinal) { RegisterProperty(entityType.BaseType, property); } } } } private void RegisterProperty(Type entityType, PropertyInfo property) { //關(guān)聯(lián)屬性,即關(guān)聯(lián)實(shí)體或子實(shí)體集屬性 if (typeof(IEntity).IsAssignableFrom(property.PropertyType) || typeof(IEntitySet).IsAssignableFrom(property.PropertyType)) { var mapping = property.GetCustomAttributes<PropertyMappingAttribute>().FirstOrDefault(); var options = mapping != null && mapping.GetFlag(PropertyMappingAttribute.SetMark.LoadBehavior) ? new RelationOptions(mapping.LoadBehavior) : null; PropertyUnity.RegisterSupposedProperty(property.Name, property.PropertyType, entityType, options: options); } else { var gp = new GeneralProperty() { Name = property.Name, Type = property.PropertyType, EntityType = entityType, Info = new PropertyMapInfo { ReflectionInfo = property, FieldName = property.Name } }; var mapping = property.GetCustomAttributes<PropertyMappingAttribute>().FirstOrDefault(); if (mapping != null) { InitMapInfo(mapping, gp.Info); } PropertyUnity.RegisterProperty(entityType, gp); } } /// <summary> /// 根據(jù)映射特性設(shè)置屬性的映射信息。 /// </summary> /// <param name="mapping"></param> /// <param name="mapInfo"></param> private void InitMapInfo(PropertyMappingAttribute mapping, PropertyMapInfo mapInfo) { mapInfo.FieldName = mapping.ColumnName; mapInfo.Description = mapping.Description; mapInfo.GenerateType = mapping.GenerateType; if (mapping.GetFlag(PropertyMappingAttribute.SetMark.DataType)) { mapInfo.DataType = mapping.DataType; } if (mapping.GetFlag(PropertyMappingAttribute.SetMark.IsPrimaryKey)) { mapInfo.IsPrimaryKey = mapping.IsPrimaryKey; } if (mapping.GetFlag(PropertyMappingAttribute.SetMark.IsDeletedKey)) { mapInfo.IsDeletedKey = mapping.IsDeletedKey; } if (mapping.DefaultValue != null) { mapInfo.DefaultValue = PropertyValue.New(mapping.DefaultValue, mapInfo.ReflectionInfo.PropertyType); } if (mapping.GetFlag(PropertyMappingAttribute.SetMark.Length)) { mapInfo.Length = mapping.Length; } if (mapping.GetFlag(PropertyMappingAttribute.SetMark.Precision)) { mapInfo.Precision = mapping.Precision; } if (mapping.GetFlag(PropertyMappingAttribute.SetMark.Scale)) { mapInfo.Scale = mapping.Scale; } } }關(guān)鍵還是攔截器了,看下面代碼:
public sealed class LighEntityInterceptor : IInterceptor { void IInterceptor.Initialize(InterceptContext context) { } void IInterceptor.Intercept(InterceptCallInfo info) { if (info.InterceptType == InterceptType.AfterGetValue || info.InterceptType == InterceptType.AfterSetValue) { var entity = info.Target as EntityObject; var entityType = entity.EntityType; var property = PropertyUnity.GetProperty(entityType, info.Member.Name); if (property == null) { return; } switch (info.InterceptType) { case InterceptType.AfterGetValue: var value = entity.GetValue(property); if (value != null && !value.IsEmpty) { info.ReturnValue = value.GetStorageValue(); }
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注