欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# AutoMapper 使用方法總結(jié)

 更新時(shí)間:2020年06月15日 14:21:50   作者:丹楓無跡  
這篇文章主要介紹了C# AutoMapper 使用方法,文中講解非常細(xì)致,代碼幫助大家更好的理解學(xué)習(xí),感興趣的朋友可以了解下

本文基于 AutoMapper 9.0.0

AutoMapper 是一個(gè)對(duì)象-對(duì)象映射器,可以將一個(gè)對(duì)象映射到另一個(gè)對(duì)象。

官網(wǎng)地址: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<Foo, FooDto>());

 var mapper = config.CreateMapper();

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

 FooDto dto = mapper.Map<FooDto>(foo);
}

2 注冊(cè)

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

var config = new MapperConfiguration(cfg => cfg.CreateMap<Foo, FooDto>());

每個(gè) AppDomain 只能進(jìn)行一次配置。這意味著放置配置代碼的最佳位置是在應(yīng)用程序啟動(dòng)中,例如 ASP.NET 應(yīng)用程序的 Global.asax 文件。

從 9.0 開始 Mapper.Initialize 方法就不可用了。

2.1 Profile

Profile 是組織映射的另一種方式。新建一個(gè)類,繼承 Profile,并在構(gòu)造函數(shù)中配置映射。

public class EmployeeProfile : Profile
{
 public EmployeeProfile()
 {
  CreateMap<Employee, EmployeeDto>();
 }
}

var config = new MapperConfiguration(cfg =>
{
 cfg.AddProfile<EmployeeProfile>();
});

Profile 內(nèi)部的配置僅適用于 Profile 內(nèi)部的映射。應(yīng)用于根配置的配置適用于所有創(chuàng)建的映射。

AutoMapper 也可以在指定的程序集中掃描從 Profile 繼承的類,并將其添加到配置中。

var config = new MapperConfiguration(cfg =>
{
 // 掃描當(dāng)前程序集
 cfg.AddMaps(System.AppDomain.CurrentDomain.GetAssemblies());
 
 // 也可以傳程序集名稱(dll 名稱)
 cfg.AddMaps("LibCoreTest");
});

3 配置

3.1 命名約定

默認(rèn)情況下,AutoMapper 基于相同的字段名映射,并且是 不區(qū)分大小寫 的。

但有時(shí),我們需要處理一些特殊的情況。

  • SourceMemberNamingConvention 表示源類型命名規(guī)則
  • DestinationMemberNamingConvention 表示目標(biāo)類型命名規(guī)則

LowerUnderscoreNamingConvention PascalCaseNamingConvention 是 AutoMapper 提供的兩個(gè)命名規(guī)則。前者命名是小寫并包含下劃線,后者就是帕斯卡命名規(guī)則(每個(gè)單詞的首字母大寫)。

我的理解,如果源類型和目標(biāo)類型分別采用了 蛇形命名法 和 駝峰命名法,那么就需要指定命名規(guī)則,使其能正確映射。

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<Foo, FooDto>();

  cfg.SourceMemberNamingConvention = new PascalCaseNamingConvention();
  cfg.DestinationMemberNamingConvention = new LowerUnderscoreNamingConvention();
 });

 var mapper = config.CreateMapper();

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

 FooDto dto = mapper.Map<FooDto>(foo);
}

3.2 配置可見性

默認(rèn)情況下,AutoMapper 僅映射 public 成員,但其實(shí)它是可以映射到 private 屬性的。

var config = new MapperConfiguration(cfg =>
{
 cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.SetMethod.IsPrivate;
 cfg.CreateMap<Source, Destination>();
});

需要注意的是,這里屬性必須添加 private set,省略 set 是不行的。

3.3 全局屬性/字段過濾

默認(rèn)情況下,AutoMapper 嘗試映射每個(gè)公共屬性/字段。以下配置將忽略字段映射。

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

3.4 識(shí)別前綴和后綴

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

3.5 替換字符

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

這功能我們基本上用不上。

4 調(diào)用構(gòu)造函數(shù)

有些類,屬性的 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 會(huì)自動(dòng)找到相應(yīng)的構(gòu)造函數(shù)調(diào)用。如果在構(gòu)造函數(shù)中對(duì)參數(shù)做一些改變的話,其改變會(huì)反應(yīng)在映射結(jié)果中。如上例,映射后 Price 會(huì)乘 2。

禁用構(gòu)造函數(shù)映射:

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 會(huì)自動(dòng)找到相應(yīng)的構(gòu)造函數(shù)調(diào)用。如果在構(gòu)造函數(shù)中對(duì)參數(shù)做一些改變的話,其改變會(huì)反應(yīng)在映射結(jié)果中。如上例,映射后 Price 會(huì)乘 2。

禁用構(gòu)造函數(shù)映射:

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

禁用構(gòu)造函數(shù)映射的話,目標(biāo)類要有一個(gè)無參構(gòu)造函數(shù)。

5 數(shù)組和列表映射

數(shù)組和列表的映射比較簡單,僅需配置元素類型,定義簡單類型如下:

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

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

映射:

var config = new MapperConfiguration(cfg =>
{
 cfg.CreateMap<Source, Destination>();
});
IMapper mapper = config.CreateMapper();

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

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

具體來說,支持的源集合類型包括:

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

映射到現(xiàn)有集合時(shí),將首先清除目標(biāo)集合。如果這不是你想要的,請(qǐng)查看AutoMapper.Collection。

5.1 處理空集合

映射集合屬性時(shí),如果源值為 null,則 AutoMapper 會(huì)將目標(biāo)字段映射為空集合,而不是 null。這與 Entity Framework 和 Framework Design Guidelines 的行為一致,認(rèn)為 C# 引用,數(shù)組,List,Collection,Dictionary 和 IEnumerables 永遠(yuǎn)不應(yīng)該為 null。

5.2 集合中的多態(tài)

這個(gè)官方的文檔不是很好理解。我重新舉個(gè)例子。實(shí)體類如下:

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; }
}

數(shù)組映射代碼如下:

var config = new MapperConfiguration(cfg =>
{
 cfg.CreateMap<Employee, EmployeeDto>().Include<Employee2, EmployeeDto2>();
 cfg.CreateMap<Employee2, EmployeeDto2>();
});
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<Employee[], EmployeeDto[]>(employees);

可以看到,映射后,dto 中兩個(gè)元素的類型,一個(gè)是 EmployeeDto,一個(gè)是 EmployeeDto2,即實(shí)現(xiàn)了父類映射到父類,子類映射到子類。

如果去掉 Include 方法,則映射后 dto 中兩個(gè)元素的類型均為 EmployeeDto。

6 方法到屬性映射

AutoMapper 不僅能實(shí)現(xiàn)屬性到屬性映射,還可以實(shí)現(xiàn)方法到屬性的映射,并且不需要任何配置,方法名可以和屬性名一致,也可以帶有 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 自定義映射

當(dāng)源類型與目標(biāo)類型名稱不一致時(shí),或者需要對(duì)源數(shù)據(jù)做一些轉(zhuǎn)換時(shí),可以用自定義映射。

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<Employee, EmployeeDto>()
  .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 扁平化映射

對(duì)象-對(duì)象映射的常見用法之一是將復(fù)雜的對(duì)象模型并將其展平為更簡單的模型。

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; }
}

如果目標(biāo)類型上的屬性,與源類型的屬性、方法都對(duì)應(yīng)不上,則 AutoMapper 會(huì)將目標(biāo)成員名按駝峰法拆解成單個(gè)單詞,再進(jìn)行匹配。例如上例中,EmployeeDto.DepartmentID 就對(duì)應(yīng)到了 Employee.Department.ID。

8.1 IncludeMembers

如果屬性命名不符合上述的規(guī)則,而是像下面這樣:

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 嵌套映射

有時(shí),我們可能不需要展平??慈缦吕樱?/p>

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<Employee, EmployeeDto>();
 cfg.CreateMap<Department, DepartmentDto>();
});

以上就是C# AutoMapper 使用方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于C# AutoMapper 用法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論