标題:重溫ABP領域層
1. 前言
最近一段時間一直在看
《ABP的開發指南》(基于DDD的經典分層架構思想)
。因為之前一段時間剛看完
《領域驅動設計:軟體核心複雜性應對之道》
,概念比較多,看着有點空。于是拿起了這本書。應該說是不是書, 隻是一個PDF版的開發指南。于是乎,就開始了。好了,廢話不多說,首先是ABP領域層的結構介紹,如下圖所示:
從圖中可以看到,
ABP
的領域層分為
實體
,
倉儲
工作單元
資料過濾器
,以及
領域事件
五個部分。這五個部分的功能作用,如果看過了解過
DDD
的應該不會陌生。接下來我将一一介紹這五個部分的詳情,每個部分具體作用,以及實作。順便給自己溫習溫習。附加一點自己粗淺的了解,如有不正确的地方,歡迎指正,交流。
2. 各個子產品
2.1 ABP領域層-實體
很多對象不是通過它們的屬性定義的,而是通過一連串的連續性事件和辨別定義的。———摘錄自《領域驅動設計》第5章 5.2 模式:Entity(又稱為Reference Object)
在ABP的實體中,實體繼承至Entity。可以細分為下面三個部分。
1、實體類
,2、
接口約定
以及
3、IEntity接口
2.1.1 首先是第一個 實體類
實體類
檢視源碼發現如下:
namespace Abp.Domain.Entities
{
/// <summary>
/// A shortcut of <see cref="T:Abp.Domain.Entities.Entity`1" /> for most used primary key type (<see cref="T:System.Int32" />).
/// </summary>
[Serializable]
public abstract class Entity : Entity<int>, IEntity, IEntity<int>
{
}
}
然後最後我們看下
IEntity<TPrimary>
之後就真相大白了。
namespace Abp.Domain.Entities
{
/// <summary>
/// Defines interface for base entity type. All entities in the system must implement this interface.
/// </summary>
/// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam>
public interface IEntity<TPrimaryKey>
{
/// <summary>Unique identifier for this entity.</summary>
TPrimaryKey Id { get; set; }
/// <summary>
/// Checks if this entity is transient (not persisted to database and it has not an <see cref="P:Abp.Domain.Entities.IEntity`1.Id" />).
/// </summary>
/// <returns>True, if this entity is transient</returns>
bool IsTransient();
}
}
相當于每個繼承于
Entity
的都有一個
Id
屬性。
Id
屬性是該實體的主鍵,是以,Id是所有繼承自
Entity
類的實體的主鍵。當然,從源碼中,我們可以發現。很顯然這個Id資料的類型可以被更改。因為是
<TPrimary>
類型的,是以,你如果想要改成
long
,或者
Guid
等等啦。隻需要向如下這樣定義:
public class ClassA : Entity<Guid>
{
//...
}
2.1.2 第二個是 接口約定
接口約定
剛開始聽到這個名字時,我覺得有點難以了解。但是在文章中,聽了一下解釋。可以幫助了解,如下:
很多實體會有像 CreationTime
用來訓示該實體是什麼時候被建立的。ABP提供了一些有用的接口來實作類似的功能,隻需要實作這些接口的實體,就能夠實作指定的功能。
在
接口預定
中,又分為如下三個部分:
首先是
審計(Auditing)
,這個接口主要的是
CreationTime
這個屬性。隻要實體類實作
IHasCreationTime
接口,當該實體被插入到資料庫時,ABP會自動設定該屬性的值為目前時間。
public interface IHasCreationTime{
DateTime CreationTime{get;set;}
}
審計中還有一個接口
ICreationAudited
,這個接口是擴充至
IHasCreationTime
,并且該接口還有一個屬性
CreatorUserId
,可以用來記錄目前使用者的
Id
,
public interface ICreationAudited : IHasCreationTime{
long ? CreatorUserId{get;set;}
}
CreationAuditedEntity
類已實作了
ICreationAudited
我們可以直接繼承來使用。
審計中還有一個實作類似修改功能的接口
IModificationAudited
public interface IModificationAudited{
DateTime? LastModificationTime{get;set;}
ling? LastModifierUserId{get;set;}
}
當然,如果你想都實作這些審計屬性,ABP也提供給你了。
IAudited
接口。
public interface IAudited : ICreationAudited, IModificationAudited{
}
可能你有點亂了,我來給你理理。大概就是如下這樣的。
這樣簡單吧。
接下來是
軟删除
, 表示标記了一個實體已經被删除了。而不是從資料庫中删除記錄。對應的接口為
ISoftDelete
:
public interface ISoftDelete{
bool IsDeleted{get;set;}
}
來源于文中:當一個實作了軟删除的實體正在被删除,ABP會察覺到這個動作,并且阻止其删除,設定屬性值為
IsDeleted
并且更新資料庫中的實體。
true
和審計中的
ICreationAudited
類似, 記錄誰删除了這個實體。
IDeletionAudited
public interface IDeletionAudited: ISoftDelete{
long? DeleterUserId{get;set;}
DateTime? DeletionTime{get;set;}
}
當然,如果你想要實作所有(包括,建立,修改,和删除。)那就實作這個終極接口,
IFullAudited
public interface IFullAudited: IAudited , IDeletionAudited{
//...
}
實體類
FullAuditedEntity
實作了
IFullAudited
接口。可以直接繼承使用。
那麼審計的終極總結圖就如下:
很清楚了吧!
PS:詳情可以檢視源代碼
Abp.Domain.Entities.Auditing
2.1.3最後一個是IEntity接口
在2.1.1 中已經介紹了一下,這裡就不贅述。
Entity
IEntity
接口(和
Entity<TPrimaryKey>
IEntity<TPrimaryKey>
接口)。
2.2 ABP領域層-倉儲
2.3 ABP領域層-工作單元
2.4 ABP領域層-資料過濾器
2.5 ABP領域層-領域事件
3. 結語
本想一次性把這些都總結整理一下,突然發現内容有點多。還是一步一步來,慢慢整理把。這次先整理實體。好尴尬。
4.附錄
參考:Github_ABPChina
參考連結:
- https://www.aspnetboilerplate.com/Pages/Documents
- http://www.cnblogs.com/farb/p/ABPTheory.html
- http://www.cnblogs.com/mienreal/p/4528470.html