图书目录

目    录

第I部分 C#和.NET 6简介

第1章  C#和.NET 6基础  3

1.1 .NET平台的一些重要优势  3

1.2 理解.NET支持周期  4

1.3 .NET平台的组成模块概述  4

1.3.1 基类库的作用  5

1.3.2 C#带来了什么  5

1.3.3 托管与非托管代码  6

1.4 使用.NET支持的其他编程语言  7

1.5 .NET程序集概述  7

1.5.1 CIL的作用  7

1.5.2 CIL的优势  10

1.5.3 将CIL编译为特定于平台的指令  10

1.5.4 .NET类型元数据的作用  10

1.5.5 程序集清单的作用  11

1.6 理解公共类型系统  12

1.6.1 CTS类类型  12

1.6.2 CTS接口类型  13

1.6.3 CTS结构类型  13

1.6.4 CTS枚举类型  13

1.6.5 CTS委托类型  14

1.6.6 CTS类型成员  14

1.6.7 CTS固有数据类型  14

1.7  理解公共语言规范  15

1.8 理解.NET运行时  17

1.9 区分程序集、名称空间和类型  17

1.9.1 在代码中访问名称空间  19

1.9.2  全局using语句(10.0新增)  19

1.9.3 文件作用域的名称空间(10.0新增)  21

1.9.4 引用外部程序集  21

1.10 使用ildasm.exe探索程序集  21

1.11  小结  22

第2章  构建C#应用程序  23

2.1 安装.NET 6  23

2.1.1 理解.NET版本号  23

2.1.2 确认.NET 6安装成功  23

2.2 使用Visual Studio构建.NET Core应用程序  25

2.2.1 安装Visual Studio 2022 (Windows)  25

2.2.2 试用Visual Studio 2022  26

2.3 使用Visual Studio Code构建.NET Core应用程序  35

2.4 找到.NET Core和C#的文档  38

2.5  小结  38

第II部分 核心C#编程

第3章  C#的核心编程结构(I)  41

3.1 分解一个简单的C#程序(C# 10更新)  41

3.1.1 使用Main()方法的不同形式(7.1更新)  43

3.1.2  使用顶级语句(9.0新增)  44

3.1.3 指定应用程序错误代码(9.0更新)  45

3.1.4 处理命令行实参(9.0更新)  47

3.1.5  在Visual Studio 2022中指定命令行实参  48

3.2 System.Environment类中的其他成员(10.0更新)  49

3.3 使用System.Console类  50

3.3.1 使用Console类执行基本的输入和输出(I/O)操作  51

3.3.2 设置控制台输出的格式  52

3.3.3 设置数值数据的格式  53

3.3.4 在控制台应用程序之外设置数值数据的格式  54

3.4 使用系统数据类型和对应的C#关键字  54

3.4.1  理解变量声明和初始化  55

3.4.2 使用固有数据类型和new操作符(9.0更新)  56

3.4.3 理解数据类型的类层次  57

3.4.4 理解数值数据类型的成员  59

3.4.5 理解System.Boolean的成员  59

3.4.6 理解System.Char的成员  59

3.4.7 解析字符串数据的值  60

3.4.8 使用TryParse从字符串数据解析值  60

3.4.9 使用System.DateTime和System.Timespan(10.0更新)  61

3.4.10 使用System.Numerics名称空间  62

3.4.11 使用数字分隔符(7.0新增)  63

3.4.12 使用二进制字面值(7.0/7.2新增)  63

3.5 使用字符串数据  64

3.5.1 执行基本字符串操作  64

3.5.2 执行字符串连接  65

3.5.3 使用转义字符  65

3.5.4 执行字符串插值  66

3.5.5 定义原样字符串(8.0更新)  69

3.5.6 字符串的相等性  69

3.5.7 String是不可变的  71

3.5.8 使用System.Text.StringBuilder类型  73

3.6 缩窄和加宽数据类型转换  73

3.6.1 使用checked关键字  75

3.6.2 设置项目级别的溢出检查(项目文件)  77

3.6.3 设置项目级别的溢出检查(Visual Studio)  77

3.6.4 使用unchecked关键字  78

3.7 理解隐式类型的局部变量  78

3.7.1 隐式声明数字  80

3.7.2 理解隐式类型的变量的限制  80

3.7.3 隐式类型的数据是强类型的数据  81

3.7.4 理解隐式类型的局部变量的有用性  82

3.8 使用C#的迭代结构  82

3.8.1 使用for循环  83

3.8.2 使用foreach循环  83

3.8.3 在foreach结构中使用隐式类型  84

3.8.4 使用while和do/while循环结构  84

3.9 作用域简介  85

3.10 使用决策结构和关系/相等性操作符  85

3.10.1 使用if/else语句  86

3.10.2 使用相等性和关系操作符  86

3.10.3 在if/else中使用模式匹配(7.0新增)  87

3.10.4 模式匹配的改进(9.0新增)  87

3.10.5 使用条件操作符(7.2、9.0更新)  88

3.10.6 使用逻辑操作符  89

3.10.7 使用switch语句  90

3.10.8 执行switch语句的模式匹配(7.0新增,9.0更新)  92

3.10.9 使用switch表达式(8.0新增)  94

3.11 小结  96

第4章  C#的核心编程结构(II)  97

4.1 理解C#的数组  97

4.1.1 C#的数组初始化语法  98

4.1.2 理解隐式类型的局部数组  99

4.1.3 定义一个Object数组  99

4.1.4 使用多维数组  100

4.1.5 将数组用作实参或返回值  101

4.1.6 使用System.Array基类  102

4.1.7 使用索引和范围(8.0新增,10.0更新)  103

4.2 理解方法  105

4.2.1 理解表达式体成员  105

4.2.2 理解局部函数(7.0新增,9.0更新)  106

4.2.3 理解静态局部函数(8.0新增)  107

4.3 理解方法参数  107

4.3.1 理解方法参数的修饰符  108

4.3.2 理解默认的参数传递行为  108

4.3.3 使用out修饰符(7.0更新)  109

4.3.4 使用ref修饰符  111

4.3.5 使用in修饰符(7.2新增)  111

4.3.6 使用params修饰符  112

4.3.7 定义可选参数  113

4.3.8 使用命名实参(7.2更新)  114

4.3.9 理解方法重载  115

4.3.10 检查参数是否为null(10.0更新)  118

4.4 理解枚举类型  118

4.4.1 控制枚举的底层存储  119

4.4.2 声明枚举变量  120

4.4.3 使用System.Enum类型  121

4.4.4 动态发现枚举的名称-值对  121

4.4.5 使用枚举、标志和位操作  122

4.5 理解结构  124

4.5.1 创建结构变量  125

4.5.2 结构的构造函数(10.0更新)  126

4.5.3 使用字段初始值(10.0新增)  127

4.5.4 使用只读结构(7.2新增)  127

4.5.5 使用只读成员(8.0新增)  128

4.5.6  使用ref结构(7.2新增)  129

4.5.7 使用可释放的ref结构(8.0新增)  129

4.6 理解值类型和引用类型  130

4.6.1 使用值类型、引用类型和赋值操作符  130

4.6.2 使用包含引用类型的值类型  132

4.6.3 按值传递引用类型  133

4.6.4 按引用传递引用类型  135

4.6.5 关于值类型和引用类型的一些细节  135

4.7 理解C#的可空类型  136

4.7.1 使用可空值类型  137

4.7.2 使用可空引用类型(8.0新增,10.0更新)  138

4.7.3 处理可空类型  141

4.8 理解元组(7.0新增/更新)  143

4.8.1 开始使用元组  143

4.8.2 使用推断的变量名称(7.1更新)  144

4.8.3  理解元组的相等性/不相等性(7.3新增)  144

4.8.4 理解作为方法返回值的元组  145

4.8.5 理解元组中使用的丢弃操作符  145

4.8.6 理解switch表达式的元组模式匹配(8.0新增)  145

4.8.7 解构元组(10.0更新)  146

4.9 小结  148

第III部分  使用C#进行面向对象编程

第5章  理解封装  151

5.1 C#的类类型简介  151

5.2 理解构造函数  153

5.2.1 理解默认构造函数的作用  154

5.2.2 定义自定义构造函数  154

5.2.3 继续介绍默认构造函数  156

5.3 理解this关键字的作用  157

5.3.1 使用this链接构造函数调用  158

5.3.2 观察构造函数的执行流  160

5.3.3 可选实参示例  162

5.4 理解static关键字  162

5.4.1 定义静态字段数据  163

5.4.2 定义静态方法  165

5.4.3 定义静态构造函数  166

5.4.4 定义静态类  168

5.4.5 通过C#的using关键字导入静态成员  168

5.5 定义面向对象编程的支柱  169

5.5.1 理解封装的作用  169

5.5.2 理解继承的作用  170

5.5.3 理解多态性的作用  171

5.6 理解C#的访问修饰符(7.2更新)  172

5.6.1 使用默认访问修饰符  173

5.6.2 使用访问修饰符和嵌套类型  173

5.7 理解第一个支柱:C#的封装服务  174

5.7.1 使用传统的访问器和修改器实现封装  175

5.7.2 使用属性进行封装  177

5.7.3 在类定义内使用属性  179

5.7.4 只读属性  181

5.7.5 只写属性  181

5.7.6 在属性中混合使用私有的和公有的get/set方法  182

5.7.7 再次讨论static关键字:定义静态属性  182

5.7.8 使用属性模式进行模式匹配(8.0新增)  182

5.7.9 展开的属性模式(10.0新增)  184

5.8 理解自动属性  185

5.8.1 使用自动属性  186

5.8.2 自动属性和默认值  187

5.8.3 初始化自动属性  188

5.9 理解对象初始化  189

5.9.1 查看对象初始化语法  189

5.9.2 使用仅初始化设置器(9.0新增)  190

5.9.3 使用初始化语法调用自定义构造函数  191

5.9.4 使用初始化语法初始化数据  192

5.10 使用常量字段数据和只读字段数据  193

5.10.1 理解常量字段数据  193

5.10.2 理解只读字段  194

5.10.3 理解静态只读字段  195

5.11 理解分部类  195

5.12 记录(9.0新增)  197

5.12.1 使用标准属性语法的不可变记录类型  198

5.12.2 使用位置语法的不可变记录类型  199

5.12.3 可变记录类型  200

5.12.4 记录类型的值相等性  200

5.12.5 使用with表达式复制记录类型  201

5.13 记录结构(10.0新增)  202

5.13.1 可变的记录结构  202

5.13.2 不可变的记录结构  203

5.13.3 解构记录结构  203

5.14 小结  203

第6章  理解继承和多态性  205

6.1 理解继承的基本机制  205

6.1.1 指定现有类的父类  206

6.1.2 多基类  207

6.1.3 使用sealed关键字  208

6.2 回顾Visual Studio的类图  208

6.3 理解OOP的第二个支柱:继承的细节  210

6.3.1 使用base关键字调用基类的构造函数  211

6.3.2 保守家族秘密:protected关键字  213

6.3.3 添加密封类  213

6.3.4 理解记录类型的继承(9.0新增)  214

6.4 包含/委托编程  217

6.5 理解OOP的第三个支柱:C#对多态性的支持  220

6.5.1 使用virtual和override关键字  220

6.5.2 在Visual Studio/ Visual Studio Code中重写虚拟方法  223

6.5.3 密封虚拟成员(10.0更新)  223

6.5.4 理解抽象类  224

6.5.5 理解多态接口  225

6.5.6 理解成员隐藏  229

6.6 理解基类/派生类的强制转换规则  230

6.6.1 使用C#的as关键字  232

6.6.2 使用C#的is关键字(7.0、9.0更新)  233

6.6.3 继续讨论模式匹配(7.0新增)  235

6.7 理解超级父类:System.Object  236

6.7.1 重写System.Object.ToString()  238

6.7.2 重写System.Object.Equals()  238

6.7.3 重写System.Object.GetHashCode()  239

6.7.4 测试修改后的Person类  240

6.7.5 使用System.Object的静态成员  241

6.8 小结  242

第7章  理解结构化异常处理  243

7.1 错误、bug和异常  243

7.2 .NET异常处理的作用  244

7.2.1 .NET异常处理的构造块  244

7.2.2 System.Exception基类  245

7.3 最简单的示例  246

7.3.1 抛出通用异常  248

7.3.2  捕获异常  249

7.3.3 将throw作为表达式(7.0新增)  250

7.4 配置异常的状态  250

7.4.1 TargetSite属性  250

7.4.2 StackTrace属性  251

7.4.3 HelpLink属性  251

7.4.4 Data属性  252

7.5 系统级异常(System.SystemException)  254

7.6 应用程序级异常(System.ApplicationException)  254

7.6.1 构建自定义异常,第一次尝试  255

7.6.2 构建自定义异常,第二次尝试  256

7.6.3 构建自定义异常,第三次尝试  257

7.7 处理多个异常  258

7.7.1  一般性的catch语句  260

7.7.2 重新抛出异常  260

7.7.3 内部异常  261

7.7.4 finally块  261

7.7.5 异常过滤器  262

7.8 使用Visual Studio调试未处理的异常  263

7.9 小结  264

第8章  使用接口  265

8.1 理解接口类型  265

8.2 定义自定义接口  268

8.3 实现接口  269

8.4 在对象级别调用接口成员  271

8.4.1 获取接口引用:as关键字  272

8.4.2 获取对象引用:is关键字(7.0更新)  272

8.5 默认实现(8.0新增)  273

8.6 静态构造函数和成员(8.0新增)  274

8.7 将接口用作参数  274

8.8 将接口用作返回值  276

8.9 接口类型的数组  276

8.10 使用Visual Studio或Visual Studio Code实现接口  278

8.11 显式接口实现  279

8.12 设计接口层次  281

8.12.1 具有默认实现的接口层次(8.0新增)  282

8.12.2 接口类型的多继承  283

8.13 IEnumerable和IEnumerator接口  285

8.13.1 使用yield关键字构建迭代器方法  287

8.13.2 构建命名迭代器  290

8.14 ICloneable接口  291

8.15 IComparable接口  295

8.15.1 使用IComparer指定多个排序顺序  298

8.15.2 自定义属性和自定义排序类型  299

8.16 小结  299

第9章  理解对象的生存期  301

9.1 类、对象和引用  301

9.2 对象生存期的基础知识  302

9.2.1 new的CIL  303

9.2.2 将对象引用设置为null  304

9.3 判断对象是否仍然存活  304

9.4 理解对象的“代”  305

9.5 垃圾回收类型  307

9.6 System.GC类型  307

9.7 构建可终结对象  311

9.7.1 重写System.Object.Finalize()  312

9.7.2 详细说明终结过程  313

9.8 构建可释放对象  314

9.8.1 重用C#的using关键字  315

9.8.2 using声明(8.0新增)  317

9.9 构建可终结、可释放的类型  317

9.10 理解对象的延迟实例化  320

9.11 小结  323

第IV部分 C#高级编程

第10章  集合和泛型  327

10.1 创建集合类的动机  327

10.1.1 System.Collections名称空间  328

10.1.2 System.Collections.Specialized名称空间简介  330

10.2 非泛型集合的问题  330

10.2.1 性能问题  331

10.2.2 类型安全性问题  334

10.2.3 初识泛型集合  337

10.3 泛型类型参数的作用  337

10.3.1 为泛型类/结构指定类型参数  338

10.3.2 为泛型成员指定类型参数  339

10.3.3 为泛型接口指定类型参数  340

10.4 System.Collections.Generic名称空间  341

10.4.1 理解集合初始化语法  342

10.4.2 使用List<T>类  343

10.4.3 使用Stack<T>类  345

10.4.4 使用Queue<T>类  346

10.4.5 使用PriorityQueue<TElement, TPriority>类(10新增)  347

10.4.6 使用SortedSet<T>类  347

10.4.7 使用Dictionary<TKey, TValue>类  349

10.5 System.Collections.ObjectModel名称空间  350

10.6 创建自定义泛型方法  352

10.7 创建自定义泛型结构和类  354

10.7.1 泛型的默认值表达式  355

10.7.2  default字面值表达式(7.1新增)  356

10.7.3 泛型的模式匹配(7.1新增)  357

10.8 约束类型参数  357

10.8.1 使用where关键字的示例  358

10.8.2 没有操作符约束  359

10.9 小结  360

第11章  C#的高级语言特性  361

11.1 理解索引器方法  361

10.1.1 使用字符串值索引数据  363

10.1.2 重载索引器方法  364

10.1.3 多维索引器  364

10.1.4 接口类型中的索引器定义  365

11.2 理解操作符重载  366

11.2.1 重载二元操作符  366

11.2.2 +=和-=操作符  368

11.2.3 重载一元操作符  369

11.2.4 重载相等性操作符  369

11.2.5  重载比较操作符  370

11.2.6 关于操作符重载的最后一点说明  371

11.3 理解自定义类型转换  371

11.3.1 回顾:数值转换  371

11.3.2 回顾:相关类类型之间的转换  371

11.3.3 创建自定义转换例程  372

11.3.4 Square类型的其他显式转换  375

11.3.5 定义隐式转换例程  375

11.4 理解扩展方法  376

11.4.1 定义扩展方法  377

11.4.2 调用扩展方法  378

11.4.3 导入扩展方法  378

11.4.4 扩展实现了特定接口的类型  379

11.4.5 扩展方法GetEnumerator支持foreach循环(9.0新增)  380

11.5 理解匿名类型  381

11.5.1 定义匿名类型  382

11.5.2 匿名类型的内部表示  382

11.5.3  ToString()和GetHashCode()的实现  384

11.5.4 匿名类型的相等性语义  384

11.5.5 在匿名类型中包含匿名类型  386

11.6 使用指针类型  386

11.6.1 unsafe关键字  388

11.6.2 使用*和&操作符  389

11.6.3 非安全的(和安全的)交换函数  390

11.6.4 通过指针访问字段(->操作符)  391

11.6.5 stackalloc关键字  392

11.6.6 通过fixed关键字钉住类型  392

11.6.7 sizeof关键字  393

11.7 小结  393

第12章  委托、事件和lambda表达式  395

12.1 理解委托类型  395

12.1.1 在C#中定义委托类型  396

12.1.2 System.MulticastDelegate和System.Delegate基类  398

12.2 最简单的委托示例  399

12.3 使用委托发送对象状态通知  401

12.3.1 启用多播  404

12.3.2 从委托的调用列表中移除目标  405

12.3.3 方法组转换语法  406

12.4 理解泛型委托  407

12.5 理解C#事件  410

12.5.1 C#的event关键字  411

12.5.2 事件的底层机制  413

12.5.3 监听传入的事件  413

12.5.4 使用Visual Studio简化事件注册  415

12.5.5 创建自定义事件实参  416

12.5.6 EventHandler<T>泛型委托  417

12.6 理解C#的匿名方法  418

12.6.1 访问局部变量  419

12.6.2 对匿名方法使用static (9.0新增)  420

12.6.3  在匿名方法中使用丢弃操作符(9.0新增)  421

12.7 理解lambda表达式  421

12.7.1 分解lambda表达式  423

12.7.2 在多条语句中处理实参  424

12.7.3 具有多个(或零个)参数的lambda表达式  425

12.7.4 在lambda表达式中使用static关键字(9.0新增)  426

12.7.5 在lambda表达式中使用丢弃操作符(9.0新增)  427

12.7.6 使用lambda表达式修改CarEvents示例  427

12.7.7 lambda和表达式体成员(7.0更新)  428

12.8 小结  428

第13章  LINQ to Objects  431

13.1 特定于LINQ的编程结构  431

13.1.1 隐式确定局部变量的类型  432

13.1.2 对象和集合初始化语法  432

13.1.3 lambda表达式  433

13.1.4 扩展方法  433

13.1.5 匿名类型  434

13.2 理解LINQ的作用  434

13.2.1 LINQ表达式是强类型的  435

13.2.2 核心的LINQ程序集  435

13.3 对原始数组应用LINQ查询  435

13.3.1 使用扩展方法的版本  437

13.3.2 不使用LINQ的版本  437

13.3.3 LINQ结果集的反射  438

13.3.4 LINQ和隐式确定类型的局部变量  439

13.3.5 LINQ和扩展方法  441

13.3.6 延迟执行的作用  441

13.3.7 立即执行的作用  443

13.4 返回LINQ查询的结果  445

13.5 对集合对象应用LINQ查询  446

13.5.1 访问被包含的子对象  447

13.5.2 对非泛型集合应用LINQ查询  448

13.5.3 使用OfType<T>()过滤数据  448

13.6 探索C#的LINQ查询操作符  449

13.6.1 基本选择语法  450

13.6.2 获取数据子集  451

13.6.3 分页数据  451

13.6.4 使用范围分页数据(10.0新增)  453

13.6.5 使用块分页数据(10.0新增)  453

13.6.6 投影新的数据类型  454

13.6.7 投影到不同的数据类型  455

13.6.8 使用Enumerable获取计数  456

13.6.9 获取未枚举的计数(10.0新增)  456

13.6.10 翻转结果集  457

13.6.11 排序表达式  457

13.6.12 将LINQ用作更好的韦恩图工具  458

13.6.13 删除重复项  460

13.6.14 LINQ聚合操作  461

13.7 LINQ查询表达式的内部表示  462

13.7.1 使用查询操作符构建查询表达式(回顾)  463

13.7.2 使用Enumerable类型和lambda表达式构建查询表达式  463

13.7.3 使用Enumerable类型和匿名方法构建查询表达式  464

13.7.4 使用Enumerable类型和原始委托构建查询表达式  465

13.8 小结  466

第14章  进程、应用程序域和加载上下文  467

14.1 Windows进程的作用  467

14.2 使用.NET Core与进程交互  469

14.2.1 枚举运行中的进程  470

14.2.2 调查具体进程  471

14.2.3 调查进程的线程集合  471

14.2.4 调查进程的模块集合  473

14.2.5 在代码中启动和终止进程  474

14.2.6 使用ProcessStartInfo类控制进程的启动过程  475

14.2.7 通过ProcessStartInfo使用OS动词  476

14.3 理解.NET应用程序域  477

14.3.1 System.AppDomain类  478

14.3.2 与默认应用程序域交互  478

14.3.3 枚举已加载的程序集  479

14.4 使用应用程序加载上下文隔离程序集  480

14.5 总结进程、应用程序域和加载上下文  482

14.6 小结  482

第15章  多线程、并行编程和异步编程  483

15.1 进程/AppDomain/上下文/线程的关系  483

15.1.1 并发问题  484

15.1.2 线程同步的作用  484

15.2 System.Threading 名称空间  485

15.3 System.Threading.Thread类  485

15.3.1 获取当前执行线程的统计信息  486

15.3.2 Name属性  487

15.3.3 Priority属性  487

15.4 手动创建辅助线程  488

15.4.1 使用ThreadStart委托  488

15.4.2 使用 ParameterizedThreadStart 委托  490

15.4.3 AutoResetEvent 类  491

15.4.4 前台线程和后台线程  491

15.5 并发性问题  492

15.5.1 使用C#的lock关键字进行同步  494

15.5.2 使用System.Threading.Monitor类型进行同步  496

15.5.3 使用System.Threading.Interlocked类型进行同步  497

15.6 使用定时器回调进行编程  497

15.7 理解ThreadPool  499

15.8 使用任务并行库进行并行编程  500

15.8.1 System.Threading.Tasks名称空间  501

15.8.2 Parallel类的作用  501

15.8.3 使用Parallel类的数据并行性  501

15.8.4 在辅助线程上访问UI元素  505

15.8.5 Task类  505

15.8.6 处理取消请求  506

15.8.7 使用 Parallel 类实现任务并行性  507

15.9 并行LINQ查询(PLINQ)  510

15.9.1 选择使用PLINQ查询  511

15.9.2 取消PLINQ查询  511

15.10 使用async/await模式的异步调用  512

15.10.1 C#关键字async和await (7.1、9.0更新)  513

15.10.2 SynchronizationContext和async/await  514

15.10.3 ConfigureAwait的作用  514

15.10.4 异步方法的命名约定  515

15.10.5 不返回数据的异步方法  515

15.10.6 有多个await的async方法  518

15.10.7 从同步方法中调用异步方法  519

15.10.8 在catch和finally块中使用await关键字  521

15.10.9 泛化的异步返回类型(7.0新增)  521

15.10.10 局部函数使用async/await(7.0新增)  521

15.10.11 取消async/await操作  522

15.10.12 异步流(8.0新增)  525

15.10.13 Parallel.ForEachAsync()方法(10.0新增)  526

15.10.14 使用async/await更新Book Reader应用程序  527

15.10.15 async和await总结  527

15.11 小结  528

第V部分 .NET Core程序集编程

第16章  构建和配置类库  531

16.1 定义自定义名称空间(10.0更新)  531

16.1.1 使用完全限定名称解决名称冲突  533

16.1.2 使用别名解决名称冲突  533

16.1.3 创建嵌套的名称空间  534

16.1.4 使用Visual Studio 2022更改根名称空间  535

16.1.5 使用项目文件更改根名称空间  535

16.2 .NET程序集的作用  536

16.2.1 程序集促进了代码重用  536

16.2.2 程序集确定了类型边界  536

16.2.3 程序集是可版本化的单元  537

16.2.4 程序集具有自我描述性  537

16.3 理解.NET程序集的格式  537

16.3.1 安装C++性能分析工具  537

16.3.2 操作系统(Windows)文件头  538

16.3.3 CLR文件头  538

16.3.4 CIL代码、类型元数据和程序集清单  539

16.3.5 可选的程序集资源  539

16.4 类库与控制台应用程序  540

16.5 .NET Standard与.NET (Core)类库  540

16.6 使用配置文件配置应用程序  541

16.6.1 多个配置文件  542

16.6.2 使用对象(10.0更新)  543

16.6.3 其他配置选项  545

16.7 构建和使用.NET类库  546

16.7.1 探索清单  548

16.7.2 探索CIL  549

16.7.3 探索类型元数据  550

16.7.4 构建C#客户端应用程序  551

16.7.5 构建Visual Basic客户端应用程序  552

16.7.6 跨语言继承的应用  553

16.7.7 将内部类型暴露给其他程序集  553

16.8 NuGet和.NET Core  554

16.8.1 使用NuGet打包程序集  554

16.8.2 引用NuGet包  555

16.9 发布控制台应用程序(.NET 5/6更新)  556

16.9.1 发布框架依赖型应用程序  557

16.9.2 发布自包含型应用程序  557

16.10 .NET如何定位程序集  559

16.11 小结  560

第17章  类型反射、延迟绑定、特性与动态类型  561

17.1 类型元数据的必要性  561

17.1.1 查看EngineStateEnum枚举的(部分)元数据  562

17.1.2 查看Car类型的(部分)元数据  563

17.1.3 TypeRef  564

17.1.4 记录定义的程序集  564

17.1.5 记录引用的程序集  565

17.1.6 记录字符串字面值  565

17.2 理解反射  566

17.2.1 System.Type类  566

17.2.2 使用System.Object.GetType()获取类型引用  567

17.2.3 使用typeof()获取类型引用  567

17.2.4 使用System.Type.GetType()获取类型引用  568

17.3 构建自定义的元数据查看器  568

17.3.1 反射方法  568

17.3.2 反射字段和属性  569

17.3.3 反射实现的接口  570

17.3.4 显示各种杂项  570

17.3.5 添加顶级语句  571

17.3.6 反射静态类型  572

17.3.7 反射泛型类型  572

17.3.8 反射方法参数和返回值  573

17.4 动态加载程序集  574

17.5 反射框架程序集  575

17.6 理解延迟绑定  577

17.6.1 System.Activator类  577

17.6.2 调用无参数的方法  578

17.6.3 调用带参数的方法  579

17.7 理解.NET特性的作用  580

17.7.1 特性消费者  580

17.7.2 在C#中应用特性  581

17.7.3 C#特性简写表示法  581

17.7.4 为特性指定构造函数参数  582

17.7.5 Obsolete特性的实际应用  582

17.8 构建自定义特性  583

17.8.1 应用自定义特性  584

17.8.2 命名属性语法  584

17.8.3 限制特性的使用  585

17.9 程序集级别的特性  585

17.10 在项目文件中添加程序集特性  586

17.11 使用提前绑定反射特性  587

17.12 使用延迟绑定反射特性  588

17.13 反射、延迟绑定和自定义特性的实际应用  589

17.14 构建可扩展的应用程序  590

17.14.1 构建多项目的ExtendableApp解决方案  590

17.14.2 构建CommonSnappableTypes.dll  593

17.14.3 构建C#插件  593

17.14.4 构建Visual Basic插件  594

17.14.5 为ExtendableApp添加代码  594

17.15 C#中dynamic关键字的作用  596

17.15.1 调用动态声明的数据的成员  598

17.15.2 dynamic关键字的应用范围  599

17.15.3 dynamic关键字的限制  600

17.15.4 dynamic关键字的实际应用  600

17.16 动态语言运行时的作用  600

17.16.1 表达式树的作用  601

17.16.2 表达式树的动态运行时查找  601

17.17 使用动态类型简化延迟绑定调用  602

17.18 小结  604

第18章  理解CIL和动态程序集的作用  607

18.1 学习CIL语法的动机  607

18.2 探究CIL指令、属性和操作码  608

18.2.1 CIL指令的作用  608

18.2.2 CIL属性的作用  609

18.2.3 CIL操作码的作用  609

18.2.4 CIL操作码/CIL助记符的区别  609

18.3 入栈与出栈:CIL的基于栈的本质  610

18.4 理解往返工程  611

18.4.1 CIL代码标签的作用  613

18.4.2 与CIL交互:修改*.il文件  614

18.4.3 使用ILASM.EXE编译CIL代码  614

18.4.4 使用Microsoft.NET.Sdk.il项目编译CIL代码  615

18.5 理解CIL指令和属性  616

18.5.1 在CIL中指定外部引用的程序集  616

18.5.2 在CIL中定义当前程序集  617

18.5.3 在CIL中定义名称空间  617

18.5.4 在CIL中定义类类型  618

18.5.5 在CIL中定义和实现接口  619

18.5.6 在CIL中定义结构  619

18.5.7 在CIL中定义枚举  620

18.5.8 在CIL中定义泛型  620

18.5.9 编译CILTypes.il文件  621

18.6 .NET基类库、C#和CIL数据类型映射  621

18.7 在CIL中定义类型成员  622

18.7.1 在CIL中定义字段数据  622

18.7.2 在CIL中定义类型构造函数  622

18.7.3 在CIL中定义属性  623

18.7.4 定义成员参数  623

18.8 深入探讨CIL操作码  624

18.8.1 .maxstack指令  626

18.8.2 在CIL中声明局部变量  626

18.8.3 在CIL中将参数映射到局部变量  627

18.8.4 隐藏的this引用  627

18.8.5 在CIL中表示迭代结构  628

18.8.6 CIL小结  629

18.9 理解动态程序集  629

18.9.1 探索System.Reflection.Emit名称空间  629

18.9.2 System.Reflection.Emit.ILGenerator的作用  630

18.9.3 发出动态程序集  631

18.9.4 发出程序集和模块集  633

18.9.5 ModuleBuilder类型的作用  633

18.9.6  发出HelloWorld类类型和字符串成员变量  634

18.9.7 发出构造函数  634

18.9.8 发出SayHello()方法  635

18.9.9 使用动态生成的程序集  635

18.10 小结  636

第VI部分  文件处理、对象序列化和数据访问

第19章  文件I/O和对象序列化  639

19.1 探索System.IO名称空间  639

19.2 Directory(Info)和File(Info)类型  640

19.3 使用DirectoryInfo类型  641

19.3.1 使用DirectoryInfo类型枚举文件  642

19.3.2 使用DirectoryInfo类型创建子目录  643

19.4 使用Directory类型  644

19.5 使用DriveInfo类型  644

19.6 使用FileInfo类  645

19.6.1 FileInfo.Create()方法  646

19.6.2 FileInfo.Open()方法  647

19.6.3 FileInfo.OpenRead()和FileInfo.OpenWrite()方法  648

19.6.4 FileInfo.OpenText()方法  649

19.6.5 FileInfo.CreateText()和FileInfo.AppendText()方法  649

19.7 使用File类型  649

19.8 Stream抽象类  651

19.9 使用StreamWriter和StreamReader  653

19.9.1 写入文本文件  654

19.9.2 读取文本文件  654

19.9.3 直接创建StreamWriter/StreamReader类型  655

19.10 使用StringWriter和StringReader  656

19.11 使用BinaryWriter和BinaryReader  657

19.12 在代码中监视文件  658

19.13 理解对象序列化  660

19.13.1 对象图的作用  660

19.13.2 创建示例类型和顶级语句  661

19.13.3 可扩展标记语言(XML)  663

19.13.4 JavaScript Object Notation (JSON)序列化  667

19.14 小结  677

第20章  使用ADO.NET访问数据  679

20.1 ADO.NET与ADO  679

20.2 理解ADO.NET数据提供程序  679

20.3 System.Data名称空间中的类型  681

20.3.1 IDbConnection接口的作用  682

20.3.2 IDbTransaction接口的作用  682

20.3.3 IDbCommand接口的作用  683

20.3.4 IDbDataParameter和IDataParameter接口的作用  683

20.3.5 IDbDataAdapater和IDataAdapter接口的作用  684

20.3.6 IDataReader和IDataRecord接口的作用  684

20.4 使用接口抽象数据提供程序  685

20.5 设置SQL Server和Azure Data Studio  687

20.5.1 安装SQL Server  687

20.5.2 安装SQL Server IDE  689

20.5.3 连接SQL Server  689

20.6 还原AutoLot数据库备份  691

20.6.1 将备份文件复制到容器中  691

20.6.2 使用SSMS还原数据库  692

20.6.3 使用Azure Data Studio还原数据库  693

20.7 创建AutoLot数据库  694

20.7.1 创建数据库  694

20.7.2 创建表  694

20.7.3 创建表关系  696

20.7.4 创建GetPetName()存储过程  697

20.7.5 添加测试记录  698

20.8 ADO.NET数据提供程序工厂模型  699

20.8.1 一个完整的数据提供程序工厂示例  700

20.8.2 数据提供程序工厂模型的一个潜在缺陷  703

20.9 深入了解连接、命令和数据读取器  704

20.9.1 使用连接对象  705

20.9.2 使用Command对象  707

20.9.3 使用数据读取器  708

20.10 使用创建、更新和删除查询  709

20.10.1 创建Car和CarViewModel类  710

20.10.2 添加InventoryDal类  711

20.10.3 添加删除逻辑  714

20.10.4 添加更新逻辑  715

20.10.5 使用参数化的命令对象  715

20.10.6 执行存储过程  718

20.11 创建一个基于控制台的客户端应用程序  720

20.12 理解数据库事务  720

20.13 在InventoryDal中添加一个事务方法  722

20.14 使用ADO.NET执行批量复制  724

20.14.1 探索SqlBulkCopy类  724

20.14.2 创建自定义数据读取器  725

20.14.3 执行批量复制  728

20.14.4 测试批量复制  729

20.15 小结  729

第VII部分 Entity Framework Core

第21章  Entity Framework Core简介  733

21.1 对象关系映射器  734

21.2 理解Entity Framework Core的作用  734

21.3 Entity Framework的组成模块  735

21.3.1 DbContext类  735

21.3.2 DbSet<T>类  740

21.3.3 ChangeTracker  741

21.3.4 实体  742

21.3.5 嵌入的实体类型  768

21.3.6 查询类型  771

21.4 查询的执行  773

21.5 跟踪与非跟踪查询  774

21.6 对比代码优先与数据库优先  775

21.7 EF Core全局工具的CLI命令  775

21.7.1 migrations命令  777

21.7.2 数据库命令  780

21.7.3 DbContext命令  780

21.8 小结  782

第22章  探索Entity Framework Core  783

22.1 创建记录  783

22.1.1 实体状态  783

22.1.2 使用Add添加一条记录  784

22.1.3 使用Attach添加一条记录  785

22.1.4 一次添加多条记录  785

22.1.5 添加记录时关于identity列的考虑事项  786

22.1.6 添加对象图  788

22.1.7 添加多对多记录  789

22.1.8 添加样本记录  790

22.2 清除样本数据  791

22.3 查询数据  791

22.3.1 获取全部记录  792

22.3.2 过滤记录  792

22.3.3 排序记录  793

22.3.4 分页  795

22.3.5 获取单条记录  796

22.3.6 聚合方法  801

22.3.7 Any()和All()  802

22.3.8 从存储过程获取数据  803

22.4 查询关联数据  804

22.4.1 提前加载  804

22.4.2 显式加载  808

22.4.3 延迟加载  809

22.5 更新记录  812

22.5.1 实体状态  812

22.5.2 更新跟踪实体  812

22.5.3 更新未跟踪实体  813

22.6 删除记录  814

22.6.1 实体状态  814

22.6.2 删除跟踪记录  814

22.6.3 删除非跟踪实体  815

22.6.4 捕获失败的级联删除  815

22.7 值得关注的EF Core特性  815

22.7.1 全局查询过滤器  816

22.7.2 在LINQ中使用原生SQL查询  818

22.7.3 投影  820

22.7.4 处理数据库生成的值  821

22.7.5 并发性检查  822

22.7.6 连接的弹性  824

22.7.7 数据库函数的映射  825

22.7.8 EF.Functions  826

22.7.9 批量处理语句  828

22.7.10 值转换器  829

22.7.11 阴影属性  831

22.7.12 SQL Server对时态表的支持  833

22.8 小结  840

第23章  使用Entity Framework Core构建数据访问层  841

23.1 创建AutoLot.Dal和AutoLot.Models项目  841

23.2 添加数据库视图  842

23.3 搭建DbContext和实体  843

23.4 切换到代码优先  843

23.4.1 创建DbContext设计时工厂  844

23.4.2 创建初始迁移  844

23.4.3  应用迁移  845

23.5 创建GlobalUsings文件  845

23.6 创建自定义异常  846

23.7 完成实体和ViewModel  847

23.7.1 实体  847

23.7.2 视图模型  865

23.8 更新ApplicationDbContext  867

23.8.1 添加映射的数据库函数  868

23.8.2 处理DbContext和ChangeTracker事件  868

23.8.3 重写约定  869

23.8.4 重写SaveChanges方法  869

23.9 创建下一个迁移和更新数据库  870

23.10 使用EF迁移来创建/更新数据库对象  870

23.10.1 添加MigrationHelpers类  871

23.10.2 创建和更新迁移  872

23.10.3 应用迁移  873

23.11 添加存储库  873

23.11.1 添加IBaseViewRepo接口  873

23.11.2 添加BaseViewRepo实现  874

23.11.3 添加IBaseRepo接口  875

23.11.4 添加BaseRepo实现  876

23.11.5 添加ITemporalTableBaseRepo接口  878

23.11.6 添加TemporalTableBaseRepo实现  878

23.11.7 特定于实体的存储库接口  880

23.11.8 实现特定于实体的存储库  882

23.11.9 更新GlobalUsings.cs文件  887

23.12  在代码中处理数据库和迁移  887

23.13 数据初始化  889

23.13.1 创建样本数据  889

23.13.2 加载样本数据  891

23.14 小结  892

第24章  测试AutoLot  893

24.1 测试的准备工作  893

24.1.1 创建项目  893

24.1.2 使AutoLot.Dal的内部方法和类对AutoLot.Dal.Tests可见  894

24.1.3 添加GlobalUsings文件  894

24.1.4 初识xUnit  895

24.1.5 配置项目和DbContext实例  896

24.1.6 添加BaseTest类  897

24.1.7 添加EnsureAutoLotDatabase测试夹具类  899

24.1.8 添加集成测试类  899

24.2 查询数据库  902

24.2.1 LINQ查询  903

24.2.2 时态查询  920

24.2.3 带LINQ的SQL查询  921

24.2.4  聚合方法  922

24.2.5 Any()和All()  923

24.2.6 从存储过程获取数据  924

24.3 创建记录  924

24.3.1 添加单条记录  925

24.3.2 使用Attach添加单条记录  925

24.3.3 一次性添加多条记录  926

24.3.4 添加对象图  927

24.4 更新记录  928

24.4.1 更新跟踪实体  928

24.4.2 更新非跟踪实体  929

24.4.3 更新记录时的并发性检查  930

24.5 删除记录  930

24.5.1 删除跟踪记录  931

24.5.2 删除非跟踪实体  931

24.5.3 捕获级联删除失败  932

24.5.4 删除记录时的并发性检查  932

24.6 小结  932

第VIII部分  Windows客户端开发

第25章  Windows Presentation Foundation和XAML简介  935

25.1 WPF背后的动机  935

25.1.1 统一不同的API  936

25.1.2 通过XAML提供关注点隔离  936

25.1.3 提供优化的渲染模型  937

25.1.4 简化复杂的UI编程  937

25.2 探索WPF程序集  938

25.2.1 Application类的作用  939

25.2.2 构造Application类  939

25.2.3 枚举Windows集合  940

25.2.4 Window类的作用  940

25.3 理解WPF XAML语法  943

25.3.1 Kaxaml简介  943

25.3.2 XAML的XML名称空间和XAML“关键字”  945

25.3.3 控制类和成员变量的可见性  947

25.3.4 XAML元素、XAML属性和类型转换器  947

25.3.5 理解XAML的属性元素语法  948

25.3.6 理解XAML附加属性  949

25.3.7 理解XAML标记扩展  949

25.4 使用Visual Studio构建WPF应用程序  951

25.4.1 WPF项目模板  952

25.4.2 工具箱和XAML设计器/编辑器  952

25.4.3 使用Properties窗口设置属性  953

25.4.4 使用Properties窗口处理事件  954

25.4.5 在XAML编辑器中处理事件  955

25.4.6 Document Outline窗口  956

25.4.7 启用或禁用XAML调试器  956

25.4.8 检查App.xaml文件  957

25.4.9 将Window的XAML标记映射到C#代码  958

25.4.10 BAML的作用  960

25.4.11 解决Main()的谜题  960

25.4.12 与应用程序级数据交互  961

25.4.13 处理Window对象的关闭  962

25.4.14 拦截鼠标事件  962

25.4.15 拦截键盘事件  963

25.5 小结  964

第26章  WPF控件、布局、事件和数据绑定  965

26.1 WPF的核心控件  965

26.1.1 WPF的Ink控件  966

26.1.2 WPF的文档控件  966

26.1.3 WPF中的常用对话框  966

26.2 Visual Studio的WPF设计器概述  966

26.2.1 在Visual Studio中使用WPF控件  967

26.2.2 使用Document Outline编辑器  967

26.3 使用面板控制内容布局  968

26.3.1 在Canvas面板中定位内容  969

26.3.2 在WrapPanel面板中定位内容  970

26.3.3 在StackPanel面板中定位内容  972

26.3.4 在Grid面板中定位内容  973

26.3.5 使用GridSplitter类型的Grid  974

26.3.6 在DockPanel面板中定位内容  975

26.3.7 为面板类型启用滚动  976

26.3.8 使用Visual Studio设计器配置面板  976

26.4 使用嵌套面板构建窗口的框架  979

26.4.1 构建菜单系统  980

26.4.2 以可视化方式构建菜单  981

26.4.3 构建工具栏  981

26.4.4 构建状态栏  982

26.4.5 完成UI设计  982

26.4.6 实现MouseEnter/MouseLeave事件处理程序  983

26.4.7 实现拼写检查逻辑  983

26.5 理解WPF命令  984

26.5.1 内置的Command对象  984

26.5.2 将命令连接到Command属性  985

26.5.3 将命令连接到任意操作  986

26.5.4 使用Open和Save命令  987

26.6 理解路由事件  988

26.6.1 路由冒泡事件的作用  989

26.6.2 继续或停止冒泡  990

26.6.3 路由隧道事件的作用  990

26.7 深入介绍WPF的API和控件  992

26.8 构建Ink API选项卡  993

26.8.1 设计工具栏  993

26.8.2 RadioButton控件  994

26.8.3 添加Save、Load和Delete按钮  994

26.8.4 添加InkCanvas控件  994

26.8.5 预览窗口  995

26.8.6 处理Ink API选项卡的事件  995

26.8.7 在Toolbox中添加控件  995

26.8.8 InkCanvas控件  996

26.8.9 ComboBox控件  998

26.8.10 保存、加载和清空InkCanvas数据  999

26.9 WPF的数据绑定模型简介  1000

26.9.1 构建Data Binding选项卡  1000

26.9.2 建立数据绑定  1001

26.9.3 DataContext属性  1001

26.9.4 格式化绑定的数据  1002

26.9.5 使用IValueConverter进行数据转换  1002

26.9.6 在代码中建立数据绑定  1003

26.9.7 构建DataGrid选项卡  1004

26.10 理解依赖属性的作用  1006

26.10.1 检查现有的依赖属性  1008

26.10.2 关于CLR属性封装器的重要说明  1010

26.11 构建自定义依赖属性  1010

26.11.1 添加一个数据验证例程  1013

26.11.2 响应属性变化  1013

26.12 小结  1014

第27章  WPF图形渲染服务  1015

27.1 理解WPF的图形渲染服务  1015

27.2 使用形状渲染图形数据  1016

27.2.1 在画布上添加矩形、椭圆形和线条  1017

27.2.2 从画布中删除矩形、椭圆形和线条  1020

27.2.3 使用折线和多边形  1020

27.2.4 使用路径  1021

27.3 WPF的画刷和钢笔  1024

27.3.1 使用Visual Studio配置画刷  1024

27.3.2 在代码中配置画刷  1026

27.3.3 配置钢笔  1027

27.4 应用图形变换  1027

27.4.1 初识变换  1028

27.4.2 变换画布数据  1029

27.5 使用Visual Studio的变换编辑器  1030

27.5.1  构建初始布局  1030

27.5.2 在设计时应用变换  1032

27.5.3 在代码中变换画布  1032

27.6 使用绘图和几何图形渲染图形数据  1033

27.6.1 使用几何图形构建DrawingBrush  1034

27.6.2 使用DrawingBrush进行填充  1034

27.6.3 在DrawingImage中包含绘图类型  1035

27.7 使用矢量图形  1035

27.7.1 将示例矢量图形文件转换为XAML  1036

27.7.2 将图形数据导入WPF项目中  1036

27.7.3 与符号交互  1037

27.8 使用可视化层渲染图形数据  1037

27.8.1 Visual基类及其派生类  1038

27.8.2 DrawingVisual类的简单用法  1038

27.8.3 将可视化数据渲染到自定义布局管理器  1039

27.8.4 响应命中测试操作  1041

27.9 小结  1042

第28章  WPF资源、动画、样式和模板  1043

28.1 理解WPF的资源系统  1043

28.2 使用对象(逻辑)资源  1047

28.2.1 Resources属性的作用  1047

28.2.2 定义窗口范围的资源  1047

28.2.3 {StaticResource}标记扩展  1049

28.2.4 {DynamicResource}标记扩展  1050

28.2.5 应用程序级别的资源  1050

28.2.6 定义合并资源字典  1051

28.2.7 定义一个只包含资源的程序集  1051

28.3 理解WPF的动画服务  1052

28.3.1 Animation类类型的作用  1053

28.3.2 To、From和By属性  1053

28.3.3 Timeline基类的作用  1054

28.3.4 在C#代码中编写动画  1054

28.3.5 控制动画的节奏  1055

28.3.6 翻转和循环动画  1056

28.4 使用XAML编写动画  1057

28.4.1 故事板的作用  1057

28.4.2 事件触发器的作用  1058

28.4.3 使用离散的关键帧的动画  1058

28.5 理解WPF样式的作用  1059

28.5.1 定义和应用样式  1060

28.5.2 覆盖样式设置  1060

28.5.3 TargetType对样式的影响  1060

28.5.4 继承现有样式  1062

28.5.5 定义带触发器的样式  1062

28.5.6 定义带多个触发器的样式  1063

28.5.7 动画样式  1063

28.5.8 在代码中指定样式  1064

28.6 逻辑树、可视化树和默认模板  1065

28.6.1 通过代码检查逻辑树  1065

28.6.2 通过代码检查可视化树  1067

28.6.3 通过代码检查控件的默认模板  1067

28.7 使用触发器框架构建控件模板  1070

28.7.1 模板作为资源  1071

28.7.2 使用触发器包含视觉提示  1071

28.7.3 {TemplateBinding}标记扩展的作用  1072

28.7.4 ContentPresenter的作用  1073

28.7.5 在样式中包含模板  1073

28.8 小结  1074

第29章  WPF通知、验证、命令和MVVM  1075

29.1 模型-视图-视图模型简介  1075

29.1.1 模型  1075

29.1.2 视图  1075

29.1.3 视图模型  1076

29.1.4 贫血模型和贫血视图模型  1076

29.2 WPF的绑定通知系统  1076

29.2.1 可观察的模型和集合  1077

29.2.2 添加绑定和数据  1078

29.2.3 在代码中修改车辆数据  1079

29.2.4 可观察模型  1079

29.2.5 可观察集合  1081

29.2.6 通知和可观察对象小结  1083

29.3 WPF的验证  1083

29.3.1 为验证示例更新文件  1083

29.3.2 Validation类  1083

29.3.3 验证选项  1084

29.3.4 在WPF中利用数据注解  1092

29.3.5 自定义ErrorTemplate  1094

29.3.6 验证小结  1095

29.4 创建自定义命令  1095

29.4.1 实现ICommand接口  1096

29.4.2 添加ChangeColorCommand  1096

29.4.3 创建CommandBase类  1098

29.4.4 添加AddCarCommand类  1098

29.4.5 RelayCommand  1100

29.4.6 命令小结  1101

29.5 将代码和数据迁移到视图模型  1102

29.5.1 移动MainWindow.xaml.cs的代码  1102

29.5.2 更新MainWindow的代码和标记  1103

29.5.3 更新控件的标记  1103

29.5.4 视图模型小结  1103

29.6 为MVVM更新AutoLot.Dal  1104

29.7 小结  1104

第IX部分  ASP.NET Core

第30章  ASP.NET Core简介  1107

30.1 快速回顾ASP.NET MVC  1107

30.1.1 MVC模式简介  1107

30.1.2 ASP.NET Core和MVC模式  1108

30.2 ASP.NET Core和.NET Core  1108

30.3 创建和配置解决方案和项目  1109

30.3.1 使用Visual Studio 2022  1109

30.3.2 使用命令行  1113

30.3.3 更新Entity Framework Core的包引用  1115

30.3.4 为所有项目禁用可空引用类型  1115

30.3.5 在每个项目中创建一个GlobalUsing.cs类  1115

30.4 运行ASP.NET Core应用程序  1115

30.4.1 使用Visual Studio  1116

30.4.2 使用Visual Studio Code  1117

30.4.3 使用命令行或Terminal窗口  1117

30.4.4 在调试时修改代码  1117

30.4.5 调试ASP.NET Core应用程序  1117

30.4.6 更新AutoLot.Api和AutoLot.Web Kestrel端口  1118

30.5 ASP.NET Core中来自MVC/Web API的概念  1119

30.5.1 约定先于配置  1119

30.5.2 控制器和动作(基于MVC的Web应用程序和RESTful服务)  1120

30.5.3 目录结构约定  1122

30.5.4 路由  1123

30.5.5 模型绑定  1132

30.5.6 模型验证  1137

30.5.7 过滤器  1139

30.6 小结  1140

第31章  深入介绍ASP.NET Core  1141

31.1 ASP.NET Core中的新增特性  1141

31.2 Razor页面  1141

31.2.1 Razor页面文件  1142

31.2.2 PageModel类  1142

31.2.3 页面处理程序方法  1143

31.3 环境感知  1143

31.4 WebAppBuilder和WebApp  1145

31.4.1 Restful服务的Program.cs文件  1146

31.4.2 MVC风格的应用程序中的Program.cs文件  1147

31.4.3 基于Razor页面的应用程序中的Program.cs文件  1148

31.5 应用程序配置  1148

31.6 内置依赖注入  1149

31.6.1 在依赖注入容器中添加对Web应用程序的支持  1150

31.6.2 将DbContext派生类添加到DI容器中  1151

31.6.3 在依赖注入容器中添加自定义服务  1151

31.6.4 依赖的层次结构  1153

31.6.5 注入依赖  1153

31.6.6 在Program.cs中获取依赖  1154

31.6.7 构建共享数据服务  1155

31.7 ASP.NET Core中的选项模式  1159

31.8 HTTP客户端工厂  1161

31.8.1 基本用法  1161

31.8.2 命名客户端  1162

31.8.3 类型化客户端  1162

31.8.4 AutoLot API服务封装器  1163

31.9 部署ASP.NET Core应用程序  1171

31.10 轻量级、模块化的HTTP请求管道  1171

31.11 日志记录  1171

31.11.1 使用Serilog添加日志记录  1173

31.11.2 AutoLot日志记录框架  1178

31.11.3 将日志记录添加到数据服务中  1182

31.11.4 测试日志记录框架  1183

31.12 字符串实用方法  1184

31.13 小结  1184

第32章  使用ASP.NET Core开发RESTful服务  1185

32.1 ASP.NET Core RESTful服务简介  1185

32.2 RESTful服务中的控制器动作  1185

32.2.1 格式化后的JSON响应结果  1186

32.2.2 ApiController特性  1189

32.3 API版本化  1193

32.3.1 微软的REST API指导原则  1193

32.3.2 添加版本化NuGet包  1193

32.3.3 添加API版本支持  1194

32.3.4 API版本特性  1197

32.3.5  版本交叉  1198

32.3.6 查询字符串版本的请求和路由  1199

32.3.7 获取请求中的API版本  1201

32.3.8 URL片段版本化的路由更新  1201

32.3.9 弃用版本  1202

32.3.10 对不支持版本的请求  1202

32.3.11 添加API版本资源管理器  1203

32.4 更新Swagger/OpenAPI设置  1204

32.4.1 添加XML文档文件  1204

32.4.2 应用程序的Swagger设置  1206

32.4.3 SwaggerDefaultValues操作过滤器  1209

32.4.4 ConfigureSwaggerOptions类  1210

32.4.5 更新SwaggerGen()调用  1211

32.4.6 更新UseSwaggerUI()调用  1212

32.4.7 在Swagger UI中查看结果  1212

32.4.8  API端点的其他文档选项  1214

32.5 构建BaseCrudController  1215

32.5.1 构造函数  1216

32.5.2 Get方法  1216

32.5.3 UpdateOne方法  1218

32.5.4 AddOne方法  1219

32.5.5 DeleteOne方法  1220

32.6 CarsController  1221

32.7 剩余的控制器  1222

32.8 异常过滤器  1224

32.8.1 创建自定义异常过滤器  1224

32.8.2 测试异常过滤器  1226

32.9 添加跨源请求支持  1226

32.9.1 创建CORS策略  1226

32.9.2 将CORS策略添加到HTTP管道处理中  1227

32.10 基本身份验证  1227

32.10.1 添加和配置安全性信息  1227

32.10.2 构建基本身份验证处理程序  1228

32.10.3 注册基本身份验证处理程序并保护控制器安全  1230

32.11 小结  1232

第33章  使用MVC开发Web应用程序  1233

33.1 ASP.NET Core中的“V”  1233

33.1.1 ViewResult和动作方法  1233

33.1.2 Razor视图引擎和Razor语法  1236

33.1.3 视图  1238

33.1.4 布局  1242

33.1.5 分部视图  1243

33.1.6 将布局拆分为分部视图  1244

33.1.7 将数据发送给视图  1245

33.2 管理客户端库  1248

33.2.1 将Library Manager作为.NET全局工具安装  1248

33.2.2 在AutoLot.Mvc中添加客户端库  1248

33.3 捆绑和最小化  1251

33.3.1 捆绑  1251

33.3.2 最小化  1251

33.3.3 WebOptimizer解决方案  1251

33.4 控制器  1253

33.4.1 HomeController  1254

33.4.2 BaseCrudController  1254

33.4.3 CarsController  1261

33.5 区域  1262

33.5.1 区域路由  1263

33.5.2 MakesController区域控制器  1263

33.5.3 _ViewImports和_ViewStart  1264

33.6 标签助手  1264

33.6.1 启用标签助手  1267

33.6.2 Form标签助手  1267

33.6.3 Form Action按钮/图像标签助手  1269

33.6.4 Anchor标签助手  1269

33.6.5 Input标签助手  1269

33.6.6 TextArea标签助手  1270

33.6.7 Select标签助手  1270

33.6.8 Validation标签助手  1271

33.6.9 Environment标签助手  1272

33.6.10 Link标签助手  1273

33.6.11 Script标签助手  1274

33.6.12 Image标签助手  1275

33.7 自定义标签助手  1276

33.7.1 搭建基础  1276

33.7.2 创建基类  1276

33.7.3 Item Details标签助手  1277

33.7.4 Item Delete标签助手  1278

33.7.5 Item Edit标签助手  1279

33.7.6 Item Create标签助手  1279

33.7.7 Item List标签助手  1280

33.7.8 使自定义标签助手可见  1280

33.8 HTML助手  1281

33.8.1 DisplayFor HTML助手  1281

33.8.2 DisplayForModel HTML助手  1281

33.8.3 EditorFor和EditorForModel HTML助手  1282

33.9 Car视图  1282

33.9.1 Car List分部视图  1282

33.9.2 Index视图  1283

33.9.3 ByMake视图  1284

33.9.4 Details视图  1285

33.9.5 Create视图  1285

33.9.6 Edit视图  1286

33.9.7 Delete视图  1288

33.10 视图组件  1289

33.10.1 服务器端代码  1289

33.10.2 构建分部视图  1290

33.10.3 调用视图组件  1290

33.10.4 更新菜单  1291

33.11 自定义验证特性  1291

33.11.1 搭建基础  1292

33.11.2 服务器端验证  1294

33.11.3 客户端验证  1298

33.11.4 更新Validation Scripts分部视图  1301

33.12 通用数据保护条例支持  1301

33.12.1 添加cookie政策支持  1301

33.12.2 用于支持cookie的分部视图  1302

33.12.3 用于同意/撤回使用cookie的菜单支持  1303

33.13 完成Admin区域  1304

33.14 同时运行AutoLot.Mvc和AutoLot.Api  1306

33.14.1 使用Visual Studio  1307

33.14.2 使用命令行  1307

33.15 小结  1308

第34章  使用Razor页面开发Web应用程序  1309

34.1 Razor页面的结构  1309

34.1.1 Razor页面的PageModel类和页面处理程序方法  1309

34.1.2 Razor页面视图  1311

34.1.3 Razor视图  1313

34.1.4 分部视图  1317

34.1.5 ViewBag、ViewData和TempData  1318

34.2 向AutoLot.Web添加客户端库  1319

34.2.1 添加libman.json文件  1319

34.2.2 更新libman.json文件  1319

34.2.3 更新JavaScript和CSS引用  1321

34.3 添加并配置WebOptimizer  1322

34.4 标签助手  1323

34.4.1 启用标签助手  1324

34.4.2 Form标签助手  1324

34.4.3 Form Action按钮/图像标签助手  1325

34.4.4 Anchor标签助手  1325

34.5 自定义标签助手  1325

34.5.1 更新Program.cs  1325

34.5.2 创建基类  1326

34.5.3 Item Details标签助手  1327

34.5.4 Item Delete标签助手  1328

34.5.5 Item Edit标签助手  1328

34.5.6 Item Create标签助手  1329

34.5.7 Item List标签助手  1329

34.5.8 使自定义标签助手可见  1330

34.6 Cars Razor页面  1330

34.6.1 BasePageModel类  1330

34.6.2 Index Razor页面  1333

34.6.3 Details Razor页面  1336

34.6.4 Create Razor页面  1337

34.6.5 Edit Razor页面  1338

34.6.6 Delete Razor页面  1340

34.7 视图组件  1342

34.8 区域  1343

34.8.1 Razor页面的区域路由  1343

34.8.2 _ViewImports和_ViewStart  1343

34.8.3 Makes Razor页面  1343

34.8.4 添加区域的菜单项  1348

34.9 自定义验证特性  1349

34.10 通用数据保护条例支持  1352

34.10.1 用于支持cookie的分部视图  1352

34.10.2 用于同意/撤回使用cookie的菜单支持  1353

34.11 小结  1354