自定义代码
自定义代码允许用户对生成的代码进行自动修改或添加代码以满足特定需求。例如:自定义代码功能可以用来解决生成的代码与已有项目代码不完全一致的兼容性问题。 自定义代码功能还可以解决项目重新生成时手工编写的代码被覆盖的问题。当您在项目中直接新增或修改代码时,这些代码在项目重新生成时将会被覆盖,您可以通过自定义代码在项目中自动加入这些代码,而不是在项目中直接修改或新增代码。
进入自定义代码的方式如下:
- 右键单击项目节点,然后选择 自定义代码。在设计器项目属性页选择 自定义代码 页签,您可以增加如下自定义代码:命名空间、继承、类特性、属性特性、方法特性、构造函数注入、以及代码片段,并选择代码生效的范围:实体、实体配置、枚举、过滤器、数据上下文、服务、控制器。
- 在设计器(例如实体设计器、枚举设计器、复合查询设计器)页面中选择 自定义代码 页签对当前对象(实体、实体配置、枚举、字段、复合查询结果集、过滤器、服务、控制器、API 等)增加以下自定义代码:命名空间、继承、类特性、属性特性、以及代码片段。
在设计器项目属性页,您还可以从引用的项目中导入自定义代码设置。选择 使用所引用的项目中的自定义代码设置 选项,这样引用项目中的自定义代码设置将自动导入并显示在此处。
对于 构造函数注入,您还可以指定依赖。
对于代码片段,您还可以指定插入代码的位置。
完成配置后,您可以预览代码以确保代码按预期生成。
有关代码示例,请参阅以下部分 添加自定义代码。
添加自定义代码
本节提供如何编写自定义代码的示例。
命名空间
命名空间主要是和其他代码片段结合使用。
例如,当需要为 DbContext 继承一个接口时,首先需要使用命名空间区添加该接口所在的命名空间,然后在继承区添加该接口。
在命名空间中添加以下内容
自定义代码 | 范围 |
---|---|
using Microsoft.Extensions.DependencyInjection; | 数据上下文 |
using Microsoft.EntityFrameworkCore.Infrastruct; | 数据上下文 |
在继承中添加以下内容
自定义代码 | 范围 |
---|---|
IServiceScope | 数据上下文 |
在代码片段中添加以下内容
代码片段 | 范围 | 插入位置 |
---|---|---|
public IServiceProvider ServiceProvider => this.GetInfrastruct(); | 数据上下文 | 类顶部 |
代码预览:
继承
当所有实体都继承某个接口或类,支持模板 {TClass} 和 {TInterface},根据模板类型在生成代码时会替换成当前类的类名或接口名。
例如,当所有实体都继承 IEquatable<> 泛型接口时(需要结合代码片段提供接口实现)
在继承中添加以下内容:
自定义代码 | 范围 |
---|---|
IEquatable<{TClass}> | 数据上下文 |
在代码片段中添加以下内容:
代码片段 | 范围 | 插入位置 |
---|---|---|
public bool Equals({TClass}? other) { return other?.Equals(this) ?? false; } |
实体 | 类底部 |
代码预览:
类特性
例如,在所有的枚举类型上添加特性 [Serializable]。
在类特性中添加以下内容:
自定义特性代码 | 范围 |
---|---|
[Serializable] | 枚举 |
代码预览:
再比如,在所有实体类型上添加特性 [Table] 并设置实体映射表名。
在类特性中添加以下内容:
自定义特性代码 | 范围 |
---|---|
[Table("{TTable}")] | 实体 |
代码预览:
属性特性
例如,为每个实体的属性添加 Json 序列化的属性名。
在命名空间中添加以下内容:
自定义代码 | 范围 |
---|---|
using System.Text.Json.Serialization; | 实体 |
在属性特性中添加以下内容:
自定义属性代码 | 范围 |
---|---|
[JsonPropertyName("{TProperty}")] | 实体 |
代码预览:
方法特性
例如,为控制器的每个 Action 添加响应类型特性 [ProducesResponseType(StatusCodes.Status200OK)]。
在命名空间中添加以下内容:
自定义代码 | 范围 |
---|---|
using Microsoft.AspNetCore.Http; | 控制器 |
在方法特性中添加以下内容:
自定义特性代码 | 范围 |
---|---|
[ProducesResponseType(StatusCodes.Status200OK)] | 控制器 |
代码预览:
构造函数注入
例如,在集成日志服务时,注入日志服务的相关接口。
在命名空间中添加以下内容:
自定义代码 | 范围 |
---|---|
using Microsoft.Extensions.Logging; | 控制器 |
在构造函数注入中添加以下内容:
构造函数参数类型 | 值(依赖) | 范围 |
---|---|---|
ILogger<{TClass}> | logger | 控制器 |
代码预览:
代码片段
例如,在处理每个请求时写入日志,日志中需要包含调用者的 UserId 及其调用的API。
在命名空间中添加以下内容:
自定义代码 | 范围 |
---|---|
using Microsoft.Extensions.Logging; | 控制器 |
在构造函数注入中添加以下内容:
构造函数参数类型 | 值(依赖) | 范围 |
---|---|---|
ILogger<{TClass}> | logger | 控制器 |
ICurrentUser | currentUser | 控制器 |
在代码片段中添加以下内容:
代码片段 | 范围 | 插入位置 |
---|---|---|
_logger.LogInformation($"UserId: {_currentUser.GetUserId()} called this method - {TMethod}"); | 控制器 | 方法顶部 |
代码预览: