实现简单DTO适配器,解放你的双手

     多数人不喜欢用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是单元测试。

    

      Dtod里面就是几个类,我们先简要概括一下。

      AppEnum 枚举定义类

      AttributeManager 自定义特性操作类

      DoAdapter DO适配器,用于DTO到DO的转换

      DtoAdapter DTO适配器,用于DO到DTO的转换

      DtodException 系统自定义异常

      DtoMemberMapAttribute 需要转换映射成员的标记特性,限制于属性

      IAdapter 适配器接口,规范DTO和DO适配器

     

       

       接下来我们看看怎么使用,我们做几个例子来说明一下,首先DTO到DO的一对一的适配,我们先做两个对象,一个DTO对象,一个DO对象

      

ExpandedBlockStart.gif 代码
///   <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类

 

ExpandedBlockStart.gif 代码
///   <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 ;
        }
    }

 

 

ExpandedBlockStart.gif 代码
///   <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对象的关系,我们做一下一对多的适配例子

 

 

ExpandedBlockStart.gif 代码
///   <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了。

 

转载于:https://www.cnblogs.com/assion/archive/2010/11/10/1873388.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值