一、DDD模块
依赖模块
[DependsOn( typeof(AbpAuditingModule), typeof(AbpDataModule), typeof(AbpEventBusModule), typeof(AbpGuidsModule), typeof(AbpMultiTenancyModule), typeof(AbpThreadingModule), typeof(AbpTimingModule), typeof(AbpUnitOfWorkModule), typeof(AbpObjectMappingModule) )] public class AbpDddDomainModule : AbpModule { }
1、实体
Defines an entity. It's primary key may not be "Id" or it may have a composite primary key.
object[] GetKeys();
在 IEntity<TKey>
的默认实现 Entity<TKey>
中,不仅提供了标识定义,也重写了 Equals()
比较方法和 ==
!=
操作符,用于区别不同实体
1)聚合根
聚合就是一组相关对象的集合,他会有一个根对象(root),和它的一个边界(boundary)。对于聚合外部来说,只能够引用它的根对象,而在聚合内部的其他对象则可以相互引用。
该类型也继承自 Entity
类型,并且内部提供了一个并发令牌防止并发冲突。并且在其内部也提供了领域事件的快速增删方法,其他的与常规实体基本一致。通过领域事件,我们可以完成对事务的拆分。例如上述的例子当中,我们也可以为 Part 增加一个领域事件,当价格被更新时,PO 可以订阅这个事件,实现对应的采购项更新。
[Serializable] public abstract class AggregateRoot<TKey> : Entity<TKey>, IAggregateRoot<TKey>, IGeneratesDomainEvents, IHasExtraProperties, IHasConcurrencyStamp
public interface IGeneratesDomainEvents { IEnumerable<object> GetLocalEvents(); IEnumerable<object> GetDistributedEvents(); void ClearLocalEvents(); void ClearDistributedEvents(); }
什么是审计属性呢?在 ABP vNext 内部将以下属性定义为审计属性:创建人、创建时间、修改人、修改时间、删除人、删除时间、软删除标记
2)AuditedAggregateRootWithUser<TUser> 携带User的class类 public virtual TUser Creator { get; set; }
Audited和FullAudit的区别:
audited包括Creation,Modification的相关信息,
而FullAudit除了audited信息,还包括了IsDeleted,DeleterId,DeletionTime等软删除信息
3)事件
public class EntityEventData<TEntity> : IEventDataWithInheritableGenericArgument
DomainEventEntry
2、仓储
IReadOnlyBasicRepository<TEntity> ;包括GetList(),GetCount()
IReadOnlyBasicRepository<TEntity, TKey>; 增加Gets an entity with given primary key
IBasicRepository<TEntity, TKey>;增加Insert,Update,Delete
public interface IRepository<TEntity, TKey> : IRepository<TEntity>,
IReadOnlyRepository<TEntity, TKey>, IBasicRepository<TEntity, TKey> where TEntity : class, IEntity<TKey> { }
RepositoryBase比BasicRepositoryBase,增加IDataFilter,ICurrentTenant,IQueryable
public abstract class RepositoryBase<TEntity> : BasicRepositoryBase<TEntity>, IRepository<TEntity> where TEntity : class, IEntity
抽象方法RepositoryRegistrarBase,仓储的具体实现模块都实现了这个基类
实现有EfCoreRepositoryRegistrar;MemoryDbRepositoryRegistrar;MongoDbRepositoryRegistrar
仓储肯定会有多种实现的,例如 EF Core 的仓储实现肯定有自己的一套注册机制,
3、服务
IDomainService,DomainService
4、值对象 ValueObject
并且按照聚合的特性来说,其实聚合与聚合之间的通讯,主要是通过领域事件来实现的。
二、DDD.Application模块
[DependsOn( typeof(AbpDddDomainModule), typeof(AbpSecurityModule), typeof(AbpObjectMappingModule), typeof(AbpValidationModule), typeof(AbpAuthorizationModule), typeof(AbpHttpAbstractionsModule), typeof(AbpSe、ttingsModule), typeof(AbpFeaturesModule) )] public class AbpDddApplicationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure<ApiDescriptionModelOptions>(options => { options.IgnoredInterfaces.AddIfNotContains(typeof(IRemoteService)); options.IgnoredInterfaces.AddIfNotContains(typeof(IApplicationService)); options.IgnoredInterfaces.AddIfNotContains(typeof(IUnitOfWorkEnabled)); }); } }
1、Dtos
请求
ILimitedResultRequest =》 int MaxResultCount { get; set; }
ISortedResultRequest=》string Sorting { get; set; } 比如 "Name";"Name DESC";"Name ASC, Age DESC"
IPagedResultRequest=》包括ILimitedResultRequest; int SkipCount { get; set; } Skip count (beginning of the page).
IPagedAndSortedResultRequest=》 IPagedResultRequest, ISortedResultRequest
返回结果
TKey Id { get; set; }
IHasTotalCount =》 long TotalCount { get; set; }
IListResult<T> =》 IReadOnlyList<T> Items { get; set; }
IPagedResult<T> 包含 IListResult<T>, IHasTotalCount
实体
顺序:IEntityDto 》 CreationAuditedEntityDto 、CreationAuditedEntityWithUserDto》AuditedEntityDto、AuditedEntityWithUserDto<TUserDto>
=》FullAuditedEntityDto、FullAuditedEntityWithUserDto
2、Services
IRemoteService=》IApplicationService
public interface IAsyncCrudAppService<TEntityDto, in TKey, in TGetListInput, in TCreateInput, in TUpdateInput> : IApplicationService where TEntityDto : IEntityDto<TKey> { Task<TEntityDto> GetAsync(TKey id); Task<PagedResultDto<TEntityDto>> GetListAsync(TGetListInput input); Task<TEntityDto> CreateAsync(TCreateInput input); Task<TEntityDto> UpdateAsync(TKey id, TUpdateInput input); Task DeleteAsync(TKey id); }