AutoMapper在MVC中的运用01

MVC中,如果想在Domain Model和View Model之间建立映射,用AutoMapper是一个不错的选择。不仅如此,AutoMapper能在不同对象之间建立映射,比如string与int类型, DateTime与int类型,接口与实现类,等等。本篇主要总结AutoMapper在MVC中的配置、使用、单元测试,以及各种映射场景。


注意:

如果通过NuGet下载最新版的AutoMapper,需要注意的是:有些方法,比如ForMember方法,和以前不一样。还有一些方法已经过期。


  配置


□ 全局配置

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ...
        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
        CreateMaps();
    }

    public void CreateMaps()
    {
        AutoMapper.Mapper.Reset();
        AutoMapper.Mapper.CreateMap<CustomerCreateEditViewModel, Customer>();
        AutoMapper.Mapper.AssertConfigurationIsValid();
    }
}


这种方法不太利于单元测试。


□ 全局配置 + 静态类配置


AutoMapper静态配置类:

    public static class AutoMapperWebConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(cfg =>
            {
                cfg.AddProfile(new UserProfile());
            });
        }
    }


UserProfile继承于AutoMapper的Profile类。通过这种继承,我们可以创建不同的映射规则。比如一套规则用于Domain Model转换成View Model,一套规则用于View Model转换成Domain Model。

    public class UserProfile : Profile
    {
        protected override void Configure()
        {
            AddFormatter<MoneyFormatter>();           
            Mapper.CreateMap<Order, OrderListViewModel>();
        }
    }

最后在全局注册。


AutoMapperWebConfiguration.Configure();


  单元测试


当项目中有比较多的model的时候,通过单元测试,可以发现映射中存在的问题,而不是等到程序运行的时候。

    [TestClass]
    public class AutoMapperConfigurationTester
    {
        [TestMethod]
        public void TestMethod1()
        {
            AutoMapperWebConfiguration.Configure();
            Mapper.AssertConfigurationIsValid();
        }
    }


  简单例子


□ Domain Models

public class Customer
{
	public string FirstName{get;set;}
	public string LastName{get;set;}
	public string Email{get;set;}
	pubic Address HomeAddress{get;set;}
	public string GetFullName()
	{
		return string.Format("{0}{1}", FirstName, LastName);
	}
}

public class Address
{
	public string Address1{get;set;}
	public string Address2{get;set;}
	public string City{get;set;}
	public string PostalCode{get;set;}
	public string Country{get;set;}
}

□ View Model

public class CustomerListViewModel
{
	public string FullName{get;set;}
	public string Email{get;set;}
	public string HomeAddressCountry{get;set;}
}

□ Controller

public class CustomersController : Controller
{
	private readonly ICustomerService m_CustomerService;
	public CustomersController(ICustomerService customerService)
	{
		m_CustomerService = customerService;
	}

	public ActionResult Index()
	{
		IList<Customer> customers = m_CustomerService.GetCustomers();
		//为了演示方便,映射规则没有写在统一的静态类中
		Mapper.CreateMap<Customer, CustomerListViewModel>();
		IList<CustomerListViewModel> viewModelList = Mapper.Map<IList<Customer>, IList<CustomerListViewModel>>(customers);
		return View(viewModelList);
	}
}

□ 要点


AutoMapper的"神奇"是建立在惯例和配置之上的。

○ 目标和源的属性名要尽可能保持一致。

○ 当源的属性是复杂类型时,目标属性如果遵循"源属性+源属性所对应类中的某个字段"的惯例,就像这里的HomeAddressCountry,就能拿到源中复杂类型属性所对应类中的字段。

○ 源中的"Get+其它"形成的方法,在目标中只要把"其它"作为属性名,就可以拿到源中方法的返回值,就像源中的GetFullName()方法,对应目标中的FullName属性。

○ 创建映射永远是类与类间的映射,而通过源获取目标,这里的源可以是单个类,也可以是集合,就像 Mapper.Map<IList<Customer>, IList<CustomerListViewModel>>(customers)。


□ 出处


以上参考了这篇博文:http://bengtbe.com/blog/2009/04/14/using-automapper-to-map-view-models-in-asp-net-mvc/



  把Domain Model与View Model的映射放到系统属性里实现


有时,为了代码更大程度的简洁,我们可以把系统属性里,以Aspect Oriented Programming(AOP),面向切面编程的思想来实现。

通过ActionFilterAttribute过滤系统属性可以控制发生在Action方法之前和之后的事件。

如果Domain Model转换成View Model,那我们就让自定义事件发生在Action方法之后。

如果View Model转换成Domain Model,那我们就让自定义事件发生在Action方法之前。


□ Domain Model转换成View Model

    public class DomainToViewAttribute : ActionFilterAttribute
    {
        private readonly Type _destType;
        private readonly Type _sourceType;

        public DomainToViewAttribute(Type sourceType, Type desType)
        {
            _sourceType = sourceType;
            _destType = desType;
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            var domainModel = filterContext.Controller.ViewData.Model;
            var viewModel = Mapper.Map(domainModel, _sourceType, _destType);
            filterContext.Controller.ViewData.Model = viewModel;
        }
    }

□ View Model转换成Domain Model

    public class ViewToDomainAttribute : ActionFilterAttribute
    {
        private readonly Type _desType;
        private readonly Type _sourseType;

        public ViewToDomainAttribute(Type sourceType, Type desType)
        {
            _sourseType = sourceType;
            _desType = desType;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var viewModel = filterContext.Controller.ViewData.Model;
            var domainModel = Mapper.Map(viewModel, _sourseType, _desType);
            filterContext.Controller.ViewData.Model = domainModel;
        }
    }

□ 把自定义系统属性打到Action方法之上


    [DomainToView(typeof(IEnumerable<Customer>), typeof(IEnumerable<CustomerInfo>))]

    public ViewResult Index()    



接下来的几篇将介绍AutoMapper的各种使用场景。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AutoMapper是一个用于对象映射的开源库。它可以帮助简化对象之间的转换过程,减少手动编写重复的代码。通过配置映射规则,AutoMapper可以自动将一个对象的属性值复制到另一个对象对应的属性上,而不需要手动逐个属性进行赋值。 使用AutoMapper,你可以定义映射规则,包括源类型和目标类型以及它们之间的属性映射关系。一旦配置好映射规则,你可以使用简单的API将源对象映射到目标对象上。 以下是一个使用AutoMapper的示例: ```csharp // 定义源类型和目标类型 public class SourceObject { public string Name { get; set; } public int Age { get; set; } } public class DestinationObject { public string Name { get; set; } public int Age { get; set; } } // 配置映射规则 var config = new MapperConfiguration(cfg => { cfg.CreateMap<SourceObject, DestinationObject>(); }); // 创建映射器 var mapper = config.CreateMapper(); // 创建源对象 var source = new SourceObject { Name = "John", Age = 30 }; // 使用映射器进行对象映射 var destination = mapper.Map<SourceObject, DestinationObject>(source); // 输出目标对象属性值 Console.WriteLine(destination.Name); // 输出:John Console.WriteLine(destination.Age); // 输出:30 ``` 通过使用AutoMapper,你可以简化对象之间的映射过程,提高开发效率。它支持各种复杂的映射场景,并且可以通过自定义转换器来处理更复杂的映射逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值