在此系统的项目中我们采用NHibernate实现了ORM;采用Unity来实现了DI和AOP。这2个技术方案应该说都很不错。但随之而来的是,在较大规模系统中产生了大量的XML配置文件。
在我们的实际开发中发现编写和存在大量的XML配置文件有以下几点不利:
1.我们需要在XML中编写大量项目中的数据表名,数据库字段名,命名控件,类名等 ,但由于各种因素我们很难保证在XML的纯文本文件编辑器里键入的准确性。
往往一个字母或符号搞错,就会导致整个项目无法运行。就连“复制粘贴大法”有时候也难避免出错,且不说“复制粘贴大法”其实效率很低....,后来尝试做了
些自动生成工具,但因为有很多差异化,效果也不理想。
2.对于XML里的字符,维护检索比较困难。刚开始还好,做到后面你会发现随着项目进度的不断推进,项目中的XML已经变得非常庞大了。
想要从中准确的找到并正确修改一些东西已经成了一件很麻烦的事情,而且还会提心吊胆的怕改错了....
3.由于实际上线中的各种情况,XML文件实现不重新编译代码就能改变系统的想法其实不大现实....对于大多数系统更新我们往往还是要暂停系统重新编译整个项目
于是我们想到,不如把这些XML的相关配置都用代码实现,干掉这些难以编写和维护的XML文件!!
一.用Fluent代替NHibernate的XML配置和映射
在Asp.Net大型项目实践(4)-用NHibernate保存和查询我们的业务领域对象之实现基本的数据库访问(附源码) 中我们采用XML文件来实现映射:
<? xml version="1.0" encoding="utf-8" ?>
< hibernate-mapping xmlns ="urn:nhibernate-mapping-2.2"
assembly ="Infrastructure.Core" namespace ="Demo.HIS.Infrastructure.Core" >
< class name ="Demo.HIS.Infrastructure.Core.Dictionary" table ="INFRA_DICTIONARY" dynamic-insert ="true" dynamic-update ="true" where ="IsDelete=0" >
< id name ="Id" column ="DICTIONARY_ID" type ="String" >
< generator class ="assigned" />
</ id >
< version name ="Version" column ="VERSION" unsaved-value ="0" />
< property name ="Name" column ="NAME" type ="String" />
< property name ="Code" column ="CODE" type ="String" />
< property name ="InputCode1" column ="INPUT_CODE1" type ="String" />
< property name ="InputCode2" column ="INPUT_CODE2" type ="String" />
< property name ="InputCode3" column ="INPUT_CODE3" type ="String" />
< property name ="Index" column ="INDEX_FIELD" type ="Int32" />
< property name ="Description" column ="DESCRIPTION" type ="String" />
< property name ="CreateTime" column ="CREATETIME" type ="DateTime" />
< property name ="IsDelete" column ="ISDELETE" type ="Boolean" />
< many-to-one name ="Category" column ="DICCATEGORY_ID" not-null ="true" lazy ="proxy" class ="Demo.HIS.Infrastructure.Core.DicCategory" />
</ class >
</ hibernate-mapping >
现在我们改进用Fluent来实现映射:
1 namespace EVHIP.OMS.Repositories.Mapping
2 {
3 public class DicItemMap : InputItemMap < DicItem >
4 {
5 public DicItemMap()
6 {
7 Table( " OMS_DIC_ITEM " );
8 Id(t => t.Id, " DIC_ITEM_ID " );
9 References(t => t.Category, " DIC_CATEGORYD_ID " );
10 Map(t => t.Description, " DESCRIPTION " );
11 Map(t => t.IndexField, " INDEX_FIELD " );
12 Map(t => t.IsEnable, " IS_ENABLE " );
13 }
14 }
15 }
注意代码中继承的这个类InputItemMap<DicItem>,用了Fluent附带的好处类的映射也可以根据类的继承关系进行继承:
1 namespace EVHIP.Support.BaseEntities.Mapping
2 {
3 public abstract class InputItemMap < T > : BaseEntityMap < T > where T : InputItem
4 {
5 public InputItemMap()
6 {
7 Map(t => t.Text, " TEXT " );
8 Map(t => t.Code, " CODE " );
9 Map(t => t.InputCode1, " INPUT_CODE1 " );
10 Map(t => t.InputCode2, " INPUT_CODE2 " );
11 Map(t => t.InputCode3, " INPUT_CODE3 " );
12 }
13 }
14 }
二.把Unity的DI和AOP配置写到代码里
在Asp.Net大型项目实践(6)-用Unity实现层与层之间的接口调用(附源码) 中我们也是采用XML来配置接口和具体实现:
现在改为写到代码里:
1 #region Dictionary
2 container.RegisterType < IDicCategoryRepository, DicCategoryRepositoryImpl > ();
3 container.RegisterType < IDicItemRepository, DicItemRepositoryImpl > ();
4 container.RegisterType < IDicCategoryBiz, DicCategoryBizImpl > ();
5 container.RegisterType < IDicItemBiz, DicItemBizImpl > ();
6 container.RegisterType < IDictionaryManager, DictionaryManagerImpl > ();
7 container.RegisterType < IDictionaryService, DictionaryServiceImpl > ();
8 #endregion Dictionary
9
10 #region GeneralDept
11 container.RegisterType < IGeneralDeptRepository, GeneralDeptRepositoryImpl > ();
12 container.RegisterType < IGeneralDeptBiz, GeneralDeptBizImpl > ();
13 container.RegisterType < IGeneralDeptManager, GeneralDeptManagerImpl > ();
14 container.RegisterType < IGeneralDeptService, GeneralDeptServiceImpl > ();
15 #endregion GeneralDept
有了强类型的智能感知,不用复制粘贴了,也不怕字符敲错了......
项目里没有一大堆Xml配置文件都不好意思和别人打招呼的时代已经过去了....让我们一起来干掉无厘头的XML吧....
下篇预告:Asp.Net大型项目实践(14)-约定胜于配置:解决Asp.net中繁琐的UI层赋值代码