zoukankan      html  css  js  c++  java
  • AutoMapper使用

    AutoMapper使用手册(一)

    2015-02-14 18:00 by 蘑菇先生, 203 阅读, 0 评论, 收藏编辑

    阅读目录

      1. 介绍

      2. 基本使用

      3. 自动分割映射(Flattening)

      4. 自定义字段映射(Projection)

      5. 验证配置(Configuration validation)

    介绍

    AutoMapper是一个轻量级的类库,主要功能是把一个对象转换成另外一个对象,而避免我们每次都手工去转换。

    常见几种使用场景:

    • 对外服务接口,把逻辑层的实体转换成服务消费者需要的字段。

    • UI展现层,把业务对象转换成UI需要展现的字段。

    • 用户的输入输出,把DTO与领域模型互转。

    AutoMapper支持的平台:

    • .NET 4+
    • Silverlight 5
    • Windows Phone 8+
    • .NET for Windows Store apps (WinRT)
    • Windows Universal Apps
    • Xamarin.iOS
    • Xamarin.Android

    基本使用

    NuGet安装使用

    PM> install-package automapper

    注册2个类型之间的映射关系:

    Mapper.CreateMap<Order, OrderDto>();

    通过Map方法生成目标类型新对象,OrderDto是目标类型,order是源对象。

    OrderDto dto = Mapper.Map<OrderDto>(order);

    AutoMapper默认是根据属性名称自动与源进行规则匹配,赋值。
    例:FirstName=FirstName,FirstName=firstname,mapper不区分大小写。

    配置

    使用静态全局mapper注册的话,应该放在应用程序启动的时候。
    比如ASP.NET的Global.asax文件中Application_Start()方法。

    测试

    AutoMapper提供下面方法去验证我们的配置是否有效,无效会抛出异常:

    Mapper.AssertConfigurationIsValid();

    自动分割映射(Flattening)

    实际中我们经常需要把一个复杂对象映射一个简单对象,给UI使用,例:

    复制代码
    public class Order
    {
        public Customer Customer { get; set; }
        public decimal GetTotal()
        {
            return 10*10;
        }
    }
     public class Customer
        {
            public string Name { get; set; }
        }
    复制代码

    然后匹配Order对象到一个简单的OrderDto,仅包含我们需要的字段:

    public class OrderDto
    {
        public string CustomerName { get; set; }
        public decimal Total { get; set; }
    }

    当我们使用AutoMapper创建Order/OrderDto映射配置时,AutoMapper映射器会尝试在Order中,寻找名称匹配的成员,有3种匹配方式。

    • 名称相同的属性进行映射,不区分大小写。
    • 带Get前缀的方法进行映射,如例子中:
      映射器会把Order中的GetTotal分割成Get、Total 2个词, 把第二个Total与OrderDto中Order进行匹配映射。
    • 目标类型属性分割,如例子中: 映射器会把OrderDto中的CustomerName分割成Customer、Name。然后在Order中去Customer类属性中查找Name的属性。

    内部匹配根据帕斯卡拼写法(PascalCase)。

    自定义字段映射(Projection)

    自动分割映射能预判源对象到目标对象的匹配,但不能自定义配置映射。AutoMapper在构造目标对象时,会自动按照规则进行目标与源属性分割匹配。
    所以自动分割映射虽然方便智能,但却不是那么精确可控制的。 在很多场景下,我们更需要的是把A属性拆分映射B、C 2个属性上,或单独映射D属性上。
    AutoMapper提供一种自定义成员映射的方法。例如:

    public class CalendarEvent
    {
        public DateTime Date { get; set; }
        public string Title { get; set; }
    }

    我们想在web页面上输出更多的字段:

    复制代码
    public class CalendarEventForm
    {
        public DateTime EventDate { get; set; }
        public int EventHour { get; set; }
        public int EventMinute { get; set; }
        public string Title { get; set; }
    }
    复制代码

    因为目标类型的属性不存在源上,所以AutoMapper也无法完成精确匹配。 我们需要自定义成员映射规则到我们的类型映射配置上面。

    复制代码
    // 源对象
    var calendarEvent = new CalendarEvent
        {
            Date = new DateTime(2008, 12, 15, 20, 30, 0),
            Title = "假期公司聚会"
        };
    
    // 配置AutoMapper。   dest是目标表达式。opt是源表达式
    Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
        .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
        .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.Date.Hour))
        .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.Date.Minute));
    
    // 执行映射
    CalendarEventForm form = Mapper.Map<CalendarEvent, CalendarEventForm>(calendarEvent);
    
    form.EventDate.ShouldEqual(new DateTime(2008, 12, 15));
    form.EventHour.ShouldEqual(20);
    form.EventMinute.ShouldEqual(30);
    form.Title.ShouldEqual("假期公司聚会");
    复制代码

    ForMember方法允许我们指定2个action委托去配置每个成员的映射关系。 在上面的例子中,我们在源表达式使用了MapFrom方法去执行源值与目标成员的映射。这个MapFrom方法接受一个lambda表达式为参数,它在对象映射期间进行求值,即惰性求值。MapFrom参数可以是任意一个func的lambda表达式。

    验证配置(Configuration validation)

    平常我们手工进行对象映射,虽然很枯燥无味,但有利于我们测试转换。在这个源类型到目标类型转换基础测试上,其实我们仍然需要测试自己的应用。 AutoMapper也想到了这点,它减少的不仅仅是我们手工进行对象映射的事情,还能帮助我们节省手工写测试代码的时间。

    AutoMapper提供了AssertConfigurationIsValid方法去测试我们的配置项。 假设我们有个轻微的错误在源类型和目标类型上: 

    public class Source 
    {
    public int SomeValue { get; set; }
    }
    public class Destination
    {
        public int SomeValuefff { get; set; }
    }

    在Destination上,我们可能不小心输入错误,多了几个fff。也可能是我们的源属性重命名了。

    我们去测试配置项,创建映射配置并且执行AssertConfigurationIsValid方法。

    Mapper.CreateMap<Source, Destination>();
    Mapper.AssertConfigurationIsValid();

    在代码执行期间会抛出一个AutoMapperConfigurationException异常,描述消息为:

    复制代码
     Unmapped members were found. Review the types and members below.
     Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
      ==============================================================
    Source -> Destination (Destination member list)
    ConsoleApplication1.Source -> ConsoleApplication1.Destination (Destination member list)
    Unmapped properties:
    SomeValuefff
    复制代码

    AssertConfigurationIsValid执行验证期间,AutoMapper会检查每个目标类型的属性,逐一去匹配源中是否存在合适相等的类型。

    异常处理(Overriding configuration errors)

    除了我们去修改源和目标类型的名称外。 我们有3种选择去解决错误:

    • 自定义值解析器
    • 指定字段映射(Projection)
    • 使用忽略(Ignore())选项

    关于第三种选择,在目标类型我们有个成员,它有其他的含义(非字面意思或预留字段), 我们不想进行转换,我们可以配置如下:

     Mapper.CreateMap<Source, Destination>()
        .ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());

    官方文档:https://github.com/AutoMapper/AutoMapper 

    坐车回家过年了,祝大家新年愉快。

    作者:蘑菇先生 出处: http://mushroom.cnblogs.com/
  • 相关阅读:
    JS中原型对象中的constructor的作用?
    ES Module,commonjs和Typescript模块系统
    webpack中的hash、chunkhash和contenthash
    react-spring介绍(翻译)
    Typescript中的对象多可能类型推导的解决办法
    博客定制样式和脚本代码
    React和Vue对比
    CSS动画属性/重绘重排组合层/GPU加速 渲染优化相关及联系
    Object.create()探索
    await的错误处理问题,一个issue引发的ts社区的讨论
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4292419.html
Copyright © 2011-2022 走看看