实现简单DTO适配器,解放你的双手
2011-05-10 22:26
399 查看
多数人不喜欢用DTO的一个重要原因是嫌麻烦,需要写一堆DTO类不说,还要做DTO到DomainObject,DomainObject到DTO的转换映射,就是这个映射部分,让我感到很不爽,所以写了一个较通用的适配器来完成这部分的Mapping工作。这里有几点觉得有必要提一下:
首先,关于DTO,伟大的“码总”说,DTO应该是扁平的,不应该包含过于复杂的对象。所以我就不考虑DTO里面的过于复杂的子对象,当然DTO只是个数据载体,也不应该有错宗复杂的对象关系了。
其次,关于DomainObject,DomainObject是充血的,对象关系是复杂的。其中包含聚合根等各种复杂关系概念。DomainObject的对象关系,复杂对象的填充应该由业务来做,而不是通过适配器来填充了。
最后,关于上面两点问题弄清楚了,事情就好办多了。D-D之间的关系我们总结一下,大至分为:一对一、一对多、多对一、多对多这么四个对象映射关系。也就是说可能一个DTO对象对应一个DomainObject对象,多个DTO对象对应一个DomainObject对象,一个DTO对象对应多个DomainObject对象,多个DTO对象对应多个DomainObject对象等。这里的映射关系我通过在DTO上标记自定义特性来实现。考虑过通过XML配置,但是想想这种场景一般都是DTO做为匹配对象,去找Do,所以我们只需要标记DTO对象就可以了。必竟DTO是为DO工作的。好接下来我们就说实现,这只是一个晚上实现的初步版本,只是实现了基本的功能。
先上个项目结构图,然后再做分解。项目没什么,因为只是一个功能嘛。Assionsoft.Dtod就是实际的适配器项目,而Assionsoft.Dtod.UnitTest是单元测试。
/// <summary>
/// Member DTO对象
/// </summary>
public class MemberDto
{
public MemberDto()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
[DtoMemberMap("Member.SysNo")]
public Guid SysNo { get; set; }
/// <summary>
/// 成员名
/// </summary>
[DtoMemberMap("Member.MemberName")]
public string MemberName { get; set; }
/// <summary>
/// 成员描述
/// </summary>
[DtoMemberMap("MemberDesc.MemberDescs")]
public string MemberDesc { get; set; }
}
这个是DTO对象,看字属性上标记了DtoMemberMap代表它要映射到DO上的哪个字段,而 Member.MemberName就是指定哪个类的哪个字段。下面是相应的DO类
/// <summary>
/// 成员领域对象
/// </summary>
public class Member
{
public Member()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
public Guid SysNo { get; set; }
/// <summary>
/// 成员名
/// </summary>
public string MemberName { get; set; }
/// <summary>
/// 成员描述
/// </summary>
public MemberDesc MemberDesc { get; set; }
/// <summary>
/// 领域逻辑
/// </summary>
/// <returns></returns>
public bool IsOk()
{
if (MemberName.Length <= 0)
return false;
else
return true;
}
}
/// <summary>
/// 成员描述领域对象
/// </summary>
public class MemberDesc
{
public MemberDesc()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
public Guid SysNo { get; set; }
/// <summary>
/// 成员描述
/// </summary>
public string MemberDescs { get; set; }
}
我们看到这里是一个DTO对应两个DO对象的关系,我们做一下一对多的适配例子
/// <summary>
/// 一对多
/// </summary>
[TestMethod()]
public void DoAdapterOneToAll()
{
//创建一个DTO对象
MemberDto memberDto = new MemberDto();
memberDto.MemberName = "张三";
memberDto.MemberDesc = "张三是好淫啊!!!";
//创建多个领域对象
Member member = new Member();
MemberDesc memberDesc = new MemberDesc();
//实例化DO适配器,并初始化DTO对象
IAdapter adapter = new DoAdapter(memberDto);
//填充领域对象
adapter.Fill(new object[]{member,memberDesc});
Assert.AreEqual(member.MemberName+memberDesc.MemberDescs, memberDto.MemberName+memberDto.MemberDesc);
}
先实例一个DTO对象并用来测试用,然后创建两个DO对象。当然,我们是空对象。这时我们实例化DO适配器。因为这里是DTO到DO的转换。我们要填充的是DO,所以实例化DO适配器。通过接口IAdapter实例化DoAdapter对象,关传入memberDto初始对象,接下来调用Fill方法,对两个DO对象member,memberDesc进行适配,最后我们做了个单元测试。对比DTO和DO对象的值。发现已经完成了DTO到DO的转换,其他的关系与此类似,我就不浪费篇幅了。
先前是用泛型做的,但是发现泛型有限制,不能做多关系。所以后来改成object了。
首先,关于DTO,伟大的“码总”说,DTO应该是扁平的,不应该包含过于复杂的对象。所以我就不考虑DTO里面的过于复杂的子对象,当然DTO只是个数据载体,也不应该有错宗复杂的对象关系了。
其次,关于DomainObject,DomainObject是充血的,对象关系是复杂的。其中包含聚合根等各种复杂关系概念。DomainObject的对象关系,复杂对象的填充应该由业务来做,而不是通过适配器来填充了。
最后,关于上面两点问题弄清楚了,事情就好办多了。D-D之间的关系我们总结一下,大至分为:一对一、一对多、多对一、多对多这么四个对象映射关系。也就是说可能一个DTO对象对应一个DomainObject对象,多个DTO对象对应一个DomainObject对象,一个DTO对象对应多个DomainObject对象,多个DTO对象对应多个DomainObject对象等。这里的映射关系我通过在DTO上标记自定义特性来实现。考虑过通过XML配置,但是想想这种场景一般都是DTO做为匹配对象,去找Do,所以我们只需要标记DTO对象就可以了。必竟DTO是为DO工作的。好接下来我们就说实现,这只是一个晚上实现的初步版本,只是实现了基本的功能。
先上个项目结构图,然后再做分解。项目没什么,因为只是一个功能嘛。Assionsoft.Dtod就是实际的适配器项目,而Assionsoft.Dtod.UnitTest是单元测试。
/// <summary>
/// Member DTO对象
/// </summary>
public class MemberDto
{
public MemberDto()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
[DtoMemberMap("Member.SysNo")]
public Guid SysNo { get; set; }
/// <summary>
/// 成员名
/// </summary>
[DtoMemberMap("Member.MemberName")]
public string MemberName { get; set; }
/// <summary>
/// 成员描述
/// </summary>
[DtoMemberMap("MemberDesc.MemberDescs")]
public string MemberDesc { get; set; }
}
这个是DTO对象,看字属性上标记了DtoMemberMap代表它要映射到DO上的哪个字段,而 Member.MemberName就是指定哪个类的哪个字段。下面是相应的DO类
/// <summary>
/// 成员领域对象
/// </summary>
public class Member
{
public Member()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
public Guid SysNo { get; set; }
/// <summary>
/// 成员名
/// </summary>
public string MemberName { get; set; }
/// <summary>
/// 成员描述
/// </summary>
public MemberDesc MemberDesc { get; set; }
/// <summary>
/// 领域逻辑
/// </summary>
/// <returns></returns>
public bool IsOk()
{
if (MemberName.Length <= 0)
return false;
else
return true;
}
}
/// <summary>
/// 成员描述领域对象
/// </summary>
public class MemberDesc
{
public MemberDesc()
{
SysNo = Guid.NewGuid();
}
/// <summary>
/// 标识
/// </summary>
public Guid SysNo { get; set; }
/// <summary>
/// 成员描述
/// </summary>
public string MemberDescs { get; set; }
}
我们看到这里是一个DTO对应两个DO对象的关系,我们做一下一对多的适配例子
/// <summary>
/// 一对多
/// </summary>
[TestMethod()]
public void DoAdapterOneToAll()
{
//创建一个DTO对象
MemberDto memberDto = new MemberDto();
memberDto.MemberName = "张三";
memberDto.MemberDesc = "张三是好淫啊!!!";
//创建多个领域对象
Member member = new Member();
MemberDesc memberDesc = new MemberDesc();
//实例化DO适配器,并初始化DTO对象
IAdapter adapter = new DoAdapter(memberDto);
//填充领域对象
adapter.Fill(new object[]{member,memberDesc});
Assert.AreEqual(member.MemberName+memberDesc.MemberDescs, memberDto.MemberName+memberDto.MemberDesc);
}
先实例一个DTO对象并用来测试用,然后创建两个DO对象。当然,我们是空对象。这时我们实例化DO适配器。因为这里是DTO到DO的转换。我们要填充的是DO,所以实例化DO适配器。通过接口IAdapter实例化DoAdapter对象,关传入memberDto初始对象,接下来调用Fill方法,对两个DO对象member,memberDesc进行适配,最后我们做了个单元测试。对比DTO和DO对象的值。发现已经完成了DTO到DO的转换,其他的关系与此类似,我就不浪费篇幅了。
先前是用泛型做的,但是发现泛型有限制,不能做多关系。所以后来改成object了。
相关文章推荐
- 实现简单DTO适配器,解放你的双手
- (4.5.5.8)Android Studio 2.2 Espresso Test Recorder-----解放双手,通过录制交互过程实现测试
- 深入剖析Spring Web源码(十三) - 处理器映射,处理器适配器以及处理器的实现 - 处理器的实现架构 - 简单控制器
- 适配器设计模式简单实现
- 最简单的android studio2.3安装 ButterKnife 8.5.1版本方法,解放双手
- Android实现一个简单的自定义适配器
- 还在手动玩游戏?你out了,现在都用python实现全自动解放双手!
- Android Studio 2.2 Espresso Test Recorder-----解放双手,通过录制交互过程实现测试
- STL之简单空间适配器实现
- 深入剖析Spring Web源码(八) - 处理器映射,处理器适配器以及处理器的实现 - 基于简单控制器流程的实现
- Ogre+ UIKit GUI 摇杆功能的简单实现
- 用php简单实现加减乘除计算器
- 简单实现异步编程promise模式
- JS实现简单的选择题测评系统代码思路详解(demo)
- IF-IDF简单实现
- 简单的方式由数据库的物理表(TABLE)生成实体类(DTO)
- 使用NetBox简单实现ASP封装为EXE教程
- Android-使用xUtils实现简单断点续传(主要代码)
- 使用正向最大匹配算法实现中文分词简单模型-用trie树实现
- jQuery实现简单的间隔向上滚动效果