Mud 代码生成器是一套基于 Roslyn 的源代码生成器,用于根据实体类和服务接口自动生成相关代码,提高开发效率。
| 组件 | 功能描述 | NuGet |
|---|---|---|
| Mud.EntityCodeGenerator | 实体代码生成:DTO、VO、QueryInput、CrInput、UpInput、Builder模式 | |
| Mud.ServiceCodeGenerator | 服务代码生成:HttpClient API、依赖注入、COM包装、自动注册 |
<ItemGroup>
<PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.6" />
<PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.6" />
</ItemGroup><PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<EntitySuffix>Entity</EntitySuffix>
</PropertyGroup>
<ItemGroup>
<CompilerVisibleProperty Include="EntitySuffix" />
<CompilerVisibleProperty Include="EmitCompilerGeneratedFiles" />
</ItemGroup>[DtoGenerator]
[Builder]
public partial class UserEntity
{
private long? _id;
private string _name;
private string _email;
}- DTO/VO 类 - 数据传输对象和视图对象
- QueryInput 类 - 查询条件输入对象
- CrInput/UpInput 类 - 创建和更新输入对象
- Builder 模式 - 链式构建器
- 映射方法 - 实体与DTO间自动转换
// VO 类
[SuppressSniffer, CompilerGenerated]
public partial class UserListOutput
{
public long? id { get; set; }
public string? name { get; set; }
public string? email { get; set; }
}
// QueryInput 类
[SuppressSniffer, CompilerGenerated]
public partial class UserQueryInput : DataQueryInput
{
public long? id { get; set; }
public string? name { get; set; }
public Expression<Func<UserEntity, bool>> BuildQueryWhere()
{
var where = LinqExtensions.True<UserEntity>();
where = where.AndIF(this.id != null, x => x.Id == this.id);
where = where.AndIF(!string.IsNullOrEmpty(this.name), x => x.Name == this.name);
return where;
}
}
// Builder 类
public class UserEntityBuilder
{
private UserEntity _userEntity = new UserEntity();
public UserEntityBuilder SetName(string name)
{
_userEntity.Name = name;
return this;
}
public UserEntityBuilder SetEmail(string email)
{
_userEntity.Email = email;
return this;
}
public UserEntity Build()
{
return _userEntity;
}
}[HttpClientApi("https://api.example.com", Timeout = 30)]
public interface IUserApi
{
[Get("users/{id}")]
Task<UserInfo> GetUserAsync(string id);
[Post("users")]
Task<UserInfo> CreateUserAsync([Body] CreateUserRequest request);
[Put("users/{id}")]
Task<UserInfo> UpdateUserAsync(string id, [Body] UpdateUserRequest request);
[Delete("users/{id}")]
Task DeleteUserAsync(string id);
[Get("users")]
Task<List<UserInfo>> GetUsersAsync([Query] string? name = null, [Query] int page = 1);
}[Get("path")]- GET请求[Post("path")]- POST请求[Put("path")]- PUT请求[Delete("path")]- DELETE请求[Patch("path")]- PATCH请求[Head("path")]- HEAD请求[Options("path")]- OPTIONS请求
[Get("users/{userId}/posts/{postId}")] // 路径参数
Task<Post> GetPostAsync(string userId, string postId);
[Get("users")] // 查询参数
Task<List<User>> GetUsersAsync([Query] string? name, [Query] int page = 1);
[Post("users")] // 请求体参数
Task<User> CreateUserAsync([Body] CreateUserRequest request);
[Post("users")] // 请求头参数
Task<User> CreateUserAsync([Body] CreateUserRequest request, [Header("Authorization")] string token);
[Get("files/{fileId}")] // 文件下载
Task<byte[]> DownloadFileAsync(string fileId);// 定义Token管理器
public interface ITokenManager
{
Task<string> GetTokenAsync();
}
// 使用Header传递Token
[HttpClientApi(TokenManage = nameof(ITokenManager))]
[Header("Authorization")]
public interface IProtectedApi
{
[Get("protected/data")]
Task<Data> GetDataAsync();
}[HttpClientApi("https://api.dingtalk.com", RegistryGroupName = "Dingtalk")]
public interface IDingtalkApi
{
[Get("user/info")]
Task<UserInfo> GetUserInfoAsync();
}生成独立的注册方法:
// 注册钉钉API
services.AddDingtalkWebApiHttpClient();
// 注册微信API
services.AddWechatWebApiHttpClient();
// 注册未分组的API
services.AddWebApiHttpClient();[ConstructorInject] // 字段构造函数注入
[LoggerInject] // 日志注入
[CacheInject] // 缓存管理器注入
[UserInject] // 用户管理器注入
[CustomInject(VarType = "IRepository<SysUser>", VarName = "_userRepository")] // 自定义注入
public partial class UserService
{
private readonly IRoleRepository _roleRepository;
private readonly IPermissionRepository _permissionRepository;
}public partial class UserService
{
private readonly ILogger<UserService> _logger;
private readonly ICacheManager _cacheManager;
private readonly IUserManager _userManager;
private readonly IRepository<SysUser> _userRepository;
private readonly IRoleRepository _roleRepository;
private readonly IPermissionRepository _permissionRepository;
public UserService(
ILoggerFactory loggerFactory,
ICacheManager cacheManager,
IUserManager userManager,
IRepository<SysUser> userRepository,
IRoleRepository roleRepository,
IPermissionRepository permissionRepository)
{
_logger = loggerFactory.CreateLogger<UserService>();
_cacheManager = cacheManager;
_userManager = userManager;
_userRepository = userRepository;
_roleRepository = roleRepository;
_permissionRepository = permissionRepository;
}
}| 特性 | 功能 | 说明 |
|---|---|---|
[ConstructorInject] |
字段注入 | 扫描私有只读字段生成构造函数参数 |
[LoggerInject] |
日志注入 | 注入 ILogger 日志记录器 |
[CacheInject] |
缓存注入 | 注入 ICacheManager 缓存管理器 |
[UserInject] |
用户注入 | 注入 IUserManager 用户管理器 |
[OptionsInject] |
配置注入 | 根据指定类型注入配置实例 |
[CustomInject] |
自定义注入 | 注入任意类型的依赖项 |
[ConstructorInject]
public partial class UserService
{
private readonly IUserRepository _userRepository;
[IgnoreGenerator]
private readonly string _connectionString = "default_connection_string"; // 不会被注入
}[ComObjectWrap]
[ComCollectionWrap]
public interface IMyComObject
{
[ComPropertyWrap]
string Name { get; set; }
[ComPropertyWrap(PropertyType = PropertyType.Method)]
void DoSomething();
}[AutoRegister]
[AutoRegister(ServiceLifetime.Singleton)]
[AutoRegister(ServiceLifetime.Scoped, InterfaceType = typeof(IMyService))]
public class MyService
{
// 服务实现
}[HttpClientApi(IsAbstract = true)]
public abstract class BaseApiClient
{
protected BaseApiClient(HttpClient httpClient, ILogger logger)
{
// 基础初始化逻辑
}
}
[HttpClientApi(InheritedFrom = "BaseApiClient")]
public interface IMyApi : BaseApiClient
{
[Get("data")]
Task<Data> GetDataAsync();
}| 参数名 | 默认值 | 说明 |
|---|---|---|
| EmitCompilerGeneratedFiles | false | 是否在obj目录下保存生成的代码 |
| EntitySuffix | Entity | 实体类后缀,用于识别实体类 |
| HttpClientOptionsName | HttpClientOptions | HttpClient配置类名 |
| DefaultLoggerVariable | _logger | 日志变量名默认值 |
| DefaultCacheManagerVariable | _cacheManager | 缓存管理器变量名默认值 |
| DefaultUserManagerVariable | _userManager | 用户管理器变量名默认值 |
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| BaseAddress | string | null | API 基础地址 |
| Timeout | int | 50 | 请求超时时间(秒) |
| ContentType | string | application/json | 默认内容类型 |
| RegistryGroupName | string | null | 注册分组名称 |
| TokenManage | string | null | Token管理器接口名 |
| IsAbstract | bool | false | 是否生成抽象类 |
| InheritedFrom | string | null | 继承的基类名 |
<!-- 在项目中配置 -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<EntitySuffix>Entity</EntitySuffix>
<EntityAttachAttributes>SuppressSniffer</EntityAttachAttributes>
</PropertyGroup>
<!-- 添加特性到实体类 -->
[DtoGenerator]
[Builder]
public partial class UserEntity
{
// 实体字段定义
}<!-- 配置HttpClient选项 -->
<PropertyGroup>
<HttpClientOptionsName>HttpClientOptions</HttpClientOptionsName>
</PropertyGroup>// 添加特性到接口
[HttpClientApi("https://api.example.com")]
public interface IUserApi
{
// API方法定义
}<!-- 配置默认注入类型 -->
<PropertyGroup>
<DefaultCacheManagerType>ICacheManager</DefaultCacheManagerType>
<DefaultUserManagerType>IUserManager</DefaultUserManagerType>
</PropertyGroup>// 添加特性到类
[ConstructorInject]
[LoggerInject]
[CacheInject]
[UserInject]
public partial class UserService
{
// 类字段定义
}// 在 Startup.cs 或 Program.cs 中注册服务
public void ConfigureServices(IServiceCollection services)
{
// 注册Token管理器
services.AddSingleton<ITokenManager, MyTokenManager>();
// 配置HttpClient选项
services.Configure<HttpClientOptions>(options =>
{
options.BaseUrl = "https://api.example.com";
options.TimeOut = "30";
options.EnableLogging = true;
});
// 注册生成的API客户端
services.AddHttpClient<IUserApi, UserApi>();
}- ✅ 完整的请求逻辑 - 自动处理请求构建、发送、响应解析
- ✅ 错误处理和日志记录 - 自动记录请求日志和错误信息
- ✅ 异步支持 - 支持async/await模式
- ✅ 类型安全 - 强类型的参数和返回值
- ✅ 配置灵活 - 支持通过特性或配置文件配置
- ✅ 生命周期管理 - 正确处理HttpClient和资源释放
- ✅ Partial方法 - 生成Partial方法支持自定义扩展
- ✅ 零运行时开销 - 编译时代码生成,性能最优
设置 EmitCompilerGeneratedFiles=true 后,生成的代码位于:
obj/[Configuration]/[TargetFramework]/generated/
文件名以 .g.cs 结尾。
- 使用
EmitCompilerGeneratedFiles=true可以在 obj 目录下查看生成的代码,便于调试 - 生成的代码文件名以
.g.cs结尾 - 所有生成的代码都是 partial 类,不会影响您手动编写的代码
- 建议在实体类和服务类上使用 partial 关键字,以便代码生成器可以扩展它们
Mud.CodeGenerator
├── Core/
│ ├── Mud.CodeGenerator // 代码生成器核心基类库
│ ├── Mud.EntityCodeGenerator // 实体代码生成器
│ └── Mud.ServiceCodeGenerator // 服务代码生成器
│ ├── HttpInvoke/ // HttpClient API 代码生成器
│ ├── ServiceCode/ // 服务类代码生成器
│ ├── CodeInject/ // 依赖注入代码生成器
│ └── ComWrap/ // COM对象包装生成器
├── Test/
│ ├── CodeGeneratorTest // 代码生成器测试项目
│ └── Mud.Common.CodeGenerator // 通用代码生成器特性定义
├── mudEntityCodeGenerator.md // 实体代码生成器详细文档
├── TokenImplementationSummary.md // Token管理功能实现总结
├── TokenUsageExample.md // Token管理功能使用示例
└── README.md
本项目采用MIT许可证模式:MIT 许可证
💡 提示: 生成的代码都是 partial 类,不影响手动编写的代码。建议使用 partial 关键字以便代码生成器扩展。编译时自动生成代码,零运行时开销。