详解c# AutoMapper 使用方式

所属分类: 软件编程 / C#教程 阅读数: 192
收藏 0 赞 0 分享

安装方式:使用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#开发word批量转pdf源码分享

已经安装有Office环境,借助一些简单的代码即可实现批量Word转PDF,看下面的实例源码吧
收藏 0 赞 0 分享

c# xml API操作的小例子

这篇文章主要介绍了c# xml API操作的小例子,有需要的朋友可以参考一下
收藏 0 赞 0 分享

c#唯一值渲染实例代码

这篇文章主要介绍了c#唯一值渲染实例代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

淘宝IP地址库采集器c#代码

这篇文章主要介绍了淘宝IP地址库采集器c#代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C#在后台运行操作(BackgroundWorker用法)示例分享

BackgroundWorker类允许在单独的专用线程上运行操作。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题,下面看示例
收藏 0 赞 0 分享

c#文本加密程序代码示例

这是一个加密软件,但只限于文本加密,加了窗口控件的滑动效果,详细看下面的代码
收藏 0 赞 0 分享

c#生成站点地图(SiteMapPath)文件示例程序

这篇文章主要介绍了c#生成站点地图(SiteMapPath)文件的示例,大家参考使用
收藏 0 赞 0 分享

C# 键盘Enter键取代Tab键实现代码

这篇文章主要介绍了C# 键盘Enter键取代Tab键实现代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C# WinForm导出Excel方法介绍

在.NET应用中,导出Excel是很常见的需求,导出Excel报表大致有以下三种方式:Office PIA,文件流和NPOI开源库,本文只介绍前两种方式
收藏 0 赞 0 分享

C#串口通信程序实例详解

在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports,创建C#串口通信程序的具体实现是如何的呢?让我们开始吧
收藏 0 赞 0 分享
查看更多