AutoMapper的基本使用请参考 :http://www.cnblogs.com/ljzforever/archive/2011/12/29/2305500.html
学习一下Nop是如何配置和集成AutoMapper的。
IStartupTask.cs
namespace Nop.Core.Infrastructure { public interface IStartupTask { void Execute(); int Order { get; } } }
之前的随便介绍了 ITypeFinder实现 , 项目启动时,ITypeFinder会找到项目中所有继承 IStartupTask 接口的实现。其中就有AutoMapperStartupTask
using AutoMapper; using Nop.Admin.Models.Blogs; using Nop.Admin.Models.Catalog; using Nop.Admin.Models.Cms; using Nop.Admin.Models.Common; using Nop.Admin.Models.Customers; using Nop.Admin.Models.Directory; using Nop.Admin.Models.Discounts; using Nop.Admin.Models.ExternalAuthentication; using Nop.Admin.Models.Forums; using Nop.Admin.Models.Localization; using Nop.Admin.Models.Logging; using Nop.Admin.Models.Messages; using Nop.Admin.Models.News; using Nop.Admin.Models.Orders; using Nop.Admin.Models.Payments; using Nop.Admin.Models.Plugins; using Nop.Admin.Models.Polls; using Nop.Admin.Models.Settings; using Nop.Admin.Models.Shipping; using Nop.Admin.Models.Tax; using Nop.Admin.Models.Topics; using Nop.Core.Domain.Blogs; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Common; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Directory; using Nop.Core.Domain.Discounts; using Nop.Core.Domain.Forums; using Nop.Core.Domain.Localization; using Nop.Core.Domain.Logging; using Nop.Core.Domain.Media; using Nop.Core.Domain.Messages; using Nop.Core.Domain.News; using Nop.Core.Domain.Orders; using Nop.Core.Domain.Polls; using Nop.Core.Domain.Shipping; using Nop.Core.Domain.Tax; using Nop.Core.Domain.Topics; using Nop.Core.Infrastructure; using Nop.Core.Plugins; using Nop.Services.Authentication.External; using Nop.Services.Cms; using Nop.Services.Messages; using Nop.Services.Payments; using Nop.Services.Shipping; using Nop.Services.Tax; namespace Nop.Admin.Infrastructure { public class AutoMapperStartupTask : IStartupTask { public void Execute() { //TODO remove 'CreatedOnUtc' ignore mappings because now presentation layer models have 'CreatedOn' property and core entities have 'CreatedOnUtc' property (distinct names) //address Mapper.CreateMap<Address, AddressModel>() .ForMember(dest => dest.AddressHtml, mo => mo.Ignore()) .ForMember(dest => dest.AvailableCountries, mo => mo.Ignore()) .ForMember(dest => dest.AvailableStates, mo => mo.Ignore()) .ForMember(dest => dest.FirstNameDisabled, mo => mo.Ignore()) .ForMember(dest => dest.LastNameDisabled, mo => mo.Ignore()) .ForMember(dest => dest.EmailDisabled, mo => mo.Ignore()) .ForMember(dest => dest.CompanyDisabled, mo => mo.Ignore()) .ForMember(dest => dest.CountryDisabled, mo => mo.Ignore()) .ForMember(dest => dest.StateProvinceDisabled, mo => mo.Ignore()) .ForMember(dest => dest.CityDisabled, mo => mo.Ignore()) .ForMember(dest => dest.Address1Disabled, mo => mo.Ignore()) .ForMember(dest => dest.Address2Disabled, mo => mo.Ignore()) .ForMember(dest => dest.ZipPostalCodeDisabled, mo => mo.Ignore()) .ForMember(dest => dest.PhoneNumberDisabled, mo => mo.Ignore()) .ForMember(dest => dest.FaxNumberDisabled, mo => mo.Ignore()); Mapper.CreateMap<AddressModel, Address>() .ForMember(dest => dest.CreatedOnUtc, mo => mo.Ignore()) .ForMember(dest => dest.Country, mo => mo.Ignore()) .ForMember(dest => dest.StateProvince, mo => mo.Ignore());
……
}
然后是单元测试,AutoMapperStartupTask 提交后进行集成测试,验证配置是否正确。
[TestFixture] public class AutoMapperConfigurationTest { [Test] public void Configuration_is_valid() { var autoMapperStartupTask = new AutoMapperStartupTask(); autoMapperStartupTask.Execute(); Mapper.AssertConfigurationIsValid(); } }
这里一个专门用于Mapper的扩展方法。
public static class MappingExtensions { #region Category public static CategoryModel ToModel(this Category entity) { return Mapper.Map<Category, CategoryModel>(entity); } public static Category ToEntity(this CategoryModel model) { return Mapper.Map<CategoryModel, Category>(model); } public static Category ToEntity(this CategoryModel model, Category destination) { return Mapper.Map(model, destination); } 。。。
最后是调用完成ViewModel,Entity的转换
var gridModel = new GridModel<CategoryModel> { Data = categories.Select(x => { var categoryModel = x.ToModel(); categoryModel.Breadcrumb = x.GetCategoryBreadCrumb(_categoryService); return categoryModel; }), Total = categories.TotalCount }; return new JsonResult { Data = gridModel };
总结: 光学会如何使用一个工具还不行,还要学习它如何能和自己的项目进行良好的集成。。使用不当的话反而影响插件和项目的扩展性,增加项目的复杂度。Nop的模块划分很清晰,方便了今后学习和改造。
参考:
http://www.cnblogs.com/ljzforever/archive/2011/12/29/2305500.html