热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#AutoMapper使用方法总结

这篇文章主要介绍了C#AutoMapper使用方法,文中讲解非常细致,代码帮助大家更好的理解学习,感兴趣的朋友可以了解下

本文基于 AutoMapper 9.0.0

AutoMapper 是一个对象-对象映射器,可以将一个对象映射到另一个对象。

官网地址:http://automapper.org/

官方文档:https://docs.automapper.org/en/latest/

1 入门例子

public class Foo
{
 public int ID { get; set; }

 public string Name { get; set; }
}

public class FooDto
{
 public int ID { get; set; }

 public string Name { get; set; }
}

public void Map()
{
 var cOnfig= new MapperConfiguration(cfg => cfg.CreateMap());

 var mapper = config.CreateMapper();

 Foo foo = new Foo { ID = 1, Name = "Tom" };

 FooDto dto = mapper.Map(foo);
}

2 注册

在使用 Map 方法之前,首先要告诉 AutoMapper 什么类可以映射到什么类。

var cOnfig= new MapperConfiguration(cfg => cfg.CreateMap());

每个 AppDomain 只能进行一次配置。这意味着放置配置代码的最佳位置是在应用程序启动中,例如 ASP.NET 应用程序的 Global.asax 文件。

从 9.0 开始 Mapper.Initialize 方法就不可用了。

2.1 Profile

Profile 是组织映射的另一种方式。新建一个类,继承 Profile,并在构造函数中配置映射。

public class EmployeeProfile : Profile
{
 public EmployeeProfile()
 {
  CreateMap();
 }
}

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.AddProfile();
});

Profile 内部的配置仅适用于 Profile 内部的映射。应用于根配置的配置适用于所有创建的映射。

AutoMapper 也可以在指定的程序集中扫描从 Profile 继承的类,并将其添加到配置中。

var cOnfig= new MapperConfiguration(cfg =>
{
 // 扫描当前程序集
 cfg.AddMaps(System.AppDomain.CurrentDomain.GetAssemblies());
 
 // 也可以传程序集名称(dll 名称)
 cfg.AddMaps("LibCoreTest");
});

3 配置

3.1 命名约定

默认情况下,AutoMapper 基于相同的字段名映射,并且是 不区分大小写 的。

但有时,我们需要处理一些特殊的情况。

  • SourceMemberNamingConvention 表示源类型命名规则
  • DestinationMemberNamingConvention 表示目标类型命名规则

LowerUnderscoreNamingConvention PascalCaseNamingConvention 是 AutoMapper 提供的两个命名规则。前者命名是小写并包含下划线,后者就是帕斯卡命名规则(每个单词的首字母大写)。

我的理解,如果源类型和目标类型分别采用了 蛇形命名法 和 驼峰命名法,那么就需要指定命名规则,使其能正确映射。

public class Foo
{
 public int Id { get; set; }

 public string MyName { get; set; }
}

public class FooDto
{
 public int ID { get; set; }

 public string My_Name { get; set; }
}

public void Map()
{
 var cOnfig= new MapperConfiguration(cfg =>
 {
  cfg.CreateMap();

  cfg.SourceMemberNamingCOnvention= new PascalCaseNamingConvention();
  cfg.DestinatiOnMemberNamingConvention= new LowerUnderscoreNamingConvention();
 });

 var mapper = config.CreateMapper();

 Foo foo = new Foo { Id = 2, MyName = "Tom" };

 FooDto dto = mapper.Map(foo);
}

3.2 配置可见性

默认情况下,AutoMapper 仅映射 public 成员,但其实它是可以映射到 private 属性的。

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.SetMethod.IsPrivate;
 cfg.CreateMap();
});

需要注意的是,这里属性必须添加 private set,省略 set 是不行的。

3.3 全局属性/字段过滤

默认情况下,AutoMapper 尝试映射每个公共属性/字段。以下配置将忽略字段映射。

var cOnfig= new MapperConfiguration(cfg =>
{
	cfg.ShouldMapField = fi => false;
});

3.4 识别前缀和后缀

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.RecognizePrefixes("My");
 cfg.RecognizePostfixes("My");
}

3.5 替换字符

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.ReplaceMemberName("Ä", "A");
});

这功能我们基本上用不上。

4 调用构造函数

有些类,属性的 set 方法是私有的。

public class Commodity
{
 public string Name { get; set; }

 public int Price { get; set; }
}

public class CommodityDto
{
 public string Name { get; }

 public int Price { get; }

 public CommodityDto(string name, int price)
 {
  Name = name;
  Price = price * 2;
 }
}

AutoMapper 会自动找到相应的构造函数调用。如果在构造函数中对参数做一些改变的话,其改变会反应在映射结果中。如上例,映射后 Price 会乘 2。

禁用构造函数映射:

public class Commodity
{
 public string Name { get; set; }

 public int Price { get; set; }
}

public class CommodityDto
{
 public string Name { get; }

 public int Price { get; }

 public CommodityDto(string name, int price)
 {
  Name = name;
  Price = price * 2;
 }
}

AutoMapper 会自动找到相应的构造函数调用。如果在构造函数中对参数做一些改变的话,其改变会反应在映射结果中。如上例,映射后 Price 会乘 2。

禁用构造函数映射:

var cOnfig= new MapperConfiguration(cfg => cfg.DisableConstructorMapping());

禁用构造函数映射的话,目标类要有一个无参构造函数。

5 数组和列表映射

数组和列表的映射比较简单,仅需配置元素类型,定义简单类型如下:

public class Source
{
 public int Value { get; set; }
}

public class Destination
{
 public int Value { get; set; }
}

映射:

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.CreateMap();
});
IMapper mapper = config.CreateMapper();

var sources = new[]
{
 new Source { Value = 5 },
 new Source { Value = 6 },
 new Source { Value = 7 }
};

IEnumerable ienumerableDest = mapper.Map>(sources);
ICollection icollectiOnDest= mapper.Map>(sources);
IList ilistDest = mapper.Map>(sources);
List listDest = mapper.Map>(sources);
Destination[] arrayDest = mapper.Map(sources);

具体来说,支持的源集合类型包括:

  • IEnumerable
  • IEnumerable
  • ICollection
  • ICollection
  • IList
  • IList
  • List
  • Arrays

映射到现有集合时,将首先清除目标集合。如果这不是你想要的,请查看AutoMapper.Collection。

5.1 处理空集合

映射集合属性时,如果源值为 null,则 AutoMapper 会将目标字段映射为空集合,而不是 null。这与 Entity Framework 和 Framework Design Guidelines 的行为一致,认为 C# 引用,数组,List,Collection,Dictionary 和 IEnumerables 永远不应该为 null

5.2 集合中的多态

这个官方的文档不是很好理解。我重新举个例子。实体类如下:

public class Employee
{
 public int ID { get; set; }

 public string Name { get; set; }
}

public class Employee2 : Employee
{
 public string DeptName { get; set; }
}

public class EmployeeDto
{
 public int ID { get; set; }

 public string Name { get; set; }
}

public class EmployeeDto2 : EmployeeDto
{
 public string DeptName { get; set; }
}

数组映射代码如下:

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.CreateMap().Include();
 cfg.CreateMap();
});
IMapper mapper = config.CreateMapper();

var employees = new[]
{
 new Employee { ID = 1, Name = "Tom" },
 new Employee2 { ID = 2, Name = "Jerry", DeptName = "R & D" }
};

var dto = mapper.Map(employees);

可以看到,映射后,dto 中两个元素的类型,一个是 EmployeeDto,一个是 EmployeeDto2,即实现了父类映射到父类,子类映射到子类。

如果去掉 Include 方法,则映射后 dto 中两个元素的类型均为 EmployeeDto。

6 方法到属性映射

AutoMapper 不仅能实现属性到属性映射,还可以实现方法到属性的映射,并且不需要任何配置,方法名可以和属性名一致,也可以带有 Get 前缀。

例如下例的 Employee.GetFullName() 方法,可以映射到 EmployeeDto.FullName 属性。

public class Employee
{
 public int ID { get; set; }

 public string FirstName { get; set; }

 public string LastName { get; set; }

 public string GetFullName()
 {
  return $"{FirstName} {LastName}";
 }
}

public class EmployeeDto
{
 public int ID { get; set; }

 public string FirstName { get; set; }

 public string LastName { get; set; }

 public string FullName { get; set; }
}

7 自定义映射

当源类型与目标类型名称不一致时,或者需要对源数据做一些转换时,可以用自定义映射。

public class Employee
{
 public int ID { get; set; }

 public string Name { get; set; }

 public DateTime JoinTime { get; set; }
}

public class EmployeeDto
{
 public int EmployeeID { get; set; }

 public string EmployeeName { get; set; }

 public int JoinYear { get; set; }
}

如上例,IDEmployeeID 属性名不同,JoinTime JoinYear 不仅属性名不同,属性类型也不同。

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.CreateMap()
  .ForMember("EmployeeID", opt => opt.MapFrom(src => src.ID))
  .ForMember(dest => dest.EmployeeName, opt => opt.MapFrom(src => src.Name))
  .ForMember(dest => dest.JoinYear, opt => opt.MapFrom(src => src.JoinTime.Year));
});

8 扁平化映射

对象-对象映射的常见用法之一是将复杂的对象模型并将其展平为更简单的模型。

public class Employee
{
 public int ID { get; set; }

 public string Name { get; set; }

 public Department Department { get; set; }
}

public class Department
{
 public int ID { get; set; }

 public string Name { get; set; }
}

public class EmployeeDto
{
 public int ID { get; set; }

 public string Name { get; set; }

 public int DepartmentID { get; set; }

 public string DepartmentName { get; set; }
}

如果目标类型上的属性,与源类型的属性、方法都对应不上,则 AutoMapper 会将目标成员名按驼峰法拆解成单个单词,再进行匹配。例如上例中,EmployeeDto.DepartmentID 就对应到了 Employee.Department.ID。

8.1 IncludeMembers

如果属性命名不符合上述的规则,而是像下面这样:

public class Employee
{
 public int ID { get; set; }

 public string Name { get; set; }

 public Department Department { get; set; }
}

public class Department
{
 public int DepartmentID { get; set; }

 public string DepartmentName { get; set; }
}

public class EmployeeDto
{
 public int ID { get; set; }

 public string Name { get; set; }

 public int DepartmentID { get; set; }

 public string DepartmentName { get; set; }
}

Department 类中的属性名,直接跟 EmployeeDto 类中的属性名一致,则可以使用 IncludeMembers 方法指定。

9 嵌套映射

有时,我们可能不需要展平。看如下例子:

public class Employee
{
 public int ID { get; set; }

 public string Name { get; set; }

 public int Age { get; set; }

 public Department Department { get; set; }
}

public class Department
{
 public int ID { get; set; }

 public string Name { get; set; }

 public string Heads { get; set; }
}

public class EmployeeDto
{
 public int ID { get; set; }

 public string Name { get; set; }

 public DepartmentDto Department { get; set; }
}

public class DepartmentDto
{
 public int ID { get; set; }

 public string Name { get; set; }
}

我们要将 Employee 映射到 EmployeeDto,并且将 Department 映射到 DepartmentDto

var cOnfig= new MapperConfiguration(cfg =>
{
 cfg.CreateMap();
 cfg.CreateMap();
});

以上就是C# AutoMapper 使用方法总结的详细内容,更多关于C# AutoMapper 用法的资料请关注其它相关文章!


推荐阅读
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • 从Oracle安全移植到国产达梦数据库的DBA实践与攻略
    随着我国对信息安全和自主可控技术的重视,国产数据库在党政机关、军队和大型央企等行业中得到了快速应用。本文介绍了如何降低从Oracle到国产达梦数据库的技术门槛,保障用户现有业务系统投资。具体包括分析待移植系统、确定移植对象、数据迁移、PL/SQL移植、校验移植结果以及应用系统的测试和优化等步骤。同时提供了移植攻略,包括待移植系统分析和准备移植环境的方法。通过本文的实践与攻略,DBA可以更好地完成Oracle安全移植到国产达梦数据库的工作。 ... [详细]
  • Node.js学习笔记(一)package.json及cnpm
    本文介绍了Node.js中包的概念,以及如何使用包来统一管理具有相互依赖关系的模块。同时还介绍了NPM(Node Package Manager)的基本介绍和使用方法,以及如何通过NPM下载第三方模块。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 本文介绍了连接库的定义和使用方法。连接库是通过编译生成的dll文件,例如php_mysql.dll。在使用扩展时,需要去掉配置文件中的分号,并通过phpinfo查看是否正确加载了mysql连接库。详细内容请参考链接:https://www.cnblogs.com/xiaobiaomei/p/7654750.html。摘要字数:180字。 ... [详细]
  • 本文介绍了2015年九月八日的js学习总结及相关知识点,包括参考书《javaScript Dom编程的艺术》、js简史、Dom、DHTML、解释型程序设计和编译型程序设计等内容。同时还提到了最佳实践是将标签放到HTML文档的最后,并且对语句和注释的使用进行了说明。 ... [详细]
  • ps:写的第一个,不足之处,欢迎拍砖---只是想用自己的方法一步步去实现一些框架看似高大上的小功能(比如说模型中的toArraytoJsonsetAtt ... [详细]
author-avatar
YON永世
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有