物件對映
在工作中,需要將相似的物件對映到另一個物件,這樣我們來看一個最繁瑣的對映方式
例:
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);
}
}
透過 new 一個新的實體去賦值並儲存資料,User 實體在現實的應用程式中會有更多的屬性,這樣的手動建立它會變得乏味且容易出錯。當我們想要向 User 和 CreateUserInput 新增新屬性時,我們還必須更改對映程式碼。
上個例子繁瑣,我們做出改進
我們可以使用一個庫來自動處理我們的對映。 AutoMapper是物件到物件對映的最佳庫之一。ASP.NET Boilerplate 定義了一個IObjectMapper 介面來抽象它,然後使用Abp.AutoMapper 包中的 AutoMapper 實現這個介面。
注意:需要將Abp.AutoMapper NuGet 包安裝到您的專案中:
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);
}
}
IObjectMapper 是一個簡單的抽象,它具有將一個物件對映到另一個物件的 Map 方法。
Map 是一個簡單的方法,它獲取源物件並建立一個新的目標物件,其型別宣告為通用引數(本示例中的 User)。Map 方法具有將物件對映到現有物件的過載 。假設我們已經有一個 User 實體並且想要使用一個物件更新它的屬性:
public void UpdateUser(UpdateUserInput input)
{
var user = _userRepository.Get(input.Id);
_objectMapper.Map(input, user);
}
大多數時候,您可能只想直接(和傳統地)對映類。在這種情況下,您可以使用AutoMap、AutoMapFrom和AutoMapTo 屬性。例如,如果我們想將CreateUserInput類對映到上面示例中的User類,我們可以使用AutoMapTo屬性,如下所示:
[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; }
}
自定義對映
在某些情況下,簡單對映可能不適合。例如,兩個類的屬性名稱可能略有不同,或者您可能希望在對映過程中忽略某些屬性。在這種情況下,您應該直接使用 AutoMapper 的 API 來定義對映。Abp.AutoMapper 包定義了一個 API 來使自定義對映更加模組化。
假設我們想在對映時忽略密碼,並且使用者的電子郵件屬性名稱略有不同。我們可以定義對映如下所示:
[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));
});
}
}
可以使用另一種變種型別:
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
public override void PreInitialize()
{
}
public override void Initialize()
{
var thisAssembly = typeof(MyModule ).GetAssembly();
IocManager.RegisterAssemblyByConvention(thisAssembly);
Configuration.Modules.AbpAutoMapper().Configurators.Add(
cfg => cfg.AddProfile<CustomDtoMapperProfile>()
);
}
}
public class CustomDtoMapperProfile : Profile
{
public CustomDtoMapperProfile()
{
CreateMap<CreateUserInput, User>()
.ForMember(u => u.Password, options => options.Ignore())
.ForMember(u => u.Email, options => options.MapFrom(input => input.EmailAddress));
}
}