ABP document, Chinese Document of the abp framework
Document directory
Content of this section:
- Introduction
- IObjectMapper Interface
- Integration with AutoMapper
- Install
- Create ing
- Features of automatic ing
- Custom ing
- Extension Method MapTo
- Unit Test
- Predefined Mappings
- LocalizableString-> string
- Inject IMapper
Introduction
It is common to map an object to another similar object. Two Objects (classes) have similar or identical attributes and must be mapped to each other. In fact, this work is repetitive and boring, consider a typical application service method as follows:
public class UserAppService : ApplicationService{ private readonly IRepository<User> _userRepository; public UserAppService(IRepository<User> userRepository) { _userRepository = userRepository; } public void CreateUser(CreateUserInput input) { var user = new User { Name = input.Name, Surname = input.Surname, EmailAddress = input.EmailAddress, Password = input.Password }; _userRepository.Insert(user); }}
CreateUserInput is a simple data transmission object, and User is a simple object. We create a User entity manually based on the input. in practical applications, the User entity will have more attributes, manual creation will become boring and error-prone. When we add new attributes to User and CreateUserInput, we need to modify the ing code.
In fact, we can use a class library to automatically complete the ing. AutoMapper is the best ing Class Library for objects. The IObjectMapper interface is defined in the Abp to abstract it. this interface is implemented in the AutoMapper package.
IObjectMapper Interface
IObjectMapper is a simple abstraction that includes the method for ing an object to another object. We can use the following code to write an example:
public class UserAppService : ApplicationService{ private readonly IRepository<User> _userRepository; private readonly IObjectMapper _objectMapper; public UserAppService(IRepository<User> userRepository, IObjectMapper objectMapper) { _userRepository = userRepository; _objectMapper = objectMapper; } public void CreateUser(CreateUserInput input) { var user = _objectMapper.Map<User>(input); _userRepository.Insert(user); }}
Map is a simple method. It obtains the source object and creates a new target object (User in this example) based on the type specified by the generic parameter. Map has an overloaded version, it maps an object to an existing object. Suppose we already have a User object and want to update the attributes of this object based on another object:
public void UpdateUser(UpdateUserInput input){ var user = _userRepository.Get(input.Id); _objectMapper.Map(input, user);}
Integration with AutoMapper
Abp. AutoMapperThe nuget package (module) implements the IObjectMapper interface and provides additional functions.
Install
First, installAbp. AutoMapperPackage nuget to your project:
Install-Package Abp.AutoMapper
Then, addAbpAutoMapperModuleDependencies:
[DependsOn(typeof(AbpAutoMapperModule))]public class MyModule : AbpModule{ ...}
Next, you can safely inject and use IObjectMapper in your code. Of course, you can also use the AutoMapper API if necessary.
Create ing
AutoMapper requires that you first define the ing relationship between two classes before ing. You can refer to its documentation for more details, and can make it simpler and more modular by using Abp.
Features of automatic ing
In most cases, you only want to map classes directly (and according to Conventions). In this case, you can use the AutoMap, AutoMapFrom, and AutoMapTo features. For example, to map CreateUserInput in the above example to the User class, we can use the AutoMapTo feature as follows:
[AutoMapTo(typeof(User))]public class CreateUserInput{ public string Name { get; set; } public string Surname { get; set; } public string EmailAddress { get; set; } public string Password { get; set; }}
The AutoMap feature is bidirectional ing between two classes. In this example, we only need to map from CreateUserInput to User, so we only need to use AutoMapTo.
Custom ing
Simple ing may not apply to some scenarios. For example, the attribute names of the two classes are somewhat different or you may want to ignore some attributes during the ing process, in these cases, you can use the AutoMapper Api to customize the ing relationship. the AutoMapper package defines more modular APIs.
Suppose we want to ignore the Password and map EmailAddress to the User's Email, we can make the following definition:
[DependsOn(typeof(AbpAutoMapperModule))]public class MyModule : AbpModule{ public override void PreInitialize() { Configuration.Modules.AbpAutoMapper().Configurators.Add(config => { config.CreateMap<CreateUserInput, User>() .ForMember(u => u.Password, options => options.Ignore()) .ForMember(u => u.Email, options => options.MapFrom(input => input.EmailAddress)); }); }}
AutoMapper has more options and functions to map objects. For more information, see its documentation.
Extension Method MapTo
We recommend that you inject and use the previously mentioned IObjectMapper interface, because it enables our project to be decoupled from AutoMapper as much as possible and makes unit testing easier, because we can replace (simulate) ing in unit tests.
A MapTo extension method is also defined in the AutoMapper module. It can map an object to another object without IObjectMapper injection. For example:
public class UserAppService : ApplicationService{ private readonly IRepository<User> _userRepository; public UserAppService(IRepository<User> userRepository) { _userRepository = userRepository; } public void CreateUser(CreateUserInput input) { var user = input.MapTo<User>(); _userRepository.Insert(user); } public void UpdateUser(UpdateUserInput input) { var user = _userRepository.Get(input.Id); input.MapTo(user); }}
The MapTo extension method is defined in the ABC. AutoMapper namespace. Therefore, you must first introduce the namespace in your code.
Since the MapTo extension method is static, they use the static instance of AutoMapper (Mapper. instance). In this way, the application code is relatively simple and easy to use, but in unit testing, because static configuration and ing are shared between different tests, they affect each other, it may cause some problems.
Unit Test
We want to separate each unit test, so we need to define the following rules for our project:
1. Only IObjectMapper is used, and the extension method MapTo is not used.
2. configure Abp. the AutoMapper module uses a local Mapper instance (registered as a single instance for dependency injection) and does not use static (Abp. autoMapper uses static Mapper by default. instance to use the MapTo extension method as above ):
Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;
Predefined Mappings
LocalizableString-> string
Abp. the AutoMapper module defines a ing from a LocalizableString (or ILocalizableString) object to a string object. It uses ILoclaizationManager for conversion. Therefore, attributes that can be localized are automatically localized during the ing process.
Inject IMapper
If you need to inject the IMapper object of AutoMapper to replace IObjectMapper, you can directly inject IMapper into your class and use it. the AutoMapper package registers IMapper as a singleton to the dependency injection system.