仓库近四万行,其中 129 个文件、20001 行是内嵌的第三方压缩库源码(SharpZipLib,跟着程序一起分发),剩下 248 个文件、18794 行是我自己写的。近四万行里有一半是别人的代码,要读的是那一半里的前半截。
工程一共十个,都挂在 IISDeployer. 下面。第一次 clone 下来的人不知道从哪看起,看引用关系就行:表按从上往下的读法排,每一行的「引用了谁」只指向它下面的行。
| 工程 | 引用了谁 | 它是干什么的 |
|---|---|---|
| Console | Definition、Deploy、Entities、Logging、Common、Core | 界面与入口。工具栏五个模块按钮、进度面板、日志窗口,60 文件 / 9653 行 |
| Core | Configure、Definition、Deploy、Common、Entities、ORM、Zip、Logging | 引擎。策略、执行器、插件加载、版本比较、事件分发,53 文件 / 5191 行 |
| Configure | Definition、Common、Deploy | 配置这一层的家:XML 加载器的基类、部署参数加载器,3 文件 / 52 行 |
| Deploy | Definition、Common | 部署动作的实现:站点、IIS、服务、配置、升级,9 文件 / 323 行 |
| Common | Definition | 通用工具:路径、文件、注册表、XML、并发、调度、工厂,28 文件 / 1803 行 |
| Entities | Definition | 数据实体:版本、事件、文件、插件、提供器、配置项,17 文件 / 304 行 |
| Logging | 谁都不引 | 日志:接口、实现、落盘处理器,13 文件 / 640 行 |
| ORM | 谁都不引 | 极简数据访问,一个仓储类 67 行 |
| Zip | 谁都不引 | 打包解包,内嵌的压缩库,129 文件 / 20001 行 |
| Definition | 谁都不引 | 契约层:51 个接口 + 9 个抽象类,761 行,没有一段实现 |
Console 是 WinForms 界面,是唯一知道用户按了哪个按钮的地方。 九个工程它引了六个,剩下 ORM、Zip、Logging 是引擎自己在用。
Core 是引擎,也是改动最集中的地方。 策略、执行器、插件加载、版本比较、事件分发都在这,具体加载器只剩三个。
Configure 是配置这一层的家,只有两个类。 一个是 XML 加载器的基类,所有配置加载器都从它派生;另一个把参数目录里的配置读成对象。它原来只是个空工程,挪进来是为了让「动配置」有确定的落点。
Deploy 只有九个文件、三百多行,却是真正在动服务器的地方。 站点、IIS、服务、配置、升级各一个实现。想看一次发版到底做了什么动作,从这九个文件看比看 Core 省劲。
Common 和 Entities 都只引 Definition,也不引对方,谁先读都行。 一个是通用工具,一个是数据实体,加起来两千来行。
Logging、ORM、Zip 谁也不引,这条最有用。 出度是零,换一个实现不影响上层编译。Configure 不在这组,换掉它的两个类只影响 Core 那三个加载器。
Definition 在最底下,谁都不引,所以谁都能引它。 它没引任何第三方库,这是它待在最底层的前提;把这 51 个接口读完就够了。
分层换来的好处落在改代码上:改行为只动 Core 和 Deploy,改配置的基类与参数加载器只动 Configure,改日志、压缩、数据访问只动 Logging、Zip、ORM。 这三组互不牵连,是这套结构唯一必须守住的地方。
(等价改写,名字换掉了)路径相关的常量集中在一个静态类里,运行时按枚举取出相对路径,再和工作根目录拼成绝对路径:
public enum PathKind {
AppRoot, Template, Backup, Logs,
TempUpgrade, UpgradeOut, Cloud
}
public static class LayoutPaths {
public static string BackupRoot = "runtime/backup";
public static string LogRoot = "runtime/appLogs";
}
想改工作目录里的目录名,只需要动这一处静态类和那个枚举,不用满仓库找拼字符串的地方。
引擎启动时先在工作根目录下建四个目录:Components\IIS、Components\Services、Components\Sites、参数目录。其余目录都从上面那张表里按名字取,不会临时拼。
分层是这套东西最值钱的一处设计。代价也明摆着,33 处嵌套单例、27 处静态 Factory,用来在没有 DI 容器的环境里把各层接起来。这是 net461 下没引第三方容器时的做法,具体代价在我另一组文章里算过账:33 个单例撑起来的部署引擎。
如果你只想用,看到这里可以停。要改的话从 Console 往下读:工具栏五个模块按钮,顺着找到引擎入口,再看策略。反过来从 Definition 读也行,几十行接口读完就知道这个系统对外承诺了什么。
上一篇是这个项目的门面:发版那五步,我为什么没做成命令行。
本篇是《部署器 · 开源记》第 2 篇,合集在 部署器 · 开源记。