Mapping随想

来源:互联网 发布:杭州网站制作宣盟网络 编辑:程序博客网 时间:2024/06/06 00:29

由于公司部门要开始将现有的UI系统改造成MVC系统,因此我们开始着手将各项原来的webform模式转写成MVC。之前公司使用一套成熟的ORM系统,能够很好的将数据库和业务逻辑进行关联,程序员在编写代码时可以用非常轻松的编码方式将业务逻辑进行开发。在现有的ORM中Module也可以在不改变现有的ORM的基础上,将原有的业务对象重新通过组装后改写成新的Module。但是存在一个比较痛苦的事情是,原有的多对象的映射无法利用原有ORM系统进行修改。比如在列表上需要呈现出一些内容,但是该列表内容通过ORM取多个对象时效率不高,且业务逻辑复杂,因此原有的ORM系统并未在列表的呈现上使用ORM的方式,而是将数据库中的结果集通过直接封装的方式,返回一个IDataReader对象的方式进行二次处理,并将IDataReader处理成模板化的HTML给予直接返回。这样如果我们要改写成MVC的话就需要重新包装这个Module。

 

对于这样的Module从数据库中直接取一张表中的部分字段而非全部字段,再使用ORM系统显然并不合适。因此需要我们将数据库中的字段另外封装成一个Module。本来我考虑是将Module加入到业务对象中去,但是这样会造成业务对象的分割混乱不清,另外由于Module中的有些数据并不能从数据库中直接获取,而是需要多个字段经过一些逻辑运算后得出的,这样也就无法直接映射。最终我决定自己写一个简单的Mapping系统,来解决数据转化的问题。

 

设想有这样一个Module对象User,具有这样几个字段属性,FirstName,LastName,Age,Sex,这些字段属性都是可以在数据库中直接映射出来的。另有Name字段,是“{FirstName}.{LastName}”的格式,在数据库中并无直接字段对应,需要通过运算后得出的。

 

 

我们可以看到数据库中可直接映射的对象都具有Set访问器,而Name属性由于在数据库中没有直接字段,因此不具有Set访问器,其Get访问器中就蕴含了Name属性的业务逻辑。

 

如果,不用Mapping方式的话,就意味着,我们的程序员需要为每一个Module写一个从IDataReader转换成Module的方法,工作量庞大且容易出错,并且需要将业务逻辑转换到IDataReader中造成分割不清。因此设想有一个自动的Mapping转换器,可以在转换时无需关注业务逻辑,需要有业务逻辑的部分由Module自己来完成。

 

 

通过以上的代码可以看到,运用Mapping的方式,IDataReader可以自动转成Viewer所需要的Module。区别仅仅在于如果是一个数据库中不存在的字段,则Module中只有Get访问器,而没有Set访问器。方法在判断时依据该Property是否存在公共的Set访问器(是否可赋值)来标记决定是否给该Property赋值。不可使用PropertyInfo的CanWrite属性来判断,因为如果该Property具有一个私有的Set访问器,则系统仍然会认为该Property是可写的。

 

这样是不是把所有的问题都解决了呢,貌似是这样,但是我们设想一下,如前面提到的,如果由于业务逻辑的需要,这个Property需要一个Set访问器(不论是public的还是private的),那么我们又该如何来决定是否需要给该Property赋值呢?

这个问题就需要我们使用Attribute来解决了。我们新建一个MappingAttribute的类,该类继承自我们Attribute类,其中有一个bool型的字段IsMapping,用他来标记一个Property是否需要被Mapping。

 

 

好了,现在我们有了一个标签属性,可以用来标记一个字段是否需要被映射。那么User就可以改写成这样

 

 

对应的Mapping方式我们也可以改写一下成以下的样子

 

 

通过获取Property的Mapping标签属性(Attribute),并判断其中的IsMapping来决定是否需要映射,问题得到了解决。程序员不需要再把一个一个IDataReader通过手工的方式转成一个一个的Module。他们只需要关心Module中的字段是否和IDataReader关联,如果不关联,业务逻辑也可以在Module中自行处理,节省了开发的时间。

 

测试一下

 

测试结果很好

原创粉丝点击