详解c# AutoMapper 使用方式

 更新时间:2017年12月04日 11:35:31   作者:大稳·杨  
本篇文章主要介绍了详解c# AutoMapper 使用方式 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

安装方式:使用vs自带的nuget管理工具,搜索AutoMapper ,选择第一个安装到你的项目即可。

先说说DTO

DTO是个什么东东?

DTO(Data Transfer Object)就是数据传输对象,说白了就是一个对象,只不过里边全是数据而已。

为什么要用DTO?

1、DTO更注重数据,对领域对象进行合理封装,从而不会将领域对象的行为过分暴露给表现层

2、DTO是面向UI的需求而设计的,而领域模型是面向业务而设计的。因此DTO更适合于和表现层的交互,通过DTO我们实现了表现层与领域Model之间的解耦,因此改动领域Model不会影响UI层

3、DTO说白了就是数据而已,不包含任何的业务逻辑,属于瘦身型的对象,使用时可以根据不同的UI需求进行灵活的运用

我从网上找了一些资料,

AutoMapper

现在我们既然知道了使用DTO的好处,那么我们肯定也想马上使用它,但是这里会牵扯一个问题:怎样实现DTO和领域Model之间的转换?

有两个思路,我们要么自己写转换代码,要么使用工具。不过就应用而言,我还是觉得用工具比较简单快捷,那就使用工具吧。其实这样的转换工具很多,不过我还是决定使用AutoMapper,因为它足够轻量级,而且也非常流行,国外的大牛们都使用它。使用AutoMapper可以很方便的实现DTO和领域Model之间的转换,它是一个强大的Object-Object Mapping工具。

下载了个demo,然后自己又写了一遍,我把AutoMapper 的使用分为两种:

1、viewmodel与实体的字段名字是一致的,viewmodel的字段可以比实体中的字段少,但是不能多。

还有一种情况是:源实体中的字段名字是Getxxx,那么viewmodel中对应的字段可以是xxx,也会自动对应赋值,比如我写的demo中源实体中GetA,viewmodel中的A;

再有一种情况就是实体中的实体赋值,在我写的这个例子中,源实体中包含的实体类字段为Sub,里面包含的字段名字为Age,

那么destmodel中对应的字段名字可以是:SubAge,那么automapper就可以自动为你赋值了,大家看最后的运行结果。

给大家看下我建的源实体:

  public class Source1
  {
    public string Name { set; get; }

    public string GetA { set; get; }
    public string GetD { set; get; }


    public string SetB { set; get; }

    public string c { set; get; }

    public SubSource1 Sub { set; get; }
  }


  public class SubSource1
  {
    public string Age { set; get; }

  }

还有viewmodel(要转化成为你想要的模型):

  public class Dest1
  {
    public string Name { set; get; }

    public string A { set; get; }

    public string C { set; get; }

    public string SubAge { set; get; }

    public string D { set; get; }
  }

我封装的扩展方法:

    /// <summary>
    /// 类型映射,默认字段名字一一对应
    /// </summary>
    /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
    /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
    /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
    /// <returns>转化之后的实体</returns>
    public static TDestination MapTo<TDestination, TSource>(this TSource source) 
      where TDestination:class 
      where TSource :class 
    {
      if (source == null) return default(TDestination);
      var config = new MapperConfiguration(cfg => cfg.CreateMap<TDestination, TSource>());
      var mapper = config.CreateMapper();
      return mapper.Map<TDestination>(source);
    }

使用方式:

        var source1 = new Source1
        {
          Name = "source",
          Sub = new SubSource1 { Age = "25" },
          c = "c",
          GetA = "A",
          SetB = "B"
        };

        var destViewModel = source1.MapTo<Dest1, Source1>();

运行结果:

 

2.viewmodel与实体字段名字没有全部对应,只有几个字段的名字和源实体中的字段名字是一样的,其他的字段是通过实体中的几个字段组合或者是格式或者是类型转化而来的,

使用方法:不能再使用这个扩展方法了,只能自己额外写代码,代码如下:

        var config2 = new MapperConfiguration(
          cfg => cfg.CreateMap<SourceUser, DestUser2>()
            .ForMember(d => d.DestName, opt => opt.MapFrom(s => s.Name))  //指定字段一一对应
            .ForMember(d => d.Birthday, opt => opt.MapFrom(src => src.Birthday.ToString("yy-MM-dd HH:mm")))//指定字段,并转化指定的格式
            .ForMember(d => d.Age, opt => opt.Condition(src => src.Age > 5))//条件赋值
            .ForMember(d => d.A1, opt => opt.Ignore())//忽略该字段,不给该字段赋值
            .ForMember(d => d.A1, opt => opt.NullSubstitute("Default Value"))//如果源字段值为空,则赋值为 Default Value
            .ForMember(d => d.A1, opt => opt.MapFrom(src => src.Name + src.Age * 3 + src.Birthday.ToString("d"))));//可以自己随意组合赋值
        var mapper2 = config2.CreateMapper();

注释中都包含了平时常用的几种情况,其他的我就没有再写。

下面再给大家把list转化的扩展方法代码贴上:

    /// <summary>
    /// 集合列表类型映射,默认字段名字一一对应
    /// </summary>
    /// <typeparam name="TDestination">转化之后的model,可以理解为viewmodel</typeparam>
    /// <typeparam name="TSource">要被转化的实体,Entity</typeparam>
    /// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
    /// <returns>转化之后的实体列表</returns>
    public static IEnumerable<TDestination> MapToList<TDestination, TSource>(this IEnumerable<TSource> source)
      where TDestination : class
      where TSource : class
    {
      if (source == null) return new List<TDestination>();
      var config = new MapperConfiguration(cfg => cfg.CreateMap<TDestination, TSource>());
      var mapper = config.CreateMapper();
      return mapper.Map<List<TDestination>>(source);
    }

同样的使用方式:

        var source1 = new Source1
        {
          Name = "source",
          Sub = new SubSource1 { Age = "25" },
          c = "c",
          GetA = "A",
          SetB = "B"
        };
var source3 = new Source1
        {
          Name = "source3",
          Sub = new SubSource1 { Age = "253" },
          c = "c3",
          GetA = "A3",
          SetB = "B3"
        };
        var sourceList = new List<Source1> { source1, source3 };
        var destViewModelList = sourceList.MapToList<Dest1, Source1>();

运行结果:

 以上就是我个人所得,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 基于C#实现图片合成功能

    基于C#实现图片合成功能

    这篇文章主要为大家详细介绍了如何利用C#实现图片合成的功能,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • C#实现绘制鼠标的示例代码

    C#实现绘制鼠标的示例代码

    这篇文章主要为大家详细介绍了如何利用C#实现绘制鼠标的效果,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • C#使用SQL DataReader访问数据的优点和实例

    C#使用SQL DataReader访问数据的优点和实例

    今天小编就为大家分享一篇关于C#使用SQL DataReader访问数据的优点和实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • c# 模拟串口通信 SerialPort的实现示例

    c# 模拟串口通信 SerialPort的实现示例

    本文主要介绍了c# 模拟串口通信 SerialPort的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • C#调用RabbitMQ实现消息队列的示例代码

    C#调用RabbitMQ实现消息队列的示例代码

    这篇文章主要介绍了C#调用RabbitMQ实现消息队列的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • vista和win7在windows服务中交互桌面权限问题解决方法:穿透Session 0 隔离

    vista和win7在windows服务中交互桌面权限问题解决方法:穿透Session 0 隔离

    服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分。我们可以把服务想像成一种特殊的应用程序,它随系统的“开启~关闭”而“开始~停止”其工作内容,在这期间无需任何用户参与
    2016-04-04
  • C#实现Oracle批量写入数据的方法详解

    C#实现Oracle批量写入数据的方法详解

    往数据库批量写入数据,这个功能使用频率相对还是比较高的,特别是在做一些导入等功能的时候。本文为大家介绍了C#实现Oracle批量写入数据的方法,需要的可以参考一下
    2022-11-11
  • C#使用后台线程BackgroundWorker处理任务的总结

    C#使用后台线程BackgroundWorker处理任务的总结

    这篇文章主要介绍了C#使用后台线程BackgroundWorker处理任务的总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • c#系列 list详情

    c#系列 list详情

    这篇文章主要介绍了c#系列 list,list 本质是一个数组,。就跟我们操作系统一样,提前申请内存大小。所以我们程序一般都有一个申请内存,实际使用内存,内存碎片这几个概念,下面俩看文章详细内容吧
    2021-10-10
  • C#生成影像金字塔的原理实例

    C#生成影像金字塔的原理实例

    最近在处理一个关于影像金字塔的问题,这个金字塔程序是用C#写的,需要的朋友可以参考一下
    2013-05-05

最新评论