你对DTO的理解有误,我帮你梳理一下,首先一个程序的灵魂是domain层,即通过面向对象的方法分析内在状态和行为,通过抽象和责任设定对象,此对象为BO,然后因为有界面,可能是HTML可能是WPF,而BO未必能匹配界面对象所要求的显示方式和数据源模式,所以通过VO进行适配,将BO以界面可以理解的方式展示出来。ok,当你的程序即domain需要持久化时,因为你数据库可能是sqlite,mysqlite这样的关系数据库,也可能是文件,所以此时需要PO介入适配持久化方式。最后当需要跨进程传递数据时,则需要用TO,因为网络或者进程间是无法传递指针,所以必须将其转化为stringify对象,这个就是TO的价值和责任。所以每一类对象都有其价值和责任,万变不离其宗,就是保证BO的干净和纯净,只对业务负责,隔离持久化、界面和跨进程交换数据,不要为了对象而对象,都是强应果关系。当然,最后需要一点点变通,很多简单场景下,BO是能过兼容VO,PO甚至TO,是情况而定,但道理你要懂。

解决方案 »

  1.   

    什么BO\VO\PO\TO,完全不知所云。
    楼主的问题很简单,只要明白两者传递方式的不同就知道了,值类型是值传递,类则是引用传递,DTO需要的是引用传递,值传递不适合,这和效率无关,你UI改动要实时反映到对象上面,必须是引用类型才能做到(大家操作的是同一个对象)。
      

  2.   

    有些搞java的人把实体对象叫做DTO。基本上,很少使用值类型。正如你说的,它往往不是正常地引用,而是不断在内存中拷贝复制,因此非常谨慎地用值类型。其实你可以想象一下,如果你是EF之类的框架的设计师,你会产品会自动产生成百上千个实体类型,你会生成为值类型还是引用类型?哪一种比较容易让更多程序员接受?
      

  3.   

    那些int、double、byte、DictionaryEntry、DataTime之类的是值类型,因为它们是如此之“小巧”。有些复杂类型内部的个别内嵌类型会设计为值类型,因为它确实几乎没有被以引用方式编程过(因此其不断复制内存的行为没有什么机会被触发),它只是在使用它的复杂类型中的代码中被简单使用一两下,并不被广大程序员直接重复使用。有些复杂的递归下降分析方法,例如在linq内部使用到的分析,或者一些数学计算模型,其理论模型就要求当调用时以copy值压入堆栈。如果是引用的,那么你仍然需要用代码先复制、然后才引用传递。因此这类内部对象设计为值类型就行了。反正是算一算声明为struct还是class分别在使用代码中的代价,取“痛苦”比较轻的哪一种。
      

  4.   

    什么BO\VO\PO\TO,完全不知所云。
    楼主的问题很简单,只要明白两者传递方式的不同就知道了,值类型是值传递,类则是引用传递,DTO需要的是引用传递,值传递不适合,这和效率无关,你UI改动要实时反映到对象上面,必须是引用类型才能做到(大家操作的是同一个对象)。
    谢谢解答!
    你说的是通过引用来实时改变我不太能够理解。
    比如一个学生类Student 对应一个DTO StudentDTO,
    那么,一个DTO的对象引用应该不可能指向一个实体引用吧?!
    还有,我们在做报表的时候也会用一个Detail对象来,这个Detail类也可以用值类型的,为什么一般都是用的类呢?
    比如说,我们要做一个成绩的报表,那么他需要Student的信息,也需要Score的信息,我们常常用一个ScoreDetail类来综合信息,我们明明可以用一个ScoreDetail值对象嘛!
      

  5.   

    别纠结啥值和引用了研究方向完全错误,你研究的方向应该是“为什么会出现DTO”而非别滴post(我的对象 obj)

    post(int 参数1,string 参数2)和
    post (object[] {1,"2"})
    到底谁更符合工程需要
      

  6.   

    谢谢回复!
    我的疑问是为什么DTO是引用类型,我大致明白DTO的作用。
    struct Student{}
    照你的例子,一个post (Student student)
    我传递一个结构体类型也是可以的,为什么一定是类对象呢?
    我的疑问是DTO为什么是类而不是结构体?
      

  7.   

    呵呵,从来就没人说过不准传结构体,你当然可以传结构体。作为DTO来说传结构体问题不大,因为DTO通常不需要修改里面的值,只不过作为其他场景我们会经常修改对象的值,默认能修改内部的值,总比每次写个ref,out要舒坦把
      

  8.   

    另外,class类本身还可以实现一些特定的接口,来做一些自动化的UI更新,消息同步工作比如我们可以挂接属性更改通知,也可以挂接属性验证,挂接了这些玩意的class,可以自动完成很多代码,不在需要你去做很多很多的UI事件操作,这也是wpf里那个viewmodel的基本原理,而单纯数据使用的结构体化对象就很难具备这样的功能了
      

  9.   

    在领域驱动里面,会经常通过修改DTO的值来达到修改实体值的目的啊。
    虽然我对这个也不太懂 呵呵~
    我只是对项目里面什么都使用类,而不适用结构体表较疑惑。
      

  10.   

    对于webform或者mvc程序员来说,DTO确实就是你说的那种功能但是对于WPF,winfrom程序员来说,DTO就不仅仅需要那种功能了
    对于WPF,winfrom程序员来说,一个对象的更改,其实可以自我保存(web没状态,而桌面程序他是有状态的)
    ,既然他可以自我保存,我们则不必去手动去修改他值举个例子:
    web程序员通常这么写
      var obj= db.getXXX() 从数据库获取对象
      textbox1.text=obj.name; 
      
     如果要保存则是: obj.name=textbox1.text;
    你当然认为这样的情况,这东西就是传递值不过对于winfrom
       public partial class Form1 : Form
        { 
            MyStruct x = new MyStruct();
            MyClass x1=new MyClass();
            public Form1()
            {
                InitializeComponent();
            }        private void Form1_Load(object sender, EventArgs e)
            {
               
                x.name = "a";
                x1.name="a";
                this.textBox1.DataBindings.Add("Text", x, "name");
                 this.textBox2.DataBindings.Add("Text", x1, "name");        }        private void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show("结构体绑定的结果:"+x.name+"无法自动反应出更新的值");
                MessageBox.Show("引用对象绑定的结果:"+x1.name+"能自动反应出更新的值");
            }
        }    public struct MyStruct
        {
            public string name { get; set; }
        }
        class MyClass
        {
            public string name { get; set; } 
        }这是一个winfrom的简单窗体,运行以后你可以看到两个textbox上都绑定一个对象,这时候你更改两个textbox的值,然后点击按钮,你会发现绑定了结构体的textbox无论你输入什么,他都会弹出最初的那个值“a”,而绑定引用对象的textbox,则你输入什么他就会弹出你输入的值ps:其实现在web方面也有mvvm化的倾向,js版的mvvm如今也在大规模运用,google有AngularJs,第3方还有KnockoutJ