有限的对象深复制,IEditableObject实现。

    最近在项目中碰到一个这样的问题,就是在列表中双击打开编辑窗口,然后将BindingSource.Current的值传递给编辑窗体进行数据绑定,编辑完后再刷新表格中的数据。这是一个很普通的流程,以前也经常这么做没出过什么问题。但是现在却出现了一个麻烦。


    这个麻烦就是在编辑窗口中,即使没有点击保存按钮,按取消或者直接关闭窗口回来后,列表中的数据也会更改了。仔细想了一下,这其实是理所当然的,因为列表中绑定的实体类是引用类型的,所以传递过去的无非是指针而已,再加上在编辑窗口中是使用DataBindings来进行数据绑定的,因此有数据更改的时候就直接更新了数据源了。原来没有发生这个情况只不过因为原来是用代码绑定的而已。


    这个问题显然不应该出现的,就算没有保存到数据库中,但是也会给用户带来困扰,所以我们应该要解决。怎么解决呢?
    首先想到的就是在编辑的时候将BindingSource.Current复制一份出去编辑,这样如果用户按了保存后,再将那份Copy替换到数据源中,如果取消当然就什么也不发生了。但是这样似乎也有问题,首先就是引用类型的复制问题,直接用另一个变量显然是不行的,原理同上。那么就要深复制了。


    单个类深复制不成问题,手写代码就可以了。但是这是实体类啊,五十多个,时间也不允许啊,何况有个类还有好几十个字段属性的。


     那么还有什么办法呢?嗯,序列化与反序列化,这样出来后的就完全是另一个崭新的对象了。基本原理可行,那么有没有办法在不改动当前列表窗口和编辑窗口的编码的情况下完成这个功能呢?


   通过查询MSDN,得知如果BindingSource的数据源项如果实现了IEditableObject的话,那么BindingSource.CancelEdit就会自动调用该Object的CancelEdit方法,从而实现撤销编辑的功能。


    可是这样一来,问题又出来了。对每一个类的反序列化只能在类的外部进行,因为在内部是没有办法将this指针赋值的。怎么办呢?嗯哼,办法总是有的,众所周知,一个类根基的东西就是字段,类的任何外在表现其实都是与字段有关系的,也就是说,只要我们备份了一个类的所有字段信息,那么也就是完整的备份了这个类。


明白了这个道理,一切就没有问题了。开始动手吧。


    打开实体的接口定义IEntity,添加IEditableObject接口,再打开实体的基类BaseEnttiy,在这个基类里来实现该接口,这样所有的实体类就都有了BeginEdit, CancelEdit, EndEdit等各行为了。


    IEditObject接口有三个方法BeginEdit, CancelEdit, EndEdit,而BindingSource提供给外部调用的只有后二者。BeginEdit则会由BindingSource在内部调用。

 

    我们先来实现这个接口,想法是这样的:当调用BeginEdit的时候,我们就备份数据,调用CancelEdit的时候我们就

    还原数据,调用EndEdit的时候就清空备份数据。所以至少需要两个方法:Backup 和 Restore.

posted @ 2010-09-09 15:02  庙子  阅读(200)  评论(0编辑  收藏  举报