首页 > 其他分享 >利用源生成器,在编译阶段生成映射代码,减少运行时反射

利用源生成器,在编译阶段生成映射代码,减少运行时反射

时间:2024-08-23 10:18:27浏览次数:12  
标签:Product nameof 映射 生成器 编译 result ProductDto public

利用源生成器,在编译阶段生成映射代码,减少运行时反射

这里有一个Product类和ProductDto类,实现对象自身的拷贝,或者Product映射ProductDto

GenMapperAttribute标注了类型需要生成映射方法,同时要求实现IAutoMap接口(由生成器自动实现)

构造函数可选参数为目标类型,默认是自身

MaoToAttributeMapFromAttribute用于自定义转换动作,顾名思义,MapTo是用于当前类型转换到目标类型用的,MapFrom是在目标类型标注的,由当前类型调用

public interface IAutoMap
{
    object MapTo(string? target = null);
}
[GenMapper]
[GenMapper(typeof(ProductDto))]
internal partial class Product : IAutoMap
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public string? Category { get; set; }
    [MapTo(Target = typeof(ProductDto), Name = nameof(ProductDto.Date))]
    public DateTime? ProductDate { get; set; }
    public IEnumerable<Product> Products { get; set; } = [];
    
}

internal class ProductDto
{
    public static string NameMapFrom(Product p)
    {
        return $"{p.Category}-{p.Name}";
    }
    public int Id { get; set; }

    [MapFrom(Source = typeof(Product), By = nameof(NameMapFrom))]
    public string? Name { get; set; }
    //[MapFrom(Source = typeof(Product), Name = nameof(Product.ProductDate))]
    public DateTime? Date { get; set; }
}

对于Product类型,生成器将生成如下代码


// <auto-generated/>
#pragma warning disable
namespace TestProject1.Models
{
    [global::System.CodeDom.Compiler.GeneratedCode("AutoGenMapperGenerator.AutoMapperGenerator", "1.0.0.0")]
    /// <inheritdoc/>
    partial class Product 
    {
        [global::System.CodeDom.Compiler.GeneratedCode("AutoGenMapperGenerator.AutoMapperGenerator", "1.0.0.0")]
        public TestProject1.Models.Product MapToProduct()
        {
            var result = new TestProject1.Models.Product();
            result.Id = this.Id;
            result.Name = this.Name;
            result.Category = this.Category;
            result.ProductDate = this.ProductDate;
            result.Products = this.Products.Select(i => i.MapTo<TestProject1.Models.Product>("Product")).ToList();
            return result;
        }

        [global::System.CodeDom.Compiler.GeneratedCode("AutoGenMapperGenerator.AutoMapperGenerator", "1.0.0.0")]
        public TestProject1.Models.ProductDto MapToProductDto()
        {
            var result = new TestProject1.Models.ProductDto();
            result.Date = this.ProductDate;
            result.Id = this.Id;
            result.Name = TestProject1.Models.ProductDto.NameMapFrom(this);
            return result;
        }

        [global::System.CodeDom.Compiler.GeneratedCode("AutoGenMapperGenerator.AutoMapperGenerator", "1.0.0.0")]
        public object? MapTo(string? target = null)
        {
            if (string.IsNullOrEmpty(target))
                throw new ArgumentNullException(nameof(target), "存在多个目标类型,请指定目标类型,推荐使用nameof(TargetType)");
            if (target == nameof(Product))
               return MapToProduct();
            if (target == nameof(ProductDto))
               return MapToProductDto();
            throw new ArgumentException("未找到指定目标类型的映射方法");
        }
    }
}

因此,对于一个已有的Product实例,你可以用如下方法获取Product新实例和ProductDto实例

var p = new Product();
var p1 = p.MapToProduct();
var pdto = p.MapToProductDto();
// 或者使用IAutoMap接口
var p2 = p.MapTo<Product>(nameof(Product));
var dto2 = p.MapTo<ProductDto>(nameof(ProductDto))

总结

源生成器号称编译阶段的反射,性能上确定很有优势。但是目前配置的话确实不方便,需要在字段上进行Attribute标注,字段匹配规则也还没设置

感兴趣的可以看看源码生成器源码地址

标签:Product,nameof,映射,生成器,编译,result,ProductDto,public
From: https://www.cnblogs.com/marvelTitile/p/18375421

相关文章

  • 05-03 Map Persistent Objects to Database Views(将持久对象映射到数据库视图 )
    MapPersistentObjectstoDatabaseViews(将持久对象映射到数据库视图)CreateaPersistentClass(创建持久类)Createapersistentclass.Theclassnameshouldmatchtheviewname.创建一个持久类。类名应与视图名匹配。AssignthePersistentattributetotheper......
  • 20240819编译 链接 单片机执行的第一个语句
    2024年8月中旬在宝鸡出差,在B站上学习了下。在linux操作系统中,gdb是调试器,gcc是编译器。Linux操作系统将main.elf文件加载到内存中以后,操作系统为其分配进程,然后main函数就开始执行了。输入layoutasm则显示出来汇编代码 键入“starti”的时候 进入到程序里面的第一......
  • CMake编译不同文件目录下的C++文件
        由于我们构建一个项目的时候,通常不会将所有的源文件放在一个文件目录下,这样既不方便开发,也不方便源码阅读,我们通常会对项目文件进行分层,比如分为include、src、res、lib这些目录,src下又分为model、controller、view这些目录。所以跨文件编译C++文件就相当必要了,如......
  • 在CentOS7.9上 编译安装openssl-3.3.1+编译安装Nginx1.26.2
    编译安装注意事项知识点一:openssl的重要性openssl在Linux系统中扮演着至关重要的角色,尤其是在网络安全方面。许多服务和应用程序都依赖于openssl提供的加密功能,包括但不限于web服务器(如Apache和Nginx)、数据库服务器(如MySQL和PostgreSQL)、邮件服务器、VPN等。以下......
  • 减小编译出来的 .so 文件的尺寸方法
    要减小编译出来的.so文件的尺寸,可以通过去除符号表、调试信息等非必要的内容来实现:一、Linux系统下方法1.使用strip命令strip命令可以删除.so文件中的符号表和调试信息,从而减小文件大小。strip--strip-unneededlibyourlibrary.so--strip-unneeded参数只会......
  • 深入理解Android MTP之存储映射分析
    深入理解AndroidMTP之UsbService启动分析 分析了MTP的服务端的启动,本文来分析切换MTP模式后,存储中的数据(文件、目录)是如何映射到PC端的。首先你得知道如何切换MTP模式。当手机通过usb连接电脑时,会出现一个关于usb的通知,点击通知后,会出现一个类似如下的界面这个FileTransfe......
  • 【生日视频制作】公园火车飞艇热气球AE模板修改文字软件生成器教程特效素材【AE模板】
    公园火车飞艇热气球生日视频制作教程AE模板修改文字特效软件生成器素材怎么如何做的【生日视频制作】公园火车飞艇热气球AE模板修改文字软件生成器教程特效素材【AE模板】生日视频制作步骤:安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频......
  • EF Core使用SharedTypeEntity,映射实体类到不同的数据库表(转载)
    我们可以借助EFCore的SharedTypeEntity,映射一个实体类到多个结构相同的数据库表:publicclassUser{publicintId{get;set;}publicstringName{get;set;}}publicclassSomeDbContext:DbContext{protectedoverridevoidOnConfiguring(DbConte......
  • Python 实现批量数字二维码生成器
    Python实现批量数字二维码生成器创建时间:2024-08-09一、背景手动逐个生成特定格式和内容的二维码是一项繁琐且耗时的任务。虽然有写二维码工具也可以制作,但是往往有一些限制,为了能够高效、批量生成自定义二维码的需求,开发了这个基于Python的数字二维码生成器应用程序。在实......
  • 【生日视频制作】教师节中秋节国庆节小蛮腰广州塔心形照片AE模板修改文字软件生成器教
    广州塔心形照片生日视频制作教程AE模板改字特效软件生成器素材怎么如何做的【生日视频制作】教师节中秋节国庆节小蛮腰广州塔心形照片AE模板修改文字软件生成器教程特效素材【AE模板】生日视频制作步骤:安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出......