仓库近四万行,其中 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 篇,合集在 部署器 · 开源记。