集成和配置AutoMapper

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

原文地址:https://www.cnblogs.com/miku/p/2706380.html