此处的Domain主要指Abp类库根目录下Domain文件夹。顾名思义该目录下是用来存放与领域实体,领域逻辑执行,存储,领域服务相关的内容。

  1.Entities

   (1)为整个Abp框架后期开发的所有实体Model提供接口及基础实现,总的来讲为实现某种规范的接口都拥有两个,一个是主键数据类型为泛型的实现,另一个则是继承该泛型接口并为泛型提供一个默认的数据类型,例如IEntity<TPrimaryKey>的属性Id就为TPrimaryKey类型,另一个接口IEntity只是接单的继承上述接口并指定一个int型public interface IEntity : IEntity<int>,最基本的模型接口IEntity<TPrimaryKey>提供了一个实现类public abstract class Entity<TPrimaryKey>,提供了对象比较功能,bool Equals(object obj)和int GetHashCode()方法。Entities提供了一个IMayHaveTenant接口只有一个可空的TenantId属性,用于确定实体是否属于应用级别的(值为空)或者租户级别以及哪个租户,在后面的EF的DynamicFilter也会用到。同时提供了一个IMustHaveTenant接口含有一个不可空的TenantId属性,指明实体对象属于哪个租户所有,IPassivable接口包含一个IsActive的布尔类型的属性,用以指明实体对象是否激活状态。ISoftDelete是为软删除设计模式设计的布尔类型的IsDeleted属性表明实体记录是否已被删除,对于EF搜索可用对象集合十分有帮助,ISoftDelete接口拥有一个扩展方法bool IsNullOrDeleted(this ISoftDelete entity)可以方便表明对象是否属于已删除状态。

   (2)Entities为框架额外提供了一个审计模型接口包括一些基类实现,用以在实体对象中保存相关信息如:创建人,删除人,更新人,更新时间用以保存到持久化设备中。所有的设计类型都有泛型类型(主要用于指定主键类型)和默认类型(指明主键的类型)。同时还有一个两个泛型参数的版本,用以设置一个外键方便跳转到相应实体。

public abstract class CreationAuditedEntity<TPrimaryKey, TUser> : CreationAuditedEntity<TPrimaryKey>, ICreationAudited<TUser>
where TUser : IEntity<long>
{
/// <summary>
/// Reference to the creator user of this entity.
/// </summary>
[ForeignKey("CreatorUserId")]
public virtual TUser CreatorUser { get; set; }
}
  • CreationAuditedEntity<TPrimaryKey>,如果模型实例仅需记录创建者ID和创建时间,那么继承该抽象类就可以了,此时也无需再继承Entity<TPrimaryKey>抽象类就已经是一个符合领域规范的实体了。
  • AuditedEntity<TPrimaryKey>,继承于第一个泛型类,同时添加了可空的修改人Id和修改时间
  • FullAuditedEntity<TPrimaryKey>,为了方便实体记录中添加创建人,修改人,是否已处于删除状态,还有删除人,删除时间,提供了此类包含上述所有需要记录的信息。

  2.Policies

   只是提供了一个IPolicy接口,无任何实现。

  3.Repositories

   (1)IRepository空接口用以表明实例是一个Repository。

   (2)IRepository<TEntity, TPrimaryKey>包含一个真正的Repository所拥有的CRUD方法,第一个泛型表示将要操作的实体类型(必须继承自IEntity<TPrimaryKey>接口),第二个泛型表示TEntity中主键的类型。主要分为五大块,分别是1.Select/Get/Query(用以搜索返回记录)2.Insert 3.Update 4.Delete 5.Aggregate(计算所有记录数),所有的方法都有同步及异步。

   (3)AbpRepositoryBase<TEntity, TPrimaryKey>,关于上述接口,框架提供了一个默认实现,该实现是一个抽象类,定义了数个抽象方法用以在具体所使用的ORM框架来决定真正逻辑,public abstract IQueryable<TEntity> GetAll();就是这样一个需要在后面实现的抽象类,所有其他的查找方法都是依赖此方法来完成自己的逻辑的,所以如果用EF来做ORM的话只需新建一个EFRepository并实现GetAll()抽象方法就ok了,1.public abstract TEntity Update(TEntity entity);2.public abstract void Delete(TEntity entity);同样如此。

  4.Services

   该块是系统的领域驱动服务,拥有一个空的IDomainService接口,同时拥有一个实现DomainService,这是一个抽象类,并继承AbpServiceBase,在AbpServiceBase类中已经存在ISettingManager,IUnitOfWorkManager,IActiveUnitOfWork,ILocalizationManager,ILogger(默认是一个空实现但是可以通过属性注入获得有意义的Logger,如果容器中有的话),还有一个本地方的方法string L(string name, CultureInfo culture, params object[] args)。

  5.UOW

   系统中所有事务逻辑都是保存于此的(系统默认是IApplicationService和IRepository方法执行时会生成事务环境并保存在静态私有字典字段中,通过线程槽中得到GUID去唯一匹配)。另外也可以为所以将会存入依赖容器的类型的方法上应用UnitOfWorkAttribute来保证在事务中被执行,同时该特性有一个IsDisabled来关闭默认事务。

   (1)在系统的启动阶段,会注册相关的类型到依赖容器中,如果是IApplicationService和IRepository或者类型或者方法上应用了UnitOfWorkAttribute依赖容器就会为该类添加一个UnitOfWorkInterceptor,确保方法在事务环境中被执行,该拦截器的void Intercept(IInvocation invocation)方法执行时会首先通过IUnitOfWorkManager的Current属性获取保存到线程槽中的IUnitOfWork(实际上是IUnitOfWork的GUID键值),如果不为空说明其已经在一个事务上下文中了,下面直接执行真正的逻辑就行了,如果为空的话会尝试获取应用在方法上的UnitOfWorkAttribute特性,如果没有的话会new一个新的(默认单元工作类上没有),利用此特性创建UnitOfWorkOptions,利用得到的options作为参数调用IUnitOfWorkManager的Begin方法,Begin方法会返回一个完成句柄,该句柄同时也是Disposable的,如果真正的逻辑执行ok,在最后会调用完成句柄的Complete()完成保存,同时该句柄也会被Dispose掉,通过Begin方法保存到线程数据槽中的IUnitOfWork也会被释放掉。(真正的执行逻辑是可以分异步同步的,都是支持的)

   (2)UnitOfWorkBase具有一些事件像Completed,Failed,Disposed都会在事务的相应阶段被处罚,需要额外处理一些东西的话可以监控这些事件,关于动态过滤的所有参数也UnitOfWorkBase中设置添加,在UnitOfWorkBase的继承类中会使用到控制在数据库的记录集的筛选。SaveChanges方法执行真正的保存逻辑也需要根据不同的ORM而有所变化的。所以当前是抽象方法。

   (3)CallContextCurrentUnitOfWorkProvider,在每次生成新的IUnitOfWork的时候我们需要存放这些对象以方便在函数调用堆栈中的方法的获得,所以提供了这样一个类,实际上IUnitOfWorkManager的Current属性就是调用该类的同名属性来获取的,当创建新的IUnitOfWork的时候,也通过此类的Current属性来保存。当获取当前环境的IUnitOfWork的时候会先从线程数据槽中得到当前执行线程的单元工作的GUID,CallContext.LogicalGetData(ContextKey),如果不存在就返回null,如果存在就从该类的ConcurrentDictionary<string, IUnitOfWork> UnitOfWorkDictionary私有静态只读属性中获取相应的IUnitOfWork,如果不存在就返回null,同时清空数据槽中的GUID,如果存在就获取IUnitOfWork再猜判断是否已经Dispose掉了,没有被Dispose就返回该IUnitOfWork,否则清理数据返回null。而设置保存一个新建的IUnitOfWork则是跟获取的方法执行流程相反。

ABP框架详解(三)Domain的更多相关文章

  1. ABP框架详解(七)Caching

    在ABP框架中存在一个缓存机制,使用ICache的继承类来存储最终需要缓存的数据,可以吧ICache看成一个字典对象,使用Key作为真实数据的具有唯一性的表示.使用上与字典对象完全相同,Get方法传递 ...

  2. ABP框架详解(二)AbpKernelModule

    AbpKernelModule类是Abp框架自己的Module,它也跟所有其他的Module一样继承自AbpModule,重写PreInitialize,Initialize,PostInitiali ...

  3. ABP框架详解(一)ABPBootstrapper

    在ABP框架的AbpBootstrapper主要用于框架的基本配置的注册和初始化,在Web应用启动阶段实例化一个AbpBootstrapper并调用Initialize方法初始化,该类主要包含两个公有 ...

  4. ABP框架详解(八)动态ApiController的生成和访问机制

    在ABP框架中提供了一套动态生成ApiController的机制(依然支持原生ApiController的使用方式),虽然说是动态生成ApiController但是实际上并没有真正在启动程序的时候生成 ...

  5. ABP框架详解(五)Navigation

    ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是.所以为方便起见,Navigation功能 ...

  6. ABP框架详解(四)Feature

    ABP框架中存在一个Feature的特性,功能和设计思路非常类似于框架中的Authorization功能,都是来控制用户是否能够继续操作某项功能,不同点在于Authorization默认是应用在IAp ...

  7. ABP框架详解(六)Aspects

    这种AOP式的设计非常类似于Asp.net MVC和WebApi中过滤器(Filter)机制,感觉没有太多可讲述的,只能谈谈设计思路. 框架中AspectAttribute特性用于设置到需要被拦截的T ...

  8. Shiro 安全框架详解二(概念+权限案例实现)

    Shiro 安全框架详解二 总结内容 一.登录认证 二.Shiro 授权 1. 概念 2. 授权流程图 三.基于 ini 的授权认证案例实现 1. 实现原理图 2. 实现代码 2.1 添加 maven ...

  9. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

随机推荐

  1. ELK日志管理之——logstash配置语法

    Logstash 设计了自己的 DSL -- 有点像 Puppet 的 DSL,或许因为都是用 Ruby 语言写的吧 -- 包括有区域,注释,数据类型(布尔值,字符串,数值,数组,哈希),条件判断,字 ...

  2. JavaScript依赖注入的实现思路

    JavaScript依赖注入的实现思路 如今各个框架都在模块化,连前端的javascript也不例外.每个模块负责一定的功能,模块与模块之间又有相互依赖,那么问题来了:javascript的依赖注入如 ...

  3. SVM学习笔记(一):libsvm参数说明(转)

    LIBSVM 数据格式需要---------------------- 决策属性 条件属性a 条件属性b ... 2 1:7 2:5 ... 1 1:4 2:2 ... 数据格式转换--------- ...

  4. 互联网商业模式O2O、C2C、B2B、B2C等介绍

    O2O是online to offline分为四种运营模式: 1.online to offline是线上交易到线下消费体验 2.offline to online是线下营销到线上交易 3.offli ...

  5. 用clock()函数计算多项式的运行时间

    百度百科中定义clock():clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下: clock_t clock(void) ; 简 ...

  6. QT toLocal8Bit奇怪的问题

    #include "mainwindow.h" #include "ui_mainwindow.h" #include<QDebug> MainWi ...

  7. eval回显变量

    eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令.该命令适用于那些一次扫描无法实现其功能的变量. 一个应用场景如下: export path="/home/bin/" ...

  8. 4. Prototype(原型)

    意图: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 适用性: 当要实例化的类是在运行时刻指定时,例如,通过动态装载:或者 为了避免创建一个与产品类层次平行的工厂类层次时:或者 当 ...

  9. 解决Nginx不支持pathinfo的问题

    server { listen 80; server_name www.zq27.cc zq27.cc; root /data/wwwroot/www.zq27.cc/; access_log off ...

  10. kernel 对浮点的支持

    http://blog.chinaunix.net/uid-22545494-id-316735.html 作者: Sam(甄峰)  sam_code@hotmail.com 一:早期ARM上的浮点模 ...