先说说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工具。

摘自让AutoMapper在你的项目里飞一会儿

AutoMapper6.2.2.0

AutoMapper6.2.2.0与之前的版本有些不同,那么究竟有什么不同,我们一起来实践一下:

1.首先,使用AutoMapper6.2.2.0需要在你的项目中引用NuGet包,右键依赖项,管理NuGet程序包,然后选择浏览,搜索AutoMapper,安装,你就可以在项目中使用啦,你也可以在vs中使用打开工具-库程序包管理器-程序包管理控制平台,输入“Install-Package AutoMapper”命令,就可以把AutoMapper添加到项目中了~

2.让我们开始使用

  (1)一个简单的映射

      首先,创建一个C#控制台应用程序,为了方便,我们在Program直接定义三个类:

      

public class Student
{
public string Name { get; set; }
public int Sex { get; set; }
public string Age { get; set; }
public DateTime Birth { get; set; }
} public class Dto_Student
{
public string n { get; set; }
public string s { get; set; }
public int a { get; set; }
public string b { get; set; }
} public class V_Student
{
public string Name { get; set; }
public int Sex { get; set; }
public string Age { get; set; }
public DateTime Birth { get; set; }
}

  (2)一个简单的映射,由于Student和V_Student类字段名称一样,类型相同,所以,映射可以这么写

  

//一个简单的映射
AutoMapper.Mapper.Initialize(map => map.CreateMap<Student, V_Student>());
var stu = AutoMapper.Mapper.Map<Student>(new V_Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
}); var vstu = AutoMapper.Mapper.Map<V_Student>(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
});

  (3)那么,不同字段名称,甚至不同类型的两个类如何映射呢,那就要手动的映射相应字段了:

//属性不同名,属性类型不同映射
AutoMapper.Mapper.Initialize(map => map.CreateMap<Student, Dto_Student>()
.ForMember(d => d.n, opt =>
{
opt.MapFrom(s => s.Name);
})
.ForMember(d => d.s, opt =>
{
opt.MapFrom(s => s.Sex == 1 ? "男" : "女");
})
.ForMember(d => d.a, opt =>
{
opt.MapFrom(s => Convert.ToInt32(s.Age));
})
.ForMember(d => d.b, opt =>
{
opt.MapFrom(s => s.Birth.ToString("yyyy-MM-dd"));
})
); var dto_stu = AutoMapper.Mapper.Map<Dto_Student>(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
}); var stu = AutoMapper.Mapper.Map<Student>(new Dto_Student
{
n = "myname",
s = "男",
a = 24,
b = DateTime.Now.ToString("yyyy-MM-dd")
});

  这边一运行,发现报错了,为什么呢,原来是因为,由于映射字段类型不同,无法反向映射,那么,如何再添加一个映射呢,这时候就需要用到Profile这个类,我们需要继承这个类,并在里面写下映射配置,具体如下:

新建Dto_StudentProfile类和StudentProfile类:

public class Dto_StudentProfile:Profile
{
public Dto_StudentProfile()
{
base.CreateMap<Dto_Student, Student>()
.ForMember(s => s.Name, opt =>
{
opt.MapFrom(stu => stu.n);
})
.ForMember(s => s.Sex, opt =>
{
opt.MapFrom(stu => stu.s.Equals("男")?1:0);
})
.ForMember(s => s.Age, opt =>
{
opt.MapFrom(stu => stu.a.ToString());
})
.ForMember(s => s.Birth, opt =>
{
opt.MapFrom(stu =>DateTime.Parse( stu.b+" 00:00:00"));
});
}
} public class StudentProfile:Profile
{
public StudentProfile()
{
base.CreateMap<Student, Dto_Student>()
.ForMember(d => d.n, opt =>
{
opt.MapFrom(stu => stu.Name);
})
.ForMember(d => d.s, opt =>
{
opt.MapFrom(stu => stu.Sex == 1 ? "男" : "女");
})
.ForMember(d => d.a, opt =>
{
opt.MapFrom(stu => Convert.ToInt32(stu.Age));
})
.ForMember(d => d.b, opt =>
{
opt.MapFrom(stu => stu.Birth.ToString("yyyy-MM-dd"));
});
}
}

  那么,我们如何使用两个配置呢?

//配置映射
AutoMapper.Mapper.Initialize(map => map.AddProfiles(new[] {
typeof(Dto_StudentProfile),
typeof(StudentProfile)
}));
var dto_stu = AutoMapper.Mapper.Map<Dto_Student>(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
}); var stu = AutoMapper.Mapper.Map<Student>(new Dto_Student
{
n = "myname",
s = "男",
a = 24,
b = DateTime.Now.ToString("yyyy-MM-dd")
});

  这样,我们就完成了两个不同字段名称,不同类型的映射

(4)映射List<T>

  如何进行实体列表的映射呢,其实,配置上并没有任何不同,只需要在使用上,换成list就可以了:

List<Student> estu = new List<Student>();
estu.Add(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
});
estu.Add(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
});
List<Dto_Student> slist = AutoMapper.Mapper.Map<List<Student>, List<Dto_Student>>(estu);

  (5)你可能觉得不太方便,那么,我们可以将AutoMapper的Initialize放到应用开始的时候运行

  Mvc项目,可以放到程序的Global中,如果是.NET Core 2.0的MVC项目,可以放到StartUp中运行:

这边直接摘了前人的方法,有兴趣可以看一下https://www.cnblogs.com/lvlinlv/p/7344916.html

  (6)那么,你可以使用拓展的方法进行映射,这里定义一个AutoMapperHelper操作类:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text; namespace AutoMapperTest
{
public static class AutoMapperHelper
{
public static T MapTo<T>(this object obj)
{
if (obj == null) return default(T);
return AutoMapper.Mapper.Map<T>(obj);
} public static List<TDestination> MapToList<TDestination>(this object source)
{
return AutoMapper.Mapper.Map<List<TDestination>>(source);
}
}
}

  这样,你就可以这么使用:

List<Student> estu = new List<Student>();
estu.Add(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
});
estu.Add(new Student
{
Name = "myname",
Sex = 1,
Age = "24",
Birth = DateTime.Now
});
var slist = estu.MapToList<Dto_Student>();

  非list的实体映射也是一样的,这里不再多说,如果有什么疑问,欢迎提出来,共同讨论进步,感谢你的阅读

C#使用AutoMapper6.2.2.0进行对象映射的更多相关文章

  1. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十三 || DTOs 对象映射使用,项目部署Windows+Linux完整版

    更新 很多小伙伴在用 IIS 发布的时候,总是会有一些问题,文章下边 #autoid-6-0-0 我也简单的动图展示了,如何 publish 到 IIS 的过程,如果你能看懂,却发现自己的项目有问题的 ...

  2. php设计模式 数据对象映射模式

    数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作. 在代码中实现数据对象映射模式,实现一个ORM类,将复杂的sql语句映射成对象属性的操作.对象关系映射(Obje ...

  3. ASP.NET MVC 模型和数据对象映射实践

    在使用 MVC 开发项目的过程中遇到了个问题,就是模型和数据实体之间的如何快捷的转换?是不是可以像 Entity Framework 的那样 EntityTypeConfiguration,或者只需要 ...

  4. PHP 设计模式 笔记与总结(9)数据对象映射模式

    [数据对象映射模式] 是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作.例如在代码中 new 一个对象,使用数据对象映射模式就可以将对象的一些操作比如设置一些属性,就会自动保存到数 ...

  5. 关于iOS上的对象映射公用方法-备

    具体的使用方法,请见下面说明,或者见工程里的单元测试代码.或者,参考原始文档: https://github.com/mystcolor/JTObjectMapping 使用方法 ======== 绝 ...

  6. MyBitis(iBitis)系列随笔之二:类型别名(typeAliases)与表-对象映射(ORM)

    类型别名(typeAliases):     作用:通过一个简单的别名来表示一个冗长的类型,这样可以降低复杂度.    类型别名标签typeAliases中可以包含多个typeAlias,如下 < ...

  7. rest-assured的对象映射(序列化和反序列化)

    rest-assured支持映射Java对象到Json和XML以及从Json和XML中映射到Java对象.Json映射需要在classpath 中有Jackson.Jackson 2或者是Gson,X ...

  8. 基于JsonPath和XmlPath的对象映射(Object Mapping)

    rest-assured支持映射Java对象到Json和XML以及从Json和XML中映射到Java对象.Json映射需要在classpath 中有Jackson.Jackson 2或者是Gson,X ...

  9. 一篇搞定SQLAlchemy--关系对象映射

    要使用SQLAlchemy,必须先下载这个模块 pip3 install sqlalchemy 或 pycharm File--> Settings-->project...-->P ...

随机推荐

  1. apache tomcat 安装

    1.安装jdk (java development kit) jdk下载 http://download.oracle.com/otn-pub/java/jdk tar -zxvf jdk-8u121 ...

  2. scrapy---callback 传递自定义参数

    在scrapy提交一个链接请求是用 Request(url,callback=func) 这种形式的,而parse只有一个response参数,如果自定义一个有多参数的parse可以考虑用下面的方法实 ...

  3. [LTR] 信息检索评价指标(RP/MAP/DCG/NDCG/RR/ERR)

    一.RP R(recall)表示召回率.查全率,指查询返回结果中相关文档占所有相关文档的比例:P(precision)表示准确率.精度,指查询返回结果中相关文档占所有查询结果文档的比例: 则 PR 曲 ...

  4. 删除日志释放空间最好不要用rm

    目前在维护一些服务器有一个根目录空间经常告警no space left ,切到/var/log 目录下du -sh * 的时候,发现有一个authlog占了12G,然后立马执行了rm authlog: ...

  5. JAVA入门——Generic/泛型

    在台科大的第二次JAVA作业,老师课上讲的内容是泛型. 泛型(generic),泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以 ...

  6. 课堂作业 泛型类-Bag

    自定义泛型类Bag 一.具体代码: 代码连接 二.伪代码: 1.思路: 老师讲完后我的想法是要做出一个类似于List的Bag,首先它的本身是又数组构成的并且是可自动增加长度的,然后实现一些基本的操作, ...

  7. Beta敏捷冲刺每日报告——Day4

    1.情况简述 Beta阶段Scrum Meeting 敏捷开发起止时间 2017.11.5 00:00 -- 2017.116 00:00 讨论时间地点 2017.11.5 晚9:30,电话会议会议 ...

  8. C语言——总结回顾

    1.当初你是如何做出选择计算机专业的决定的?经过一个学期,你的看法改变了么,为什么? 你觉得计算机是你喜欢的领域吗,它是你擅长的领域吗? 为什么? 答:①当初选择计算机专业是出于一种选择,是一种带着冲 ...

  9. networkx 学习

    import networkx as nx import pylab import numpy as np #自定义网络 row=np.array([,,,,,,]) col=np.array([,, ...

  10. python第三方库requests详解

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...