序
致谢
关于本书
- 谁适合阅读本书
- 如何阅读本书
- 书写惯例
- 此区块会提示当前范例源代码的所在位置。
- 注意事项。
- 相关信息。
- 通常是笔者的碎碎念、个人观点(不见得完全正确或放诸四海皆准),或额外的补充说明。
- 需要准备的工具
- 范例程序与补充材料
关于作者
- Part I:基础篇
第 1 章:导论
- 本章范例源代码位置:
- 为什么需要 DI?
- 动态绑定
- 可维护性
- 宽松耦合
- 可测试性
- 平行开发
- 什么是 DI?
- 入门范例—非 DI 版本
- 开放/封闭原则
- 入门范例—DI 版本
- 提炼接口(Extract Interface)
- 控制反转(IoC)
- 何时该用 DI?
- 本章回顾
第 2 章:DI 用法与模式
- 本章范例源代码位置:
- 设计模式梗概
- 小引-电器与接口
- Null Object 模式
- Decorator 模式
- Composite 模式
- Adapter 模式
- Factory 模式
- 注入方式
- 构造函数注入
- 已知应用例
- 用法
- 范例程序
- 属性注入
- 已知应用例
- 用法
- 范例程序
- Strategy 模式
- 方法注入
- 已知应用例
- 用法
- 范例
- Ambient Context 模式
- Context 的中文术语
- 已知应用例
- 范例程序(一)
- 范例程序(二)
- Service Locator 模式
- 过犹不及-再谈构造函数注入
- 半吊子注入
- 阻止相依蔓延
- 解决「半吊子注入」
- 过度注入
- 重构成参数对象
- 重载构造函数
- 重构成 Façade 模式
- 单一责任原则
- 本章回顾
第 3 章:DI 容器
- 本章范例源代码位置:
- DI 容器简介
- 对象组合
- 自制 DI 容器
- DI 容器与 Factory 模式
- 自制 DI 容器—2.0 版
- 现成的 DI 容器
- MEF 是 DI 容器吗?
- 对象组合
- 使用 XML
- 使用代码
- 自动注册
- 自动或手动?隐含或明确?
- 自动匹配
- 深层解析
- 对象生命周期管理
- 内存泄漏问题
- 生命周期选项
- 拦截
- AOP 与拦截
- 使用 Decorator 模式实现拦截
- 本章回顾
- Part II:实战篇
第 4 章:DI 与 ASP.NET MVC 分层架构
- 本章范例源代码位置:
- 分层架构概述
- 关于洋葱架构
- Repository 模式
- Repository 参考数据
- MVC 分层架构范例 V1-紧密耦合
- 本节范例的源代码位置:
- 领域模型
- 数据访问层
- 应用层
- 表示层
- 审视目前设计
- MVC 分层架构范例 V2-宽松耦合
- 真实案例:为了方便测试而切换数据源
- 此范例的源代码位置:
- 领域模型
- 数据访问层
- 应用层
- 表示层
- 组合对象
- 切换 Controller 工厂
- 审视目前设计
- 避免过度设计
- YAGNI
- MVC 分层架构范例 V3-简化一些
- 此范例的源代码位置:
- 数据访问层
- 应用层
- 表示层
- 审视目前设计
- 一个 HTTP 请求搭配一个 DbContext
- 本节范例的源代码位置:
- ASP.NET MVC 5 的
IDependencyResolver - 实现自定义的
IDependencyResolver组件 - 此范例的源代码位置:
- ASP.NET MVC 5 应用程序的生命周期
- 本章回顾
第 5 章:DI 与 ASP.NET Web API
- 本章范例源代码位置:
- ASP.NET Web API 管线
- 讯息处理程序
- Controller 是怎样建成的?
- Controller 建立完成后
- 注入对象至 Web API Controller
- 抽换 IHttpControllerActivator 服务
- 纯手工打造
- 使用 DI 容器:Unity
- 抽换 IDependencyResolver 服务
- IDependencyResolver 与 IDependencyScope
- 纯手工 DI 范例
- 步骤 1:实现
IDependencyResolver接口 - 步骤 2:替换默认的类型解析器
- 使用 DI 容器:Unity
- 使用 DI 容器:Autofac
- 本章回顾
第 6 章:更多 DI 实现范例
- 本章范例的项目源代码位置:
- 共享代码
- DI 与 ASP.NET MVC 5
- 练习:使用 Unity
- Step 1:建立新项目
- Step 2:设定 Unity 容器
- 在一个 HTTP 请求的范围内共享同一个对象
- Step 3:建立 Controller
- DI 与 ASP.NET Web Forms
- 问题描述
- 解法
- 练习:使用 Unity
- Step 1:建立新项目
- Step 2:注册类型
- Step 3:编写 HTTP Handler
- Step 4:注册 HTTP Handler
- Step 5:编写测试页面
- 练习:使用 Unity 的 BuildUp 方法
- 练习:使用 Autofac
- 本练习的源代码项目为 WebFormsDemo.Autofac.csproj。
- Step 1:建立新项目
- Step 2:注册类型
- Step 3:编写 HTTP Handler
- Step 4:注册 HTTP Handler
- Step 5:编写测试页面
- DI 与 WCF
- 问题描述
- 解法
- 练习:使用 Unity
- Step 1:建立 WCF 服务
- Step 2:编写自定义的 ServiceHostFactory
- Step 3:编写自定义的 ServiceHost
- Step 4:实现 IContractBehavior 接口
- Step 5:实现 IInstanceProvider 接口
- Step 6:设定 Unity 容器
- Step 7:修改 Web.config
- Step 8:编写客户端程序
- 练习:使用 Autofac.Wcf 套件
- Step 1:建立 WCF 服务
- Step 2:编写自定义的 ServiceHostFactory
- Step 3:设定 Autofac 容器
- Step 4:修改 Web.config
- Step 5:编写客户端程序
- 本章回顾
- Part III:工具篇
第 7 章:Unity 学习手册
- 本章范例源代码位置:
- Unity 快速入门
- Hello, Unity!
- 注册类型对应
- 串接调用
- 注册现有对象
- 解析
- 解析一个对象:
Resolve - 具名注册与解析
- 解析多个对象:
ResolveAll - 注册与解析泛型
- 检查注册
- 使用配置文件来设定容器
- Unity 配置文件基本格式
- 加载配置文件设定
- 执行时期配置 vs. 设计时期配置
- 注册与解析-进阶篇
- 共享的范例程序
- 情境
- 设计
- 代码
- 自动注册
- 解决重复类型对应的问题
AllClasses类型WithMappings类型- 自动匹配
- 自动匹配规则
- 手动匹配
- 循环参考问题
- 注入参数
- 解析对象时改写注入之参数与对象
- 注入属性
- 延迟解析
- 使用
Lazy<T> - 使用自动工厂
- 注入自定义工厂
- 对象生命周期管理
- 默认的生命周期
- 指定生命周期
- Transient vs. Per-Resolve
- 方便记忆的比喻——如果你能接受的话
- Per-Request 生命周期
- 阶层式容器
- 选择生命周期管理员
- 拦截
- 使用 Unity 容器实现拦截
- Step 1:加入 Unity 的拦截扩展包
- Step 2:实现拦截行为
- Step 3:注册拦截行为
- 结语
附录一:DI 容器实务建议
- 容器设定
- 避免对同一个组件(DLL)重复扫描两次或更多次
- 使用不同类型来注册不同用途的组件
- 使用非静态类型来建立与设定 DI 容器
- 不要另外建立一个 DLL 项目来集中处理依赖关系的解析
- 为个别组件加入一个初始化类型来设定依赖关系
- 扫描组件时,尽量避免指定组件名称
- 生命周期管理
- 优先使用 DI 容器来管理对象的生命周期
- 考虑使用子容器来管理 Per-Request 类型的对象
- 在适当时机调用容器的 Dispose 方法
- 组件设计相关建议
- 避免建立深层的巢状对象
- 考虑使用泛型来封装抽象概念
- 考虑使用 Adapter 或 Façade 来封装 3rd-party 组件
- 不要一律为每个组件定义一个接口
- 对于同一层(layer)的组件,可依赖其具象类型
- 动态解析
- 尽量避免把 DI 容器直接当成 Service Locator 来使用
- 考虑使用对象工厂或
Func<T>来处理晚期绑定
附录二:初探 ASP.NET 5 的自带 DI 容器
- 练习步骤
- 步骤 1:建立项目
- 步骤 2:加入必要组件
- 步骤 3: 将 Web API 组件加入 ASP.NET 管线
- 步骤 4:加入 API Controller
- 步骤 5:编写测试用的服务类型
- 步骤 6:注入相依对象至 Controller 的构造函数
- 结语
