实战框架ABP

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实战框架ABP
abp及实战框架概述
接触abp也快⼀年了,有过⼤半年的abp项⽬开发经验,⽬前项⽬中所⽤的abp框架版本为0.10.3,最新的abp框架已经到了1.4,并且⽀持了 core。

关于abp框架有哪些特性、有什么好处我这⾥就不讲了。

如果你对abp不太了解请先去 Abp官⽹了解或者参考我的学习之路⾥⾯的链接。

在这系列的⽂章⾥⾯我会把我在实战中的经验、碰到的坑分享出来。

希望跟⼤家⼀起学习讨论。

学习之路
框架概述
这个框架版本主要⽤的技术有 mvc5.0、web api、EF 6.1 。

⼀、整体框架概述
Topeveyr.Core:主要存放业务实体以及仓储接⼝。

Application⽂件夹:这⾥⾯有两个应⽤服务层,当时是想做读写分离的,⼀个读⼀个写。

但是底层的数据访问层没有实现读写分离。

(全完实现读写分离还没找到解决⽅案)
Topevery.EntityFramework.Oracle:主要存放实体映射⽂件、仓储实现类。

Topevery.Web:web界⾯。

Topevery.WebApi:api接⼝。

Topevery.Infrastructure:框架中跟业务⽆关的公共类。

Topevery.WF.Framework:流程业务相关项⽬。

Topevery.Abp:封装了abp类的公共类。

TimeServices:定时服务类库。

Dapper:⼀款轻量级orm框架。

主要是为了⽀持EF操作Oracled包⽽加进来的。

如果是其他数据库可以忽略该项⽬。

为了更好的统⼀,以后应该全部换成存储过程。

Zero⽂件夹:这⾥⾯的三个项⽬分别对应abp的应⽤服务层、核⼼层、数据访问层。

这个项⽬主要⽤来操作⼀些基础信息表以及公共模块。

⽐如,⽤户、⾓⾊、权限、部门等。

⼆、整体框架设计
整体框架设计⾥⾯,我觉得“模块”的⽐较重要,这⾥就讲⼀讲我对模块的理解。

每个单独类库或者应⽤程序即是⼀个模块。

当需要⽤到Ioc容器、abp启动配置或者是在应⽤程序启动的时候做⼀些设置就需要⽤到abp⾥⾯的模块。

模块类可以被依赖。

模块类在应⽤程序启动的时候被执⾏,并且按依赖的关系进⾏执⾏。

即没有被依赖的模块最后执⾏。

模块有四个⽅法,PreInitialize()、Initialize()、PostInitialize()、Shutdown()。

前三个⽅法是在应⽤程序启动的时候运⾏的,最后⼀个⽅法是在应⽤程序关闭的时候运⾏的。

模块⽅法的执⾏顺序是先执⾏完所有模块的PreInitialize(),再执⾏所有模块的Initialize(),最后执⾏所有模块的PostInitialize()。

整体框架模块的依赖设计图如下:
三、框架详细设计
本框架⼤概思路是根据abp的⽰例代码⽽来。

我只是参照原来的框架做了⼀些扩展。

相同的框架设计就不讲了。

讲⼀讲不同之处。

在本框架⾥⾯的Zero项⽬跟官⽅Abp.Zero不同。

Abp.Zero⾥⾯基本上都是提供抽象类,要具体实例化必须得在相应的业务类库⾥⾯继承才能⽤。

本框架⾥的Zero项⽬直接提供对外的服务接⼝。

Topevery.Zero是应⽤服务接⼝。

Topevery.Zero.Core存放实体仓储接⼝。

Topevery.Zero.EntityFramework.Oracel是数据访问抽象层,该类库⾥⾯有继承了AbpDbContext的抽象类。

由于本框架⽤的是Oracle,⽬前还没有找到EF操作⾃增长类型的解决⽅案。

所以⽬前插⼊数据的时候解决思路是先获取序列再插⼊数据。

 获取序列的话有两种解决⽅案。

⼀种是在仓储的基类⾥⾯添加公共⽅法,这种⽅案的优势可以很好的集成依赖注⼊,并且可以做到事务控制。

但这种⽅案的劣势是所有的实体类都必须有对应的仓储基类。

另外⼀种⽅案是新增⼀个数据访问DbContext。

这个⽅案的优势在于可以在应⽤服务的基类⾥⾯添加⼀个获取序列的公共⽅法。

劣势是序列的获取和其他数据的操作不能⼀起做事务控制。

我在框架⾥⾯采⽤的是第⼆种⽅案。

整体思路是在 Topevery.Zero.EntityFramework.Oracle 项⽬中添加 IDbContextHelper 接⼝,该接⼝
有两个获取序列的⽅法。

在Topevery.EntityFramework.Oracle 项⽬中添加 DbContextHelper,该类继承 IDbContextHelper 接⼝,并且有个DbContext 的变量,⽤来访问数据库。

为啥要这样设计?因为解耦。

所有 Zero ⾥⾯的的项⽬都不需要直接引⽤具体的DbContextHelper⽽只要引⽤接⼝即可,具体的接⼝实现是在运⾏的时候注⼊。

具体代码如下:
1 public interface IDbContextHelper
2 {
3 /// <summary>
4 /// 获取序列值
5 /// </summary>
6 /// <typeparam name="T"></typeparam>
7 /// <param name="sequenceName"></param>
8 /// <returns></returns>
9 T GetSequenceValueByName<T>(string sequenceName) where T : struct;
10
11 /// <summary>
12 /// 获取序列值(默认int)
13 /// </summary>
14 /// <param name="sequenceName"></param>
15 /// <returns></returns>
16 int GetSequenceValueByName(string sequenceName);
17 }
View Code
1 public class DbContextHelper:IDbContextHelper,ITransientDependency
2 {
3 /// <summary>
4 /// 数据访问类
5 /// </summary>
6 private volatile DbContext _dbContext ;
7
8 /// <summary>
9 /// 锁帮助对象
10 /// </summary>
11 private readonly object _lockObject = new object();
12
13 /// <summary>
14 ///
15 /// </summary>
16 private DbContext TopeveryDbContext
17 {
18 get
19 {
20 if (_dbContext == null)
21 {
22 lock (_lockObject)
23 {
24 if (_dbContext == null)
25 _dbContext = IocManager.Instance.Resolve<TopeveryDbContext>();
26 }
27 }
28 return _dbContext;
29 }
30 }
31
32 /// <summary>
33 /// 得到序列的字符串
34 /// </summary>
35 /// <param name="sequenceName"></param>
36 /// <returns></returns>
37 private string GetSequenceSqlByName(string sequenceName)
38 {
39 return "select " + sequenceName + ".nextval from dual";
40 }
41
42 /// <summary>
43 /// 获取序列值
44 /// </summary>
45 /// <typeparam name="T"></typeparam>
46 /// <param name="sequenceName"></param>
47 /// <returns></returns>
48 public T GetSequenceValueByName<T>(string sequenceName) where T : struct
49 {
50 string sql = GetSequenceSqlByName(sequenceName);
51 return TopeveryDbContext.Database.SqlQuery<T>(sql).First();
52 }
53
54
55 /// <summary>
56 /// 获取序列值(默认int)
57 /// </summary>
58 /// <param name="sequenceName"></param>
59 /// <returns></returns>
60 public int GetSequenceValueByName(string sequenceName)
61 {
62 return GetSequenceValueByName<int>(sequenceName);
63 }
64 }
View Code
今天就讲这么多了。

ABP理论基础篇
发表⼀些关于ABP基础理论性的⽂章
摘要: "返回总⽬录" 本篇⽬录 "介绍" " MVC" " WEB API" " Core" 【以后补上】 "客户端类库" "内部原理" 介绍CSRF【Cross Site Request Forgery】跨站请求伪造是⼀种攻击类型,⼀般指的是⼀个恶意的⽹站、
posted @ tkbSimplest 阅读(4209) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "Clock" "时区" "绑定器和转换器" 介绍虽然有些应⽤针对的是⼀个特定的时区,但是也有⼀些应⽤针对多个不同的时区。

为了满⾜这些需求,ABP为datetime操作提供了通⽤的基础设施。

Clock Clock 是⽤于处理 DateTime 类型的主要操作类posted @ tkbSimplest 阅读(2947) |
摘要: "返回总⽬录" Hangfire是⼀个综合的后台⼯作管理者。

你可以将Hangfire集成到ABP中,这样就可以不使⽤默认的后台⼯作管理者了。

但你仍然可以为Hangfire使⽤相同的后台⼯作API 。

这样,你的代码就独⽴于Hangfire了,但是,如果你喜欢的话,也可以直接使⽤Hangfire的A
posted @ tkbSimplest 阅读(2970) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "后台⼯作" "后台⼯作者" "让你的应⽤程序⼀直运⾏" 介绍 ABP提供了后台⼯作和后台⼯作者,它们会在应⽤程序的后台线程中执⾏⼀些任务。

后台⼯作后台⼯作以队列和持续的⽅式在后台给⼀些即将被执⾏的任务排队。

你可能因为某些原因需要后台⼯作,⽐如:执⾏长
posted @ tkbSimplest 阅读(7610) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "安装" "建⽴连接" "内置功能" "你⾃⼰的SignaR代码" 介绍 "Abp.Web.SignalR" 使得在基于ABP的应⽤程序中使⽤ SignalR 相当容易。

查看 "SignalR⽂档" 获取更多关于SignalR的详细信息。

安装服务端将 "Ab
posted @ tkbSimplest 阅读(4423) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "订阅通知" "发布通知" "⽤户通知管理者" "实时通知" "通知存储" "通知定义" 介绍通知(Notification)⽤于告知⽤户系统中的特定事件。

ABP提供了基于实时通知基础设施的发布订阅模型(pub/sub)。

发送模型给⽤户发送通知有两种⽅式posted @ tkbSimplest 阅读(5992) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "安装" "安装Nuget包" "配置" "测试" 介绍从官⽅⽹站上可以看到:“启⽤了Swagger API,就可以获得交互式⽂档,⽣成和发现客户端SDK”。

安装将 "Swagger" 集成到基于ABP的应⽤中是很容易的事情。

安装Nuget包将 "Swa
posted @ tkbSimplest 阅读(4762) |
摘要: "返回总⽬录" 如果你的应⽤中使⽤了 OWIN ,那么需要在主项⽬(⼀般来说是指Web项⽬)中添加 "Abp.Owin" 的nuget包,然后像下⾯那样在OWIN的 Startup ⽂件中调⽤ UseAbp() 扩展⽅法:
posted @ tkbSimplest 阅读(3696) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "安装" "创建控制器" "例⼦" "样例项⽬" <a name='intro' </a 介绍 OData 在 "其官⽹" 的定义是:允许以⼀种简单且标准的⽅式创建和使⽤可查询的、可互操作的 RESTful APIs。

在ABP中也可以...
posted @ tkbSimplest 阅读(2641) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "AbpController基类" "本地化" "异常处理" "响应结果的包装" "审计⽇志" "授权" "⼯作单元" "其他" <a name='intro' </a 介绍 ABP通过Abp.Web.Mvc nuget包集...
posted @ tkbSimplest 阅读(3245) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "AbpWebViewPage基类" <a name='intro' </a 介绍 ABP通过 Abp.Web.Mvc Nuget包集成了MVC视图。

因此你可以像常规那样创建MVC视图。

<a name='base' </a AbpWebViewPag...
posted @ tkbSimplest 阅读(2020) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "AbpApiController基类" "本地化" "审计⽇志" "授权" "⼯作单元" "其他" <a name='intro' </a 介绍 ABP通过 Abp.Web.Api Nuget包集成了 Web AP...
posted @ tkbSimplest 阅读(3649) |
摘要: "返回总⽬录" 本篇⽬录 "构建动态Web API控制器" "ForAll ⽅法" "重写ForAll ⽅法" "Http动词" "动态Javascript代理" "Ajax参数" "单⼀服务脚本" "Angular⽀持" "Durandal⽀持" "返回结果封装" 【2016/3/28 更新】 "
posted @ tkbSimplest 阅读(6900) |
摘要: "返回总⽬录" 本篇⽬录 "Ajax" "Notification" "Message" "UI block和busy" "事件总线" "Logging" "其他⼯具功能" 说在前⾯的话不知不
觉,我们送⾛了2015,同时迎来了2016。

我相信,每⼀个⼈,都会在过去的⼀年有所失,但我更相信,我们所得
posted @ tkbSimplest 阅读(9377) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "功能类型" "定义功能" "检查功能" "功能管理者" "版本说明" <a name='intro' </a 介绍⼤多数的 Saas (多租户)应⽤都有不同功能的版本(包)。

因此,他们可以给租户(客户)提供不同的价格和功能选项。

...
posted @ tkbSimplest 阅读(3411) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "定义权限" "检查权限" "使⽤AbpAuthorize特性" "使⽤IPermissionChecker" "Razor视图" "客户端(Javascript)" "权限管理者" 介绍⼏乎所有的企业应⽤都在不同程度使⽤了授权。

授权的⽬的在于检查是否允许⽤户在
posted @ tkbSimplest 阅读(7584) |
摘要: "返回总⽬录" 本篇⽬录 "应⽤语⾔" "本地化资源" "获取本地化⽂本" "扩展本地化资源" "最佳实践" 应⽤语⾔⼀个应⽤⾄少有⼀种UI语⾔,许多应⽤不⽌有⼀种语⾔。

ABP为应⽤提供了⼀个灵活的本地化系统。

第⼀件事情就是声明⽀持哪些语⾔。

这个是在模块的PreInitialize ⽅法中完成
posted @ tkbSimplest 阅读(4442) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "开启错误处理" "⾮Ajax请求" "展⽰异常信息" "UserFriendlyException" "Error模型" "Ajax请求" "异常事件" <a name='intro' </a 介绍在⼀个web应⽤中,异常通常是在...
posted @ tkbSimplest 阅读(7206) |
摘要: "返回总⽬录" 本篇⽬录 "创建菜单" "注册导航提供者" "展⽰菜单" 每⼀个web应⽤在页⾯之间都有⼀些要导航的菜单。

ABP提供了公⽤的基础设施来创建菜单并将菜单展⽰给⽤户。

<a name='create' </a 创建菜单⼀个应⽤可能由不同的模块组成,每个模块可能有它⾃⼰的菜...
posted @ tkbSimplest 阅读(2580) |
摘要: "返回总⽬录" 本篇⽬录 "验证介绍" "使⽤数据注解" "⾃定义验证" "标准化" <a name='intro' </a 验证介绍⾸先应该验证应⽤的输⼊。

⽤户或者其它应⽤都可以向该应⽤发送输⼊。

在⼀个web应⽤中,验证通常要实现两次:在客户端和服务器端。

客户端的验证⼤多数情况下... posted @ tkbSimplest 阅读(3624) |
摘要: "返回总⽬录" 本篇⽬录 "为何需要DTO" "领域层抽象" "数据隐藏" "序列化和懒加载问题" "DTO惯例和验证" "DTO和实体的⾃动映射" "使⽤特性和扩展⽅法进⾏映射" "帮助接⼝" DTO⽤于应⽤层和展现层间的数据传输。

展现层调⽤具有DTO参数的 ...
posted @ tkbSimplest 阅读(6408) |
摘要: "返回总⽬录" 本篇⽬录 "IApplicationService接⼝" "ApplicationService类" "⼯作单元" "数据库连接和事务管理" "⾃动保存更改" "更多" "应⽤服务的⽣命周期" 应⽤服务⽤于将领域逻辑暴露给展现层。

展现层调⽤具有DTO参数的应⽤服务,使⽤领域对象来执⾏
posted @ tkbSimplest 阅读(3042) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "预定义过滤器" "关闭过滤器" "开启过滤器" "设置过滤器参数" "定义⾃定义过滤器" "其他ORM" <a name='intro' </a 介绍软删除模式通常⽤于不会真正从数据库删除⼀个实体⽽是仅仅将它标记为"已删除的"。

这样,...
posted @ tkbSimplest 阅读(4362) |
摘要: "返回总⽬录" 本篇⽬录 "事件总线" "定义事件" "触发事件" "处理事件" "句柄注册" "取消注册" 在C 中,我们可以在⼀个类中定义⾃⼰的事件,⽽其他的类可以注册该事件,当某些事情发⽣时,可以通知到该类。

这对于桌⾯应⽤或者独⽴的windows服务来说是⾮常有⽤的。

但对于⼀个web应⽤来说是
posted @ tkbSimplest 阅读(6252) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "创建内嵌⽂件" "暴露内嵌⽂件" "使⽤内嵌⽂件" <a name='intro' </a 介绍在⼀个web应⽤中,有供客户端使⽤的javascript,css,xml等⽂件。

它们⼀般是作为分离的⽂件被添加到web项⽬中并发布。

有时,我们需要将...
posted @ tkbSimplest 阅读(1843) |
摘要: "返回总⽬录" 本篇⽬录 "公共连接和事务管理⽅法" "ABP中的连接和事务管理" "仓储类" "应⽤服务" "⼯作单元" "⼯作单元详解" "关闭⼯作单元" "⾮事务的⼯作单元" "⼯作单元⽅法调⽤其它" "⼯作单元作⽤域" "⾃动保存" "IRepository.GetAll()⽅法" "Uni
posted @ tkbSimplest 阅读(6432) |
摘要: "返回总⽬录" 本篇⽬录 "Nuget包" "配置" "实体映射" "仓储" "仓储基类" "实现仓储" "⾃定义仓储⽅法" "阅读其他" ABP可以使⽤任何ORM框架⼯作,并且已经内置了 NHibernate 集成。

这篇⽂章会解释如何在ABP中使⽤NHibernate。

阅读本⽂的前提是假设你已经熟posted @ tkbSimplest 阅读(2013) |
摘要: "返回总⽬录" 本篇⽬录 "Nuget包" "创建DbContext" "仓储" "仓储基类" "实现仓储" "⾃定义仓储⽅法" "阅读其他" ABP可以使⽤任何ORM框架⼯作,并且已经内置了 EntityFramework 集成。

这篇⽂章会解释如何在ABP中使⽤Entit...
posted @ tkbSimplest 阅读(4080) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "IDomainService接⼝和DomainService类" "样例" "创建⼀个接⼝" "服务实现" "调⽤应⽤服务" "⼀些讨论" "何不只使⽤应⽤服务" "如何强制使⽤领域服务" <a name='intro' </...
posted @ tkbSimplest 阅读(6573) |
摘要: "返回总⽬录" 本篇⽬录 "IRepository接⼝" "查询" "插⼊" "更新" "删除" "其他" "关于异步⽅法" "仓储实现" "管理数据库连接" "仓储的⽣命周期" "仓储最佳实践" Martin Fowler对仓储的定义位于领域层和数据映...
posted @ tkbSimplest 阅读(6510) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "配置" "通过特性开启/关闭" "注意" "我项⽬中的例⼦" <a name="intro" </a 介绍维基百科说: “审计跟踪(也叫审计⽇志)是与安全相关的按照时间顺序的记录,记录集或者记录源,它们提供了活动序列的⽂档证据,这些活动序...
posted @ tkbSimplest 阅读(4735) |
摘要: "返回总⽬录" 本篇⽬录 "实体类" "惯例接⼝" "审计" "软删除" "激活/未激活" "IEntity接⼝" 实体是DDD(领域驱动设计)的核⼼概念之⼀。

Eirc Evans是这样描述的实体的:“它根本上不是通过属性定义的,⽽是通过⼀系列连续性和标识定义的”。

因此,实...
posted @ tkbSimplest 阅读(5813) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "定义设置" "获取设置值" "更改设置" "关于缓存" 介绍每个应⽤程序都需要存储⼀些设置信息,然后在应⽤程序中的某个地⽅使⽤这些设置。

ABP提供了健壮的基础设施来存储或检索服务端和客户端的应⽤程序,租户,⽤户级别的可⽤设置。

⼀个设置⼀般是存储在数据库(
posted @ tkbSimplest 阅读(5040) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "ICacheManager" "ICache" "ITypedCache" "配置" <a name='intro' </a 介绍 ABP提供了缓存的抽象,它内部使⽤了这个缓存抽象。

虽然默认的实现使⽤了MemoryCache,但是也可以为其他的...
posted @ tkbSimplest 阅读(5714) |
摘要: "返回总⽬录" 本篇⽬录 "服务端" "获取Logger" "基类中的Logger" "配置" "客户端" <a name='server' </a 服务端 ABP使⽤的是Castle Windsor的 "⽇志记录设备" 。

它可以和不同的⽇志类库⼀起⼯作,⽐如 Log4Net...
posted @ tkbSimplest 阅读(4129) |
摘要: "返回总⽬录" 本篇⽬录 "介绍" "注⼊Session" "使⽤Session属性" <a name='intro' </a 介绍当应⽤程序要求⽤户登录时,那么应⽤程序也需要知道当前⽤户正在执⾏的操作。

虽然本⾝在展现层提供了Session对象,但ABP也提供了在任何需...
posted @ tkbSimplest 阅读(5583) |
摘要: "返回总⽬录" 本篇⽬录 "什么是依赖注⼊" "传统⽅式产⽣的问题" "解决办法" "依赖注⼊框架" "ABP中的依赖注⼊基础设施" "注册" "解析" "其他" " MVC和 Web API集成" "最后提⽰" 什么是依赖注⼊维基百科说:“依赖注⼊是⼀种软件设计模式,
posted @ tkbSimplest 阅读(10516) |
摘要: "返回总⽬录" "查看更详细信息以及下载源代码请查看原⽂档" ABP v0.9.2.0 | 【更新⽇期:2016/6/6 11:21:28 】解决⽅案转换成xproj/project.json格式。

添加了Appveyor持续集成。

创建了EntityCache基类,可以轻松缓存实体了。

添加了可
posted @ tkbSimplest 阅读(3748) |
摘要: "返回总⽬录" 本篇⽬录 "框架" "测试基" ABP已经发布在Nuget上,这⾥是所有包的列表。

<a name='framework' </a 框架 "Abp" Abp系统的核⼼包。

所有其他的包都依赖这个包。

"Abp.Web" 提供了MVC和Web API都使⽤的⼀些通⽤类和资源 ...
posted @ tkbSimplest 阅读(2452) |
摘要: "返回总⽬录" 本篇⽬录 "什么是多租户" "ABP中的多租户" <a name='what' </a 什么是多租户维基百科:“软件多租户是指⼀种软件架构,在这种软件架构中,软件的⼀个实例运⾏在服务器上并且为多个租户服务”。

⼀个租户是⼀组共享该软件实例特定权限的⽤户。

有了多租户...
posted @ tkbSimplest 阅读(10271) |
摘要: "返回总⽬录" 本篇⽬录 "配置ABP" "配置模块" "为模块创建配置" 为了在应⽤启动时配置ABP和模块,ABP提供了⼀个基础设施。

<a name='abp' </a 配置ABP 配置ABP是在模块的 PreInitialize 事件中完成的。

下⾯的代码摘⾃Github上的Task...
posted @ tkbSimplest 阅读(6634) |
摘要: "返回总⽬录" 本篇⽬录 "模块介绍" "⽣命周期事件" "模块依赖" "⾃定义模块⽅法" <a name='intro' </a 模块介绍 ABP提供了构建模块并将这些模块组合起来创建应⽤的基础设施。

⼀个模块可以依赖另⼀个模块。

⼀般来说,⼀个程序集可以认为是⼀个模块。

⼀个模块是由⼀... posted @ tkbSimplest 阅读(8258) |
摘要: "返回总⽬录" ⾃从写这个系列博客之后,发现很多园友还是希望有个直接运⾏的demo,其实在github上就有官⽅的demo,我直接把这demo的链接放到这⾥吧,另外,我分析,这些找不到demo的同学,很可能是不怎么⽤github,可能的原因就是英⽂不好。

所以还是希望程序员多看看英⽂⽂档,⼀开始看...
posted @ tkbSimplest 阅读(10950) |
摘要: "返回总⽬录" 为了和2016年春节赛跑,完成该系列博客,我牺牲了今天中午的时间来完成该系列的第⼀篇————开篇介绍。

开篇介绍嘛,读过⼤学教材的同学都知道,这玩意总是那么⽆聊,跟考试没关系,⼲脆直接跳过,呵呵,多么美好的⼤学时光啊!不过,现在想想,开篇介绍确实不怎么重要,它只是告诉我们今后我要开始讲
posted @ tkbSimplest 阅读(15066) |
摘要: ⽬前,我已经完成了Module Zero的翻译,请查看我的 "《Module Zero学习⽬录》" 。

到现在为⽌,使⽤ABP框架开发正式项⽬已经3个⽉有余了,期间翻阅了⼤量⽂档资料,包括ABP官⽹的⽂档,以及 @阳光铭睿的系列教程。

但是我今天想回过头来,照着ABP官⽹的英⽂⽂档,加上我这⼏个⽉
posted @ tkbSimplest 阅读(76835) |
BP
摘要: ABP 中异常处理的思路是很清晰的。

⼀共五种类型的异常类。

AbpInitializationException⽤于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationException异常就可以,⽆须做额外处理。

这类异常往往是需要维护⼈员介⼊分析的。

其他四个异常都在Abp posted @ ZHK的博客阅读(1309) |
摘要: 通过AD作为⽤户认证的数据源。

整个管理⽤户认证逻辑就在LdapAuthenticationSource类中实现。

LdapSettingProvider:定义LDAP 的setting和提供DefautValue。

主要提供配置访问AD数据库的账号信息。

LdapSettings/ILdapSettin
posted @ ZHK的博客阅读(769) |
摘要: AbpZeroDbContext:配置ABP.Zero中定义的entity的Dbset EntityFrameworkModelBuilderExtensions:给PrimitivePropertyConfiguration添加了扩展⽅法⽤于创建Index。

AbpZeroDbModelBuild
posted @ ZHK的博客阅读(782) |
摘要: ABP Zero模块中需要配置的地⽅主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语⾔和资源。

UserManagementConfig/IUserManagementConfig:定义了⼀个配置项,⽤于配置外部认证源。

默认情况下,ABP Zero使⽤AbpUser表作为⾝份认证
posted @ ZHK的博客阅读(643) |
摘要: ABP Zero模块扩展了ABP基础框架中的本地化功能,实现了通过数据库管理本地化的功能。

其通过数据库保存本地化语⾔及其资源。

ApplicationLanguage:代表本地化语⾔的实体类。

⼀种语⾔就是⼀个ApplicationLanguage实例。

ApplicationLanguageProv
posted @ ZHK的博客阅读(893) |
摘要: ABP Zero模块通过⾃定义实现 Identity完成⾝份认证功能, 对 Identity做了较⼤幅度的扩展。

同时重写了ABP核⼼模块中的permission功能,以实现授权。

注意:ABP仅仅使⽤了 Identity的⾝份认证功能,但没有使⽤
posted @ ZHK的博客阅读(1650) |
摘要: AuditLog: 继承⾃Entity<long>的实体类。

封装AuditLog的信息。

AuditingStore: 实现了IAuditingStore接⼝,实现了将AuditLog的信息保存到数据库的功能。

其通过IRepository<AuditLog, long>实例完成对数据库的操作。

Ba
posted @ ZHK的博客阅读(776) |
摘要: ABP的Zero模块以数据库为数据源实现了ABP框架中的tenant management (multi-tenancy), role management, user management, session, authorization (permission management), setti
posted @ ZHK的博客阅读(1340) |
摘要: ABP对HangFire的集成主要是通过实现IBackgroundJobManager接⼝的HangfireBackgroundJobManager类完成的。

HangfireBackgroundJobManager:实现了接⼝IBackgroundJobManager中的⽅法EnqueueAsyn
posted @ ZHK的博客阅读(880) |
摘要: 如果对OData不熟悉的话可参考OData的初步认识⼀⽂以获取OData的⼀些初步知识。

API.Odata 模块唯⼀⽤处就是提供了⼀个泛型版本的ODataController,实现了Controller代码的常⽤。

AbpODataEntityController<TEntity, TPrimar
posted @ ZHK的博客阅读(379) |
摘要: ABP提供Script Proxy WebApi为所有的Dynamic WebApi⽣成访问这些WebApi的JQuery代理,AngularJs代理以及TypeScriptor代理。

这些个代理就是javascript脚本,通过这些代理可以简单的访问Dynamic webApi。

如下实例演⽰⼀个最
posted @ ZHK的博客阅读(816) |
摘要: 这⾥的内容和ABP 动态webapi没有关系。

除了动态webapi,ABP必然是⽀持使⽤传统的webApi。

ABP.Web.Api模块中实现了⼀些同意的基础功能,以⽅便我们创建和使⽤ webApi。

AbpApiController:这是⼀个抽象基类,继承⾃ApiController,
posted @ ZHK的博客阅读(1092) |
摘要: 动态WebAPI应该算是ABP中最Magic的功能之⼀了吧。

开发⼈员⽆须定义继承⾃ApiController的类,只须重⽤Application Service中的类就可以对外提供WebAPI的功能,这应该算是对DRY的最佳诠释了. 如下图所⽰,⼀⾏代码就为所有实现了IApplicationServ
posted @ ZHK的博客阅读(4390) |
摘要: ABP.Web.Mvc模块主要完成两个任务:第⼀,通过⾃定义的AbpController抽象基类封装ABP核⼼模块中的功能,以便利的⽅式提供给我们创建controller使⽤。

第⼆,⼀些常见的基础功能的实现。

AbpController:这是⼀个抽象基类,继承⾃MVC Controller,是A posted @ ZHK的博客阅读(703) |
摘要: ABP.Web模块并不复杂,主要完成ABP系统的初始化和⼀些基础功能的实现。

AbpWebApplication : 继承⾃的HttpApplication类,主要完成下⾯三件事⼀,在Application_Start完成AbpBootstrapper的初始化。

整个ABP系统的初始化就
posted @ ZHK的博客阅读(766) |
摘要: Realtime Realtime是ABP底层模块提供的功能,⽤于管理在线⽤户。

它是使⽤SignalR实现给在线⽤户发送通知的功能的前提IOnlineClient/OnlineClient: 封装在线⽤户的信息 OnlineClientManager/IOnlineClientManager: ⽤
posted @ ZHK的博客阅读(1005) |
摘要: 这个模块封装了Automapper,使其更易于使⽤。

下图描述了改模块涉及的所有类之间的关系。

AutoMapAttribute,AutoMapFromAttribute和AutoMapToAttribute:这三个attribute⽤于标注⼀个类到另外⼀个类的map⽅向。

AutoMapperHe
posted @ ZHK的博客阅读(1106) |
摘要: ABP 通过StackExchange.Redis类库来操作Redis数据库。

AbpRedisCacheModule:完成ABP.RedisCache模块的初始化(完成常规的依赖注⼊) AbpRedisCacheConfig:定义了connectionStringKey和databaseIdApp
posted @ ZHK的博客阅读(1005) |
摘要: 这个Module通过建⽴⼀个MongoDbRepositoryBase<TEntity> 基类,封装了对MongoDb数据库的操作。

这个module通过引⽤MongoDB.Driver,MongoDB.Bson,MongoDB.Driver.Core,MongoDB.Driver.Legacy类库
posted @ ZHK的博客阅读(720) |
摘要: 这个模块简单,且⽆实际作⽤。

⼀般实际项⽬中都有⽤数据库做持久化,⽤了数据库就⽆法⽤这个MemoryDB 模块了。

原因在于ABP 限制了UnitOfWork的类型只能有⼀个(前⽂以作介绍),⼀般⽤了数据库的必然要注⼊efUnitOfWork. ⽽注⼊了efUnitOfWork就不能在注⼊MemoryDb
posted @ ZHK的博客阅读(520) |
摘要: IRepository:接⼝定义了Repository常见的⽅法 AbpRepositoryBase:实现了IRepository接⼝的常见⽅法 EfRepositoryBase:实现了AbpRepositoryBase中定义的抽象⽅法:GetAll,Insert,Delete,Update。

在实际
posted @ ZHK的博客阅读(1496) |
摘要: 本⽂是ABP核⼼项⽬源码分析的最后⼀篇,介绍⼀些前⾯遗漏的功能 AbpSession AbpSession: ⽬前这个和CLR的Session没有什么直接的联系。

当然可以⾃定义的去实现IAbpSession使之与CLR的Session关联 IAbpSession:定义如下图中的四个属性。

NullA
posted @ ZHK的博客阅读(923) |
摘要: IEventData/EventData: 封装了EventData信息,触发event的源对象和时间 IEventBus/EventBus: 定义和实现了了⼀系列注册,注销和触发事件处理函数的⽅法。

EventBus定义了⼀个Dictionary容器来存放事件和处理该事件的对象(其实不是对象⽽是Fa
posted @ ZHK的博客阅读(1066) |
摘要: NotificationDefinition: ⽤于封装Notification Definnition 的信息。

注意和Notification 的区别,如果把Notification看成是具体的消息内容,NotificationDefinition则是对这个消息⾃⾝的定义(可理解为消息的类型)。

posted @ ZHK的博客阅读(720) |
摘要: Permission:⽤于定义⼀个Permission,⼀个permission可以包含多个⼦Permission. PermissionDictionary:继承⾃Dictionary<string, Permission>类,很明显是⼀个⽤于存储permission对象的字典。

IPermiss
posted @ ZHK的博客阅读(1111) |
摘要: MenuDefinition:封装了导航栏上的主菜单的属性。

MenuItemDefinition:封装了主菜单的⼦菜单的属性。

⼦菜单可以引⽤其他⼦菜单构成⼀个菜单树 UserMenu/UserMenuItem:封装了⽤于显⽰给⽤户的菜单/以及⼦菜单集合。

ABP通过MenuDefinition/M
posted @ ZHK的博客阅读(646) |
摘要: Feature是什么?Feature就是对function的分类⽅法,其与function的关系就⽐如Role和User的关系⼀样。

ABP中Feature具有以下属性:其中最重要的属性是name,⽤以表⽰feature的Identity,⼀个feature⼀个name. ⼀个Feature可以有
posted @ ZHK的博客阅读(924) |
摘要: IApplicationService : 空接⼝,起标识作⽤。

所有实现了IApplicationService 的类都会被⾃动注⼊到容器中。

同时所有IApplicationService对象都会被注⼊⼀些拦截器(例如:auditing, UnitOfWork等)以实现AOP AbpServiceB
posted @ ZHK的博客阅读(859) |
摘要: 审计跟踪(也叫审计⽇志)是与安全相关的按照时间顺序的记录,它们提供了活动序列的⽂档证据,这些活动序列可以在任何时间影响⼀个特定的操作。

AuditInfo:定义如下图中需要被Audit的信息。

AuditedAttribute:⽤于标识⼀个⽅法或⼀个类的所有⽅法都需要启⽤Auditing功能。

D
posted @ ZHK的博客阅读(1179) |
摘要: 以下图中描述的接⼝和类都在Abp项⽬的Runtime/Validation, UI/Inputs⽬录下的。

在当前版本的ABP(0.83)中这些接⼝和类并没有实际使⽤到。

阅读代码时可以忽略,⽆需浪费时间去寻找其是如何被ABP使⽤的(本⽂的⽬的)。

这些接⼝和类最终都是通过IInputType被Feat posted @ ZHK的博客阅读(659) |
摘要: 对传给Application service对象中的⽅法的DTO参数,ABP都会在⽅法真正执⾏前⾃动完成validation(根据标注到DTO对象中的validate规则)。

ABP是如何做到的? 思路⽆外乎通过Castle的拦截器实现AOP。

本⽂主要分析ABP是如何设计。

Ivalidate: 空
posted @ ZHK的博客阅读(1257) |
摘要: IDTO:空接⼝,⽤于标注Dto对象。

ComboboxItemDto:⽤于combobox/list中Item的DTO NameValueDto<T>/NameValueDto:⽤于name value键值对的DTO, name为string类型, value为泛型或string类型。

Entit
posted @ ZHK的博客阅读(2166) |。

相关文档
最新文档