找回密码
 立即注册
首页 业界区 业界 打造.NET平台的Lombok:实现构造函数注入、日志注入、构 ...

打造.NET平台的Lombok:实现构造函数注入、日志注入、构造者模式代码生成等功能

鞭氅 10 小时前
在Java生态系统中,Lombok是一个非常受欢迎的库,它通过注解的方式大大减少了Java开发者需要编写的样板代码量。通过简单的注解,如@Data、@Getter、@Setter、@AllArgsConstructor等,开发者可以自动生成getter/setter方法、构造函数、toString方法等。这不仅提高了开发效率,还减少了代码中的冗余,使代码更加简洁和易于维护。
然而,在.NET生态系统中,虽然没有直接等价于Lombok的官方库,但我们可以通过Roslyn源代码生成器来实现类似甚至更强大的功能。本文将介绍如何在.NET平台上构建一个类似Lombok的代码生成工具,实现构造函数注入、日志注入、构造者模式等代码生成功能。
为什么需要类似Lombok的工具?

在现代软件开发中,我们经常需要编写大量重复的样板代码,例如:

  • 依赖注入:为服务类编写构造函数注入代码
  • 数据传输对象(DTO):为实体类创建对应的DTO类
  • Builder模式:为复杂对象创建Builder构建器
  • 属性访问器:为私有字段生成公共属性
  • 映射方法:在不同对象之间进行属性映射
这些样板代码不仅占用大量时间编写,还容易出错且难以维护。通过代码生成工具,我们可以自动化这些重复性工作,让开发者专注于业务逻辑的实现。
Mud代码生成器

Mud代码生成器是一套基于Roslyn的源代码生成器,专门针对.NET平台设计,提供了类似Lombok的功能,甚至更加丰富。它包含两个主要组件:

  • Mud.EntityCodeGenerator:实体代码生成器,用于根据实体类自动生成各种相关代码
  • Mud.ServiceCodeGenerator:服务代码生成器,用于自动生成服务层相关代码
这套工具通过在代码中添加特定的特性(Attribute)标记,然后在编译时自动生成相应的代码,大大减少了开发者需要手动编写的代码量。
核心功能

1. 生成构造函数注入代码

在.NET的依赖注入系统中,构造函数注入是最推荐的依赖注入方式。然而,手动编写构造函数注入代码可能会很繁琐,特别是当一个类需要注入多个服务时。
Mud.ServiceCodeGenerator提供了多种注入特性,可以自动生成构造函数注入代码:
ConstructorInjectAttribute 字段注入

使用[ConstructorInject]特性可以将类中已存在的私有只读字段通过构造函数注入初始化:
  1. [ConstructorInject]
  2. public partial class UserService
  3. {
  4.     private readonly IUserRepository _userRepository;
  5.     private readonly IRoleRepository _roleRepository;
  6.    
  7.     // 生成的代码将包含:
  8.     // public UserService(IUserRepository userRepository, IRoleRepository roleRepository)
  9.     // {
  10.     //     _userRepository = userRepository;
  11.     //     _roleRepository = roleRepository;
  12.     // }
  13. }
复制代码
LoggerInjectAttribute 日志注入

使用[LoggerInject]特性可以为类注入ILogger类型的日志记录器:
  1. [LoggerInject]
  2. public partial class UserService
  3. {
  4.     // 生成的代码将包含:
  5.     // private readonly ILogger<UserService> _logger;
  6.     //
  7.     // public UserService(ILoggerFactory loggerFactory)
  8.     // {
  9.     //     _logger = loggerFactory.CreateLogger<UserService>();
  10.     // }
  11. }
复制代码
CacheInjectAttribute 缓存管理器注入

使用[CacheInject]特性可以注入缓存管理器实例:
  1. [CacheInject]
  2. public partial class UserService
  3. {
  4.     // 生成的代码将包含:
  5.     // private readonly ICacheManager _cacheManager;
  6.     //
  7.     // public UserService(ICacheManager cacheManager)
  8.     // {
  9.     //     _cacheManager = cacheManager;
  10.     // }
  11. }
复制代码
UserInjectAttribute 用户管理器注入

使用[UserInject]特性可以注入用户管理器实例:
  1. [UserInject]
  2. public partial class UserService
  3. {
  4.     // 生成的代码将包含:
  5.     // private readonly IUserManager _userManager;
  6.     //
  7.     // public UserService(IUserManager userManager)
  8.     // {
  9.     //     _userManager = userManager;
  10.     // }
  11. }
复制代码
OptionsInjectAttribute 配置项注入

使用[OptionsInject]特性可以根据指定的配置项类型注入配置实例:
  1. [OptionsInject(OptionType = "TenantOptions")]
  2. public partial class UserService
  3. {
  4.     // 生成的代码将包含:
  5.     // private readonly TenantOptions _tenantOptions;
  6.     //
  7.     // public UserService(IOptions<TenantOptions> tenantOptions)
  8.     // {
  9.     //     _tenantOptions = tenantOptions.Value;
  10.     // }
  11. }
复制代码
CustomInjectAttribute 自定义注入

使用[CustomInject]特性可以注入任意类型的依赖项:
  1. [CustomInject(VarType = "IRepository<SysUser>", VarName = "_userRepository")]
  2. [CustomInject(VarType = "INotificationService", VarName = "_notificationService")]
  3. public partial class UserService
  4. {
  5.     // 生成的代码将包含:
  6.     // private readonly IRepository<SysUser> _userRepository;
  7.     // private readonly INotificationService _notificationService;
  8.     //
  9.     // public UserService(IRepository<SysUser> userRepository, INotificationService notificationService)
  10.     // {
  11.     //     _userRepository = userRepository;
  12.     //     _notificationService = notificationService;
  13.     // }
  14. }
复制代码
组合注入示例

多种注入特性可以组合使用,生成器会自动合并所有注入需求:
  1. [ConstructorInject]
  2. [LoggerInject]
  3. [CacheInject]
  4. [UserInject]
  5. [OptionsInject(OptionType = "TenantOptions")]
  6. [CustomInject(VarType = "IRepository<SysUser>", VarName = "_userRepository")]
  7. public partial class UserService
  8. {
  9.     private readonly IRoleRepository _roleRepository;
  10.     private readonly IPermissionRepository _permissionRepository;
  11.    
  12.     // 生成的代码将包含所有注入项:
  13.     // private readonly ILogger<UserService> _logger;
  14.     // private readonly ICacheManager _cacheManager;
  15.     // private readonly IUserManager _userManager;
  16.     // private readonly TenantOptions _tenantOptions;
  17.     // private readonly IRepository<SysUser> _userRepository;
  18.     // private readonly IRoleRepository _roleRepository;
  19.     // private readonly IPermissionRepository _permissionRepository;
  20.     //
  21.     // public UserService(
  22.     //     ILoggerFactory loggerFactory,
  23.     //     ICacheManager cacheManager,
  24.     //     IUserManager userManager,
  25.     //     IOptions<TenantOptions> tenantOptions,
  26.     //     IRepository<SysUser> userRepository,
  27.     //     IRoleRepository roleRepository,
  28.     //     IPermissionRepository permissionRepository)
  29.     // {
  30.     //     _logger = loggerFactory.CreateLogger<UserService>();
  31.     //     _cacheManager = cacheManager;
  32.     //     _userManager = userManager;
  33.     //     _tenantOptions = tenantOptions.Value;
  34.     //     _userRepository = userRepository;
  35.     //     _roleRepository = roleRepository;
  36.     //     _permissionRepository = permissionRepository;
  37.     // }
  38. }
复制代码
2. Builder模式代码生成

Builder模式是一种创建型设计模式,能够分步骤创建复杂对象。使用Builder模式可以创建不同表现的对象,同时避免构造函数参数过多的问题。
Mud.EntityCodeGenerator支持通过[Builder]特性自动生成Builder构建器模式代码:
  1. /// <summary>
  2. /// 客户端信息实体类
  3. /// </summary>
  4. [DtoGenerator]
  5. [Builder]
  6. [Table(Name = "sys_client"),SuppressSniffer]
  7. public partial class SysClientEntity
  8. {
  9.     /// <summary>
  10.     /// id
  11.     /// </summary>
  12.     [property: Column(Name = "id", IsPrimary = true, Position = 1)]
  13.     [property: Required(ErrorMessage = "id不能为空")]
  14.     private long? _id;
  15.     /// <summary>
  16.     /// 客户端key
  17.     /// </summary>
  18.     [property: Column(Name = "client_key", Position = 3)]
  19.     [property: Required(ErrorMessage = "客户端key不能为空")]
  20.     private string _clientKey;
  21.     /// <summary>
  22.     /// 删除标志(0代表存在 2代表删除)
  23.     /// </summary>
  24.     [property: Column(Name = "del_flag", Position = 10)]
  25.     private string _delFlag;
  26. }
复制代码
基于以上实体,将自动生成Builder构建器类:
  1. /// <summary>
  2. /// <see cref="SysClientEntity"/> 的构建者。
  3. /// </summary>
  4. public class SysClientEntityBuilder
  5. {
  6.     private SysClientEntity _sysClientEntity = new SysClientEntity();
  7.     /// <summary>
  8.     /// 设置 <see cref="SysClientEntity.Id"/> 属性值。
  9.     /// </summary>
  10.     /// <param name="id">属性值</param>
  11.     /// <returns>返回 <see cref="SysClientEntityBuilder"/> 实例</returns>
  12.     public SysClientEntityBuilder SetId(long? id)
  13.     {
  14. <ItemGroup>
  15.   
  16.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  17.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  18. </ItemGroup>  this._sysClientEntity.Id = id;
  19. <ItemGroup>
  20.   
  21.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  22.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  23. </ItemGroup>  return this;
  24.     }
  25.     /// <summary>
  26.     /// 设置 <see cref="SysClientEntity.ClientKey"/> 属性值。
  27.     /// </summary>
  28.     /// <param name="clientKey">属性值</param>
  29.     /// <returns>返回 <see cref="SysClientEntityBuilder"/> 实例</returns>
  30.     public SysClientEntityBuilder SetClientKey(string clientKey)
  31.     {
  32. <ItemGroup>
  33.   
  34.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  35.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  36. </ItemGroup>  this._sysClientEntity.ClientKey = clientKey;
  37. <ItemGroup>
  38.   
  39.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  40.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  41. </ItemGroup>  return this;
  42.     }
  43.     /// <summary>
  44.     /// 设置 <see cref="SysClientEntity.DelFlag"/> 属性值。
  45.     /// </summary>
  46.     /// <param name="delFlag">属性值</param>
  47.     /// <returns>返回 <see cref="SysClientEntityBuilder"/> 实例</returns>
  48.     public SysClientEntityBuilder SetDelFlag(string delFlag)
  49.     {
  50. <ItemGroup>
  51.   
  52.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  53.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  54. </ItemGroup>  this._sysClientEntity.DelFlag = delFlag;
  55. <ItemGroup>
  56.   
  57.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  58.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  59. </ItemGroup>  return this;
  60.     }
  61.     /// <summary>
  62.     /// 构建 <see cref="SysClientEntity"/> 类的实例。
  63.     /// </summary>
  64.     public SysClientEntity Build()
  65.     {
  66. <ItemGroup>
  67.   
  68.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  69.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  70. </ItemGroup>  return this._sysClientEntity;
  71.     }
  72. }
复制代码
使用Builder模式可以链式设置实体属性,创建实体对象更加方便:
  1. var client = new SysClientEntityBuilder()
  2.     .SetClientKey("client123")
  3.     .SetDelFlag("0")
  4.     .Build();
复制代码
3. DTO/VO代码生成

在现代Web应用开发中,数据传输对象(DTO)和视图对象(VO)是常见的设计模式。它们用于在不同层之间传输数据,避免直接暴露实体类。
Mud.EntityCodeGenerator可以自动生成DTO和VO类:
  1. /// <summary>
  2. /// 客户端信息实体类
  3. /// </summary>
  4. [DtoGenerator]
  5. [Table(Name = "sys_client"),SuppressSniffer]
  6. public partial class SysClientEntity
  7. {
  8.     /// <summary>
  9.     /// id
  10.     /// </summary>
  11.     [property: TableField(Fille = FieldFill.Insert, Value = FillValue.Id)]
  12.     [property: Column(Name = "id", IsPrimary = true, Position = 1)]
  13.     [property: Required(ErrorMessage = "id不能为空")]
  14.     private long? _id;
  15.     /// <summary>
  16.     /// 客户端key
  17.     /// </summary>
  18.     [property: Column(Name = "client_key", Position = 3)]
  19.     [property: Required(ErrorMessage = "客户端key不能为空")]
  20.     [property: ExportProperty("客户端key")]
  21.     [property: CustomVo1, CustomVo2]
  22.     [property: CustomBo1, CustomBo2]
  23.     private string _clientKey;
  24.     /// <summary>
  25.     /// 删除标志(0代表存在 2代表删除)
  26.     /// </summary>
  27.     [property: Column(Name = "del_flag", Position = 10)]
  28.     [property: ExportProperty("删除标志")]
  29.     [IgnoreQuery]
  30.     private string _delFlag;
  31. }
复制代码
基于以上实体,将自动生成以下几类代码:
VO类 (视图对象)
  1. /// <summary>
  2. /// 客户端信息实体类
  3. /// </summary>
  4. [SuppressSniffer, CompilerGenerated]
  5. public partial class SysClientListOutput
  6. {
  7.     /// <summary>
  8.     /// id
  9.     /// </summary>
  10.     public long? id { get; set; }
  11.     /// <summary>
  12.     /// 客户端key
  13.     /// </summary>
  14.     [ExportProperty("客户端key")]
  15.     [CustomVo1, CustomVo2]
  16.     public string? clientKey { get; set; }
  17.     /// <summary>
  18.     /// 删除标志(0代表存在 2代表删除)
  19.     /// </summary>
  20.     [ExportProperty("删除标志")]
  21.     public string? delFlag { get; set; }
  22. }
复制代码
QueryInput类 (查询输入对象)
  1. // SysClientQueryInput.g.cs
  2. /// <summary>
  3. /// 客户端信息实体类
  4. /// </summary>
  5. [SuppressSniffer, CompilerGenerated]
  6. public partial class SysClientQueryInput : DataQueryInput
  7. {
  8.     /// <summary>
  9.     /// id
  10.     /// </summary>
  11.     public long? id { get; set; }
  12.     /// <summary>
  13.     /// 客户端key
  14.     /// </summary>
  15.     public string? clientKey { get; set; }
  16.     /// <summary>
  17.     /// 删除标志(0代表存在 2代表删除)
  18.     /// </summary>
  19.     public string? delFlag { get; set; }
  20.     /// <summary>
  21.     /// 构建通用的查询条件。
  22.     /// </summary>
  23.     public Expression<Func<SysClientEntity, bool>> BuildQueryWhere()
  24.     {
  25. <ItemGroup>
  26.   
  27.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  28.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  29. </ItemGroup>  var where = LinqExtensions.True<SysClientEntity>();
  30. <ItemGroup>
  31.   
  32.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  33.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  34. </ItemGroup>  where = where.AndIF(this.id != null, x => x.Id == this.id);
  35. <ItemGroup>
  36.   
  37.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  38.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  39. </ItemGroup>  where = where.AndIF(!string.IsNullOrEmpty(this.clientKey), x => x.ClientKey == this.clientKey);
  40. <ItemGroup>
  41.   
  42.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  43.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  44. </ItemGroup>  where = where.AndIF(!string.IsNullOrEmpty(this.delFlag), x => x.DelFlag == this.delFlag);
  45. <ItemGroup>
  46.   
  47.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  48.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  49. </ItemGroup>  return where;
  50.     }
  51. }
复制代码
CrInput类 (创建输入对象)
  1. // SysClientCrInput.g.cs
  2. /// <summary>
  3. /// 客户端信息实体类
  4. /// </summary>
  5. [SuppressSniffer, CompilerGenerated]
  6. public partial class SysClientCrInput
  7. {
  8.     /// <summary>
  9.     /// 客户端key
  10.     /// </summary>
  11.     [Required(ErrorMessage = "客户端key不能为空"), CustomBo1, CustomBo2]
  12.     public string? clientKey { get; set; }
  13.     /// <summary>
  14.     /// 删除标志(0代表存在 2代表删除)
  15.     /// </summary>
  16.     public string? delFlag { get; set; }
  17.     /// <summary>
  18.     /// 通用的BO对象映射至实体方法。
  19.     /// </summary>
  20.     public virtual SysClientEntity MapTo()
  21.     {
  22. <ItemGroup>
  23.   
  24.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  25.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  26. </ItemGroup>  var entity = new SysClientEntity();
  27. <ItemGroup>
  28.   
  29.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  30.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  31. </ItemGroup>  entity.ClientKey = this.clientKey;
  32. <ItemGroup>
  33.   
  34.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  35.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  36. </ItemGroup>  entity.DelFlag = this.delFlag;
  37. <ItemGroup>
  38.   
  39.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  40.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  41. </ItemGroup>  return entity;
  42.     }
  43. }
复制代码
UpInput类 (更新输入对象)
  1. /// <summary>
  2. /// 客户端信息实体类
  3. /// </summary>
  4. [SuppressSniffer, CompilerGenerated]
  5. public partial class SysClientUpInput : SysClientCrInput
  6. {
  7.     /// <summary>
  8.     /// id
  9.     /// </summary>
  10.     [Required(ErrorMessage = "id不能为空")]
  11.     public long? id { get; set; }
  12.     /// <summary>
  13.     /// 通用的BO对象映射至实体方法。
  14.     /// </summary>
  15.     public override SysClientEntity MapTo()
  16.     {
  17. <ItemGroup>
  18.   
  19.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  20.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  21. </ItemGroup>  var entity = base.MapTo();
  22. <ItemGroup>
  23.   
  24.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  25.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  26. </ItemGroup>  entity.Id = this.id;
  27. <ItemGroup>
  28.   
  29.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  30.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  31. </ItemGroup>  return entity;
  32.     }
  33. }
复制代码
4. 实体映射方法生成

在不同对象之间进行属性映射是一项常见但繁琐的工作。Mud.EntityCodeGenerator可以自动生成实体与DTO之间的映射方法:
  1. /// <summary>
  2. /// 通用的实体映射至VO对象方法。
  3. /// </summary>
  4. public virtual SysClientListOutput MapTo()
  5. {
  6.     var voObj = new SysClientListOutput();
  7.     voObj.id = this.Id;
  8.     voObj.clientKey = this.ClientKey;
  9.     voObj.delFlag = this.DelFlag;
  10.     return voObj;
  11. }
复制代码
配置和使用

项目配置

在使用Mud代码生成器时,可以通过在项目文件中配置参数来自定义生成行为。
实体代码生成器配置参数
  1. <PropertyGroup>
  2.   <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>  
  3.   <EntitySuffix>Entity</EntitySuffix>  
  4.   <EntityAttachAttributes>SuppressSniffer</EntityAttachAttributes>  
  5.   
  6.   
  7.   <PropertyNameLowerCaseFirstLetter>true</PropertyNameLowerCaseFirstLetter>  
  8.   
  9.   
  10.   <VoAttributes>CustomVo1Attribute,CustomVo2Attribute</VoAttributes>  
  11.   <BoAttributes>CustomBo1Attribute,CustomBo2Attribute</BoAttributes>  
  12. </PropertyGroup>
  13. <ItemGroup>
  14.   <CompilerVisibleProperty Include="EntitySuffix" />
  15.   <CompilerVisibleProperty Include="EntityAttachAttributes" />
  16.   <CompilerVisibleProperty Include="PropertyNameLowerCaseFirstLetter" />
  17.   <CompilerVisibleProperty Include="VoAttributes" />
  18.   <CompilerVisibleProperty Include="BoAttributes" />
  19. </ItemGroup>
复制代码
服务代码生成器配置参数
  1. <PropertyGroup>
  2.   <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>  
  3.   
  4.   
  5.   <DefaultCacheManagerType>ICacheManager</DefaultCacheManagerType>  
  6.   <DefaultUserManagerType>IUserManager</DefaultUserManagerType>  
  7.   <DefaultLoggerVariable>_logger</DefaultLoggerVariable>  
  8.   <DefaultCacheManagerVariable>_cacheManager</DefaultCacheManagerVariable>  
  9.   <DefaultUserManagerVariable>_userManager</DefaultUserManagerVariable>  
  10.   
  11.   
  12.   <ServiceGenerator>true</ServiceGenerator>  
  13.   <EntitySuffix>Entity</EntitySuffix>  
  14.   <ImpAssembly>Mud.System</ImpAssembly>  
  15.   
  16.   
  17.   <EntityAttachAttributes>SuppressSniffer</EntityAttachAttributes>  
  18. </PropertyGroup>
  19. <ItemGroup>
  20.   <CompilerVisibleProperty Include="DefaultCacheManagerType" />
  21.   <CompilerVisibleProperty Include="DefaultUserManagerType" />
  22.   <CompilerVisibleProperty Include="DefaultLoggerVariable" />
  23.   <CompilerVisibleProperty Include="DefaultCacheManagerVariable" />
  24.   <CompilerVisibleProperty Include="DefaultUserManagerVariable" />
  25.   <CompilerVisibleProperty Include="ServiceGenerator" />
  26.   <CompilerVisibleProperty Include="EntitySuffix" />
  27.   <CompilerVisibleProperty Include="ImpAssembly" />
  28.   <CompilerVisibleProperty Include="EntityAttachAttributes" />
  29. </ItemGroup>
复制代码
依赖项配置
  1. <ItemGroup>
  2.   
  3.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  4.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  5. </ItemGroup>
复制代码
高级特性

忽略字段注入

对于某些不需要通过构造函数注入的字段,可以使用[IgnoreGenerator]特性标记:
  1. [ConstructorInject]public partial class UserService{    private readonly IUserRepository _userRepository;<ItemGroup>
  2.   
  3.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  4.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  5. </ItemGroup>  [IgnoreGenerator]    private readonly string _connectionString = "default_connection_string"; // 不会被注入<ItemGroup>
  6.   
  7.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  8.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  9. </ItemGroup>  // 只有_userRepository会被构造函数注入}
复制代码
自定义属性生成

Mud代码生成器支持通过配置参数为生成的类添加自定义特性:
  1. <PropertyGroup>
  2.   
  3.   <VoAttributes>CustomVo1Attribute,CustomVo2Attribute</VoAttributes>
  4.   
  5.   <BoAttributes>CustomBo1Attribute,CustomBo2Attribute</BoAttributes>
  6. </PropertyGroup>
复制代码
与其他工具的比较

与AutoMapper的比较

AutoMapper是一个流行的对象映射工具,但它运行时进行映射,而Mud代码生成器在编译时生成映射代码。这意味着:

  • 性能:Mud生成的代码在运行时性能更好,因为没有反射开销
  • 类型安全:编译时生成的代码具有更好的类型安全性
  • 调试友好:生成的代码可以直接调试,更容易排查问题
与传统手工编码的比较


  • 开发效率:大大减少了样板代码的编写时间
  • 维护性:当实体类发生变化时,相关代码会自动更新
  • 一致性:生成的代码风格统一,减少了人为错误
最佳实践

1. 合理使用特性标记

不要为所有类都添加代码生成特性,只在确实需要的类上使用。过度使用可能导致生成大量不必要的代码。
2. 配置参数优化

根据项目实际情况配置生成参数,例如:
  1. <PropertyGroup>
  2.   <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  3.   <EntitySuffix>Entity</EntitySuffix>
  4.   <PropertyNameLowerCaseFirstLetter>false</PropertyNameLowerCaseFirstLetter>
  5. </PropertyGroup>
复制代码
3. 查看生成代码

在开发阶段,建议启用[EmitCompilerGeneratedFiles]参数,以便查看生成的代码:
  1. <PropertyGroup>
  2.   <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
  3. </PropertyGroup>
复制代码
生成的代码将位于obj/[Configuration]/[TargetFramework]/generated/目录下,文件名以.g.cs结尾。
4. 版本管理

生成的代码不需要加入版本管理,因为它们会在编译时自动生成。可以在.gitignore中添加:
  1. **/*.g.cs
复制代码
实际应用案例

案例1:用户服务类
  1. [ConstructorInject][LoggerInject][CacheInject][UserInject]public partial class UserService{    private readonly IUserRepository _userRepository;    private readonly IRoleRepository _roleRepository;<ItemGroup>
  2.   
  3.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  4.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  5. </ItemGroup>  public async Task GetUserAsync(long userId)    {<ItemGroup>
  6.   
  7.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  8.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  9. </ItemGroup>  _logger.LogInformation("Getting user with id: {UserId}", userId);<ItemGroup>
  10.   
  11.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  12.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  13. </ItemGroup><ItemGroup>
  14.   
  15.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  16.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  17. </ItemGroup>    var user = await _userRepository.GetByIdAsync(userId);<ItemGroup>
  18.   
  19.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  20.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  21. </ItemGroup>  if (user == null)<ItemGroup>
  22.   
  23.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  24.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  25. </ItemGroup>  {<ItemGroup>
  26.   
  27.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  28.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  29. </ItemGroup><ItemGroup>
  30.   
  31.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  32.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  33. </ItemGroup>_logger.LogWarning("User with id {UserId} not found", userId);<ItemGroup>
  34.   
  35.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  36.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  37. </ItemGroup><ItemGroup>
  38.   
  39.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  40.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  41. </ItemGroup>return null;<ItemGroup>
  42.   
  43.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  44.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  45. </ItemGroup>  }<ItemGroup>
  46.   
  47.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  48.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  49. </ItemGroup><ItemGroup>
  50.   
  51.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  52.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  53. </ItemGroup>    var userDto = user.MapTo();<ItemGroup>
  54.   
  55.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  56.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  57. </ItemGroup>  return userDto;    }}
复制代码
案例2:订单实体类
  1. [DtoGenerator][Builder]public partial class OrderEntity{    [property: Column(Name = "id", IsPrimary = true)]    [property: Required]    private long? _id;<ItemGroup>
  2.   
  3.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  4.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  5. </ItemGroup>  [property: Column(Name = "order_no")]    [property: Required]    private string _orderNo;<ItemGroup>
  6.   
  7.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  8.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  9. </ItemGroup>  [property: Column(Name = "amount")]    [property: Required]    private decimal? _amount;<ItemGroup>
  10.   
  11.   <PackageReference Include="Mud.EntityCodeGenerator" Version="1.1.8" />
  12.   <PackageReference Include="Mud.ServiceCodeGenerator" Version="1.1.8" />
  13. </ItemGroup>  [property: Column(Name = "status")]    private string _status;}
复制代码
性能和安全性考虑

性能优势


  • 编译时生成:所有代码在编译时生成,运行时无额外开销
  • 无反射调用:生成的代码直接调用,避免反射带来的性能损耗
  • 类型安全:编译时检查确保类型安全,减少运行时错误
安全性考虑


  • 代码审查:虽然代码是自动生成的,但仍需要审查生成的代码以确保符合安全要求
  • 依赖注入:通过构造函数注入确保依赖关系明确,便于测试和维护
  • 访问控制:生成的属性和方法遵循.NET的访问控制原则
扩展和定制

Mud代码生成器设计为可扩展的,开发者可以根据自己的需求定制代码生成逻辑:

  • 自定义特性:可以创建自己的特性来控制代码生成行为
  • 模板定制:可以修改代码生成模板以适应特定需求
  • 插件机制:可以通过插件机制添加新的代码生成功能
总结

通过Mud代码生成器,我们可以在.NET平台上实现类似Java Lombok的功能,甚至更加丰富和强大。这套工具通过Roslyn源代码生成技术,在编译时自动生成我们需要的样板代码,大大提高了开发效率,减少了手动编写代码的工作量。
主要优势包括:

  • 提高开发效率:自动生成构造函数注入、Builder模式、DTO等代码
  • 保证代码质量:生成的代码遵循统一规范,减少人为错误
  • 提升性能:编译时生成,运行时无额外开销
  • 易于维护:当源代码变化时,相关代码自动更新
通过合理使用这套工具,我们可以专注于业务逻辑的实现,而将重复性的样板代码交给代码生成器处理,真正实现高效、高质量的软件开发。
无论你是正在开发新的.NET项目,还是想要重构现有项目以减少样板代码,Mud代码生成器都是一个值得考虑的强大工具。它不仅能够显著提高开发效率,还能帮助团队保持代码的一致性和可维护性。
开始使用Mud代码生成器,让你的.NET开发体验更加接近Java Lombok带来的便利,甚至更进一步!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册