AutoMapper使用
需求:
在现代的软件开发中,项目的层级更加的细分,而不同层级之间对于对象的需求是有区别的,这就需要在不同层级间传递数据的时候,必须要转换数据。
每个层都做了它们职责范围内的事情:
持久层关注数据,所以只提供数据对象,它无需知道外层如何使用这些数据对象,也无法知道。
界面层关注数据的呈现,它只关注它要显示的数据。
那么问题是,谁来弥补它们之间的鸿沟?DTO(Data Transfer Object)——数据传输对象。
1、DTO更注重数据,对领域对象进行合理封装,从而不会将领域对象的行为过分暴露给表现层。
2、DTO是面向UI的需求而设计的,而领域模型是面向业务而设计的。因此DTO更适合于和表现层的交互,通过DTO我们实现了表现层与领域Model之间的解耦,因此改动领域Model不会影响UI层。
3、DTO说白了就是数据而已,不包含任何的业务逻辑,属于瘦身型的对象,使用时可以根据不同的UI需求进行灵活的运用。
解决方案:
而AutoMapper就是解决其中涉及到的数据对象转换的工具,一个将对象映射到对象的映射工具。对象映射的工作机制是:通过输入一个类型的对象然后将其转换成另一个不同类型的对象并输出。
在项目中多使用DTO实现表现层与领域Model的解耦,用AutoMapper来实现DTO与领域Model的相互转换。
参考资料:
git:https://github.com/AutoMapper/AutoMapper
http://www.qeefee.com/article/automapper
http://www.mamicode.com/info-detail-256271.html
http://www.3fwork.com/b303/000011MYM011315/
工具-库程序包管理器-程序包管理控制平台,输入“Install-Package AutoMapper”命令,就可以把AutoMapper添加到项目中;
1、简单使用demo:
Article article = new Article{
Title = “漫谈实体、对象、DTO及AutoMapper的使用”,
Content = “实体(Entity)、对象(Object)、DTO(Data Transfer Object)数据传输对象。”,
Author = “xishuai”,PostTime = DateTime.Now, Remark = “文章备注”};
//配置AutoMapper
AutoMapper.Mapper.Initialize(cfg =>{
cfg.CreateMap<Article, ArticleDTO>()//创建映射
.ForMember(dest => dest.ArticleID, opt => opt.MapFrom(src => src.Id))//指定映射规则
.ForMember(dest => dest.Summary, opt => opt.MapFrom(src => src.Content.Substring(0, 10)))//指定映射规则
.ForMember(dest => dest.PostYear, opt => opt.MapFrom(src => src.PostTime.Year))//指定映射规则
.ForMember(dest => dest.Remark, opt => opt.Ignore());//指定映射规则 忽视没有的属性
});
CreateMap<CodeRecordInput, CodeRecord>().ForMember(desc => desc.CreateTime, option => option.UseValue(DateTime.Now));
//调用映射
ArticleDTO form = AutoMapper.Mapper.Map<Article, ArticleDTO>(article);
2、使用Profile在Asp.net MVC项目中配置AutoMapper:
Profile是AutoMapper中用来分离类型映射定义的,这样可以让我们的定义AutoMapper类型匹配的代码可以更加分散,合理和易于管理。
利用Profile, 我们可以更加优雅的在MVC项目中使用我们的AutoMapper。
1. 在不同层中定义Profile,只定义本层中的类型映射
继承AutoMapping的Profile类,重写ProfileName属性和Configure()方法。
public class SettlementProfile : Profile
{
protected override void Configure()
{
// 财务单 DbModel / DbModel ,关联生成使用
CreateMap<FinanceReceipts, FinanceReceipts>()
// 不加 Ignore() 以保留来源单据 Id ,添加结算关系时用
//.ForMember(desc => desc.ReceiptId, option => option.Ignore())
.ForMember(desc => desc.FinanceReceiptDetail, option => option.Ignore())
.ForMember(desc => desc.FinanceBillLog, option => option.Ignore());
CreateMap<AutoCreateItem, FinanceReceipts>()
.ForMember(desc => desc.Remark, option => option.MapFrom(src => src.GetRemark()))
.ForMember(desc => desc.ShouldAmount, option => option.MapFrom(src => src.GetShouldCreateAmount()))
.ForMember(desc => desc.UnSettleAmount, option => option.MapFrom(src => src.GetShouldCreateAmount()))
.ForMember(desc => desc.ReaclAmount, option => option.MapFrom(src => 0M))
.ForMember(desc => desc.SettledAmount, option => option.MapFrom(src => 0M));
}
public override string ProfileName
{
get { return “SettlementProfile”;}
// return GetType().Name;
}
}
2. 创建MapperConfigure, 提供静态方法Configure,一次加载所有层中profile定义
public static void Configure(){
Mapper.Initialize(config =>{
config.AddProfile<SettlementProfile>();
config.AddProfile<SmsEmailProfile>();
Mapper.AssertConfigurationIsValid();
});
}
3. 在Global.cs文件Application_Start()方法中执行
// 配置 AutoMapper
MapperConfig.Configure();
转换:
RuleItem model = AutoMapper.Mapper.Map<AddRuleItemInput, RuleItem>(inputModel);