使用 .NET Core API 2.1 的 Automapper






4.84/5 (10投票s)
本文帮助你开始使用 automapper 并使用一些常用的功能。
引言
AutoMapper 是一种对象到对象的映射,用于轻松地映射不同的对象。 Automapper 最常见的场景之一是尝试将实际对象转换为 DTO 对象。
为了给你一个更好的例子,请考虑以下代码
var Department = GetDepartmentDetails();
DepartmentDetailsDTO obj = new DepartmentDetailsDTO()
{
obj.Name = Department.Name,
obj.Id = Department.Id,
...
...
//So on . .
}
想象一下,仅仅为了忽略主对象的一些属性而浪费了多少行代码。 因此,AutoMapper 派上用场,将上面的代码块替换为单行!
在本文中,我们将了解如何在你的项目中设置 Automapper 并使用其一些最受欢迎的功能。 我将展示在 .NET ASP Core 2.1 API 项目中。
背景
由于我们将把 mapper 对象注入到我们的控制器中,因此需要对 API 和依赖注入有一个概念。 最好对 LINQ 有一些基本的了解。
初始设置
首先,让我们创建一个新的 .NET ASP core
接下来,让我们为 Automapper 添加 NuGet 包。 在这里,我们将使用名为AutoMapper.Extensions.Microsoft.DependencyInjection
的依赖注入包,如下图所示
现在 AutoMapper 已经安装好了,我们必须配置startup.cs类,让它知道我们将要注入 automapper。
这是一个简单的单行代码,如下所示,在 ConfigureServices
方法内
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAutoMapper(); // Adding automapper
}
映射配置文件
我们必须将映射配置文件添加到我们的项目中,以告知 Automapper 正确的映射对象方式。
映射配置文件类总是扩展一个 Profile
类。 当程序第一次运行时,Automapper 会找到从 Profile
类继承的类,并加载映射配置。
Automapper 自动映射来自源和目标的同名属性。
让我们创建一个名为Mappings的新文件夹,并向其中添加一个新的映射类,并将其命名为SimpleMappings.cs。
namespace AutoMapper.Mappings
{
public class SimpleMappings : Profile
{
}
}
现在是时候添加 DTO 文件夹和 Classes 文件夹了,我们将用适当的类填充它们
//Department.cs
namespace AutoMapper.Classes
{
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public string Owner { get; set; }
public string SecretProperty { get; set; } // You dont want to display this
}
}
这是 DTO 类
//DepartmentDTO.cs
namespace AutoMapper.DTO
{
public class DepartmentDTO
{
public int Id { get; set; }
public string Name { get; set; }
public string Owner { get; set; }
}
}
完成这些后,让我们回到并修改我们的 MappingProfiles.cs
//MappingProfiles.cs
namespace AutoMapper.Mappings
{
public class MappingProfiles : Profile
{
public MappingProfiles()
{
CreateMap<Department, DepartmentDTO>().ReverseMap();
}
}
}
请注意,指定 ReverseMap()
允许我们以两种方式进行映射。
最后,是时候添加一个新的控制器了,让我们将其命名为 MappingController
//MappingController
namespace AutoMapper.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MappingController : Controller
{
private readonly IMapper _mapper;
private readonly Department sampleDepartment;
public MappingController(IMapper mapper)
{
_mapper = mapper; //injected automapper
//Initializing department object assume from a database
sampleDepartment = new Department()
{
Name = "department1",
Id = 1,
Owner = "ABC",
SecretProperty = "Very secret property"
};
}
[HttpGet]
public ActionResult<DepartmentDTO> Get()
{
return _mapper.Map<DepartmentDTO>(sampleDepartment);
}
}
}
这是从 postman 调用到 localhost:<port>/api/mapping 获得的结果
我们的秘密属性未显示,这意味着我们的 automapper 工作正常。
更深入
在上面的示例中,它是一个简单的单对单映射,但 automapper 也用于对象展平或从展平的对象创建复杂对象。
例如,让我们考虑一个 Person
和 personDTO
对象,如下所示,Person
对象具有一个 Address
属性,该属性是 Address
对象的一种类型。 在这里,我们将从复杂对象创建一个展平的对象。
//Person.cs//Person.cs
namespace AutoMapper.Classes
{
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
}
Address.cs 类
//Address.cs
namespace AutoMapper.Classes
{
public class Address
{
public string HouseNumber { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
}
PersonDTO.cs 将仅包含 Address
对象的 city
属性。
//PersonDTO.cs
namespace AutoMapper.DTO
{
public class PersonDTO
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string City { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
}
}
现在,我们必须回到映射 profile
类,并明确告诉 automapper 从 Address
的 city
属性映射 city
属性。 这可以通过 ForMember
来完成,如下面的更新的 MappingProfiles.cs 所示。
//MappingProfiles.cs
namespace AutoMapper.Mappings
{
public class MappingProfiles : Profile
{
public MappingProfiles()
{
CreateMap<Department, DepartmentDTO>().ReverseMap();
//Complex to Flattened
CreateMap<Person, PersonDTO>()
.ForMember(dest => dest.City,
opts => opts.MapFrom(
src => src.Address.City
)).ReverseMap();
}
}
}
这是完整的 MappingController
namespace AutoMapper.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MappingController : Controller
{
private readonly IMapper _mapper;
private readonly Department sampleDepartment;
private readonly Person samplePerson;
public MappingController(IMapper mapper)
{
_mapper = mapper; //injected automapper
//Initializing department object assume from a database
sampleDepartment = new Department()
{
Name = "department1",
Id = 1,
Owner = "ABC",
SecretProperty = "Very secret property"
};
//Initializing person object assume from a database
samplePerson = new Person()
{
Firstname = "John",
Lastname = "Doe",
Age = 25,
Sex = "Male",
Address = new Address()
{
City = "New York City",
HouseNumber = "10",
State = "NY",
ZipCode = "99999"
}
};
}
[HttpGet]
public ActionResult<DepartmentDTO> Get()
{
return _mapper.Map<DepartmentDTO>(sampleDepartment);
}
[HttpGet]
[Route("person")]
public ActionResult<PersonDTO> GetPerson()
{
return _mapper.Map<PersonDTO>(samplePerson);
}
}
}
最后,这是 postman 上的输出
最终的 DTO 对象显示了 city
。 我们的映射配置有效!