基于 Attribute 生成代码
June 21, 2021 · View on GitHub
生成模型
在类上标记 [AdaptFrom], [AdaptTo], 或 [AdaptTwoWays]:
[AdaptTo("[name]Dto")]
public class Student {
...
}
这将会生成:
public class StudentDto {
...
}
在生成时忽略一些成员
默认代码生成将忽略标记了 [AdaptIgnore] 特性的成员,但是可以通过 IgnoreAttributes, IgnoreNoAttributes, IgnoreNamespaces 特性标记自定义生成代码忽略成员的逻辑。
例如,使用 IgnoreNoAttributes 特性配置让没有 [DataMember] 特性标记的成员在生成时忽略:
[AdaptTo("[name]Dto", IgnoreNoAttributes = new[] { typeof(DataMemberAttribute) })]
public class Student {
[DataMember]
public string Name { get; set; } // 这个属性将生成到DTO
public string LastName { get; set; } // 这个属性将不会生成到DTO
}
修改属性类型
默认情况下,代码生成将在同一声明上转发类型。例如,Student 有ICollection<Enrollment>,代码生成后StudentDto 将有ICollection<EnrollmentDto>。
可以通过 [PropertyType(typeof(Target))] 特性标记重写默认行为
这个特性标记既可以注释到属性上,也可以特性标记到类上。
例:
[AdaptTo("[name]Dto")]
public class Student {
public ICollection<Enrollment> Enrollments { get; set; }
}
[AdaptTo("[name]Dto"), PropertyType(typeof(DataItem))]
public class Enrollment {
[PropertyType(typeof(string))]
public Grade? Grade { get; set; }
}
这将生成:
public class StudentDto {
public ICollection<DataItem> Enrollments { get; set; }
}
public class EnrollmentDto {
public string Grade { get; set; }
}
生成只读属性
对于 [AdaptTo] 和 [AdaptTwoWays] 特性标记,可以通过设置 MapToConstructor来生成只读属性:
[AdaptTo("[name]Dto", MapToConstructor = true)]
public class Student {
public string Name { get; set; }
}
这将生成:
public class StudentDto {
public string Name { get; }
public StudentDto(string name) {
this.Name = name;
}
}
生成可空属性
对于 [AdaptFrom] 特性标记,可以通过设置 IgnoreNullValues来生成可空属性:
[AdaptFrom("[name]Merge", IgnoreNullValues = true)]
public class Student {
public int Age { get; set; }
}
这将生成:
public class StudentMerge {
public int? Age { get; set; }
}
生成扩展方法
使用 [GenerateMapper] 特性标记
对于任何带有 [AdaptFrom], [AdaptTo] 或 [AdaptTwoWays] 特性标记的实体类,可以通过添加 [GenerateMapper] 特性标记实现生成扩展方法:
[AdaptTo("[name]Dto"), GenerateMapper]
public class Student {
...
}
这将生成:
public class StudentDto {
...
}
public static class StudentMapper {
public static StudentDto AdaptToDto(this Student poco) { ... }
public static StudentDto AdaptTo(this Student poco, StudentDto dto) { ... }
public static Expression<Func<Student, StudentDto>> ProjectToDto => ...
}
配置
如果有映射配置,它必须在实现了 IRegister 的类中:
public class MyRegister : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<TSource, TDestination>();
}
}
使用配置生成
可以生成扩展方法并从映射配置中添加额外的设置。
public class MyRegister : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<TSource, TDestination>()
.GenerateMapper(MapType.Map | MapType.MapToTarget);
}
}