利用.Net的Source Generator功能,生成开发过程中哪些无聊的代码。
- 代码实时生成,无需额外操作,立即生效
- 开发过程中生成的代码,执行性能比运行时反射更有效率
https://www.bilibili.com/video/BV1a3411Y7xb?share_source=copy_web
Install-Package CC.CodeGenerator
Install-Package CC.NetCore
因为VS的原因,在添加包引用或者升级包版本后,建议重启VS。
global using CC.CodeGenerator;
Mapping
启用对象映射,可指定多个映射对象
MappingIgnore
忽略不需要的属性
[Mapping(typeof(People2Map), typeof(People3Map))]
public partial class People1Map
{
public Guid PeopleId { get; set; }
public string UserName { get; set; }
public string City { get; set; }
[MappingIgnore]
public string Disply => $"{UserName}";
}
public class People2Map
{
public Guid PeopleId { get; set; }
public string UserName { get; set; }
}
public class People3Map
{
public string City { get; set; }
}
进行对象之间的赋值
//初始新的Dto
var people1Map = new People1Map() { PeopleId=Guid.NewGuid(),UserName="Tim" };
var people2Map = new People2Map();
var people3Map = new People3Map() { City="ShangHai"};
//复制到对象
people1Map.CopyTo(people2Map);
//从对象复制来
people1Map.CopyFrom(people3Map);
//从别的对象初始化
var people4Map = new People1Map(people2Map);
简化在EF的Select中的无意义赋值代码,并能从多个对象汇获取数据
[Mapping(typeof(People), typeof(City))]
public partial class PeopleViewDto
{
public Guid PeopleId { get; set; }
public string Name { get; set; }
public string CityTitle { get; set; }
public List<SkillViewDto> SkillViews { get; set; }
}
[Mapping(typeof(Skill))]
public partial class SkillViewDto
{
public Guid SkillId { get; set; }
public Guid PeopleId { get; set; }
}
//简化赋值
var PeopleViewDtos1 = context.People
.Select(x => new PeopleViewDto(x)
{
CityTitle = x.City.CityTitle,
SkillViews = x.Skill.Select(y => new SkillViewDto(y)).ToList()
})
.ToList();
//通过级联CopyFrom函数可以从多个实体获得数据
var PeopleViewDtos2 = context.People
.Select(x => new PeopleViewDto(x)
{
SkillViews = x.Skill.Select(y => new SkillViewDto(y)).ToList()
}
.CopyFrom(x.City))
.ToList();
Service
自动创建服务注册代码,让Program更加清洁
- LifeCycle:自定义生命周期,默认Scoped
AutoInject
自动创建注入代码
var builder = WebApplication.CreateBuilder(args);
CC.CodeGenerator.AutoDI.AddServices(builder);//加入此行代码
[Service(LifeCycle = ELifeCycle.Singleton)]
public class WeatherForecastService
{
[AutoInject]
public DemoService3 DemoService3 { get; }
}
Dto
增强实体特性,提供对象赋值,默认增删改查代码
- Context:上下文对象
- Entity:映射的EF实体
Ignore
忽略不需要的属性
[Dto(Context=nameof(DemoaContext),Entity =typeof(People))]
public partial record PeopleDto
{
public Guid PeopleId { get; set; }
public string UserName { get; set; }
public string City { get; set; }
[DtoIgnore]
public string Disply => $"{UserName}";
}
var context = new DemoaContext();
//创建Dto
var secondDto = new PeopleDto() { City = "ShangHai" };
//初始新的Dto
var firstDto = PeopleDto.NewGen();
//快速从Dto复制
firstDto.CopyFormDto(secondDto);
//EF快速Select
var peopleEntityDtos = context.People.Where(x=>x.City == "ShangHai").ToPeopleDtos();
//快速载入Dto
var peopleEntityDto = PeopleDto.LoadGen(context, new Guid(""));
//Dto复制到实体
var peopleEntity = context.People.FirstOrDefault();
peopleEntityDto.CopyToEntity(peopleEntity);
//Dto重新载入
peopleEntityDto.ReLoadGen(context);
//Dto快速保存
peopleEntityDto.City = "北京";
peopleEntityDto.SaveGen(context);
//Dto快速删除
peopleEntityDto.DeleteGen(context);
//最后保存操作
context.SaveChanges();
[AddNotifyPropertyChanged("Id", typeof(long), XmlSummary = "从类上创建属性")]
partial class Demo0
{
[AddNotifyPropertyChanged(XmlSummary = "从字段创建属性")]
private string _name;
}
生成代码如下
partial class Demo0 : INotifyPropertyChanged
{
#region 接口相关
public event PropertyChangedEventHandler? PropertyChanged;
private bool SetProperty<T>(ref T storage, T value , [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string? propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
#region 生成的属性和字段
private long _id;
/// <summary>
/// 从类上创建属性
/// </summary>
public long Id
{
get => _id;
set => SetProperty(ref _id, value);
}
/// <summary>
/// 从字段创建属性
/// </summary>
public string? Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
}