|
前言
源生成器的好处很多, 通过在编译时生成代码,可以减少运行时的反射和动态代码生成,从而提高应用程序的性能, 有时候需要对程序AOT以及裁剪编译的dll也是需要用SG来处理的。
我们开发程序应该都绕不过Mapper对象映射,用的比较多的库可能就是AutoMapper,Maspter之内的三方库吧;这些库很强大但是因为内部实现存在反射,因此开发的程序就没办法AOT了,因此如果程序不是很复杂但是又有很特殊的需求,建议使用SG来实现Mapper
功能演示
这里我演示下自己开发的AutoDto生成DTO功能:
比如我们有一个User的类,需要生成UserDto- public class User
- {
- public string Id { get; set; } = null!;
- public string FirstName { get; set; } = null!;
- public string LastName { get; set; } = null!;
- public int? Age { get; set; }
- public string? FullName => $"{FirstName} {LastName}";
- }
复制代码 定义UserDto并标注特性:- [AutoDto<User>(nameof(User.Id))]//这里我们假设排除Id属性
- public partial record UserDto;
复制代码 就这样,源生成器将自动为我们生成对应的Dto:- partial record class UserDto
- {
- /// <inheritdoc cref = "User.FirstName"/>
- public string FirstName { get; set; }
- /// <inheritdoc cref = "User.LastName"/>
- public string LastName { get; set; }
- /// <inheritdoc cref = "User.Age"/>
- public int? Age { get; set; }
- }
复制代码 并同时为我们生成一个简单的Mapper扩展方法:- public static partial class UserToUserDtoExtentions
- {
- /// <summary>
- /// mapper to UserDto
- /// </summary>
- /// <returns></returns>
- public static UserDto MapperToUserDto(this User model)
- {
- return new UserDto()
- {
- FirstName = model.FirstName,
- LastName = model.LastName,
- Age = model.Age,
- FullName = model.FullName,
- };
- }
- }
复制代码 实现代码
[code]static void GENDTO(Compilation compilation, ImmutableArray nodes, SourceProductionContext context){ if (nodes.Length == 0) return; StringBuilder envStringBuilder = new(); envStringBuilder.AppendLine("// "); envStringBuilder.AppendLine("using System;"); envStringBuilder.AppendLine("using System.Collections.Generic;"); envStringBuilder.AppendLine("using System.Text;"); envStringBuilder.AppendLine("using System.Threading.Tasks;"); envStringBuilder.AppendLine("#pragma warning disable"); foreach (var nodeSyntax in nodes.AsEnumerable()) { //Cast() //Cast() if (nodeSyntax is not TypeDeclarationSyntax node) { continue; } //如果是Record类 var isRecord = nodeSyntax is RecordDeclarationSyntax; //如果不含partial关键字,则不生成 if (!node.Modifiers.Any(x => x.IsKind(SyntaxKind.PartialKeyword))) { continue; } AttributeSyntax? attributeSyntax = null; foreach (var attr in node.AttributeLists.AsEnumerable()) { var attrName = attr.Attributes.FirstOrDefault()?.Name.ToString(); if (attrName?.IndexOf(AttributeValueMetadataNameDto, System.StringComparison.Ordinal) == 0) { attributeSyntax = attr.Attributes.First(x => x.Name.ToString().IndexOf(AttributeValueMetadataNameDto, System.StringComparison.Ordinal) == 0); break; } } if (attributeSyntax == null) { continue; } //转译的Entity类名 var entityName = string.Empty; string pattern = @"(? |
|