|
源代码网推荐
在7月份中我曾经写过一篇随笔叫,叫" .NET2.0 框架中的 AbstractFactory 模式 " 。
里面主要说了在2.0框架下的数据库链接工厂中新增的几个类,而这几个类采用的就是 抽象类工厂模式(Abstract Factory)。因为在Discuz!NT 2。0中使用了这些新的类,所以导致我们的产品dbhelper.cs可以支持几种数据库(目前官方实现的有sqlserver ,access ,mysql)。但同时因为1.0框架下没有这些类,所以我们采用自已简单实现其中主要的类代码来解决这个问题。这就有了今天文章的内容!
为了便于大家对照我将抽象类工厂模式结构图与项目中实现的结构图同时贴上:
首先请大家看一下AbstractFactory模式的结构图

然后请大家看一下Discuz!NT项目中的数据链接结构图

好,现在开始上路了。
这个架构中最主要的核心数据库链接所需要的(connection,Command,DataAdapter)对象就是围绕下面m_factory的使用和赋值展开的, 请看如下代码
1 /// <summary> 2 /// DbProviderFactory实例 3 /// </summary> 4 private static IDbProviderFactory m_factory = null; 5 6 /// <summary> 7 /// DbFactory实例 8 /// </summary> 9 public static IDbProviderFactory Factory 10 { 11 get 12 { 13 if (m_factory == null) 14 { 15 m_factory = Provider.Instance(); 16 } 17 return m_factory; 18 } 19 } 20
而其中的Provider.Instance();实现的代码如下
1 /// <summary> 2 /// Discuz!NT数据接口 3 /// </summary> 4 private static IDbProvider m_provider = null; 5 6 /// <summary> 7 /// IDbProvider接口 8 /// </summary> 9 public static IDbProvider Provider 10 { 11 get 12 { 13 if (m_provider == null) 14 { 15 lock(lockHelper) 16 { 17 if (m_provider == null) 18 { 19 try 20 { 21 m_provider = (IDbProvider)Activator.CreateInstance(Type.GetType(string.Format("Discuz.Data.{0}Provider, Discuz.Data.{0}", BaseConfigs.GetDbType))); 22 } 23 catch 24 { 25 throw new Exception("请检查DNT.config中Dbtype节点数据库类型是否正确,例如:SqlServer、Access、MySql,注意大小写。"); 26 } 27 28 } 29 } 30 31 //m_provider = new DbProviderFinder().GetDbProvider("accesss"); 32 33 34 } 35 return m_provider; 36 } 37 } 38
大家看到这里使用了反射,而BaseConfigs.GetDbType这个属性的调用在一个叫做Dnt.config的文件中有相应设置,它标识了当前数据库是Sqlserver,Access还是MySql 那么目前我们假设使用的是SqlServer型的数据库,那么上面的"Discuz.Data.{0}Provider, Discuz.Data.{0}"就会变成是"Discuz.Data.SqlServerProvider, Discuz.Data.SqlServer",我们不妨在这里找一下Discuz.Data.SqlServer这个项目中,为方便,我这里直接将Discuz.Data.SqlServer这个类代码贴在这
1 public class SqlServerProvider : IDbProvider 2 { 3 public IDbProviderFactory Instance() 4 { 5 return SqlClientFactory.Instance; 6 } 7 8 public void DeriveParameters(IDbCommand cmd) 9 { 10 if ((cmd as SqlCommand) != null) 11 { 12 SqlCommandBuilder.DeriveParameters(cmd as SqlCommand); 13 } 14 } 15 16 public IDataParameter MakeParam(string ParamName, DbType DbType, Int32 Size) 17 { 18 SqlParameter param; 19 20 if (Size > 0) 21 param = new SqlParameter(ParamName, (SqlDbType)DbType, Size); 22 else 23 param = new SqlParameter(ParamName, (SqlDbType)DbType); 24 25 return param; 26 } 27 28 29 30 } 31 32 //SqlClientFactory工厂类,提供对SqlServerProvider中的Instance返回实例的支持 33 public class SqlClientFactory : IDbProviderFactory 34 { 35 public static readonly SqlClientFactory Instance; 36 37 static SqlClientFactory() 38 { 39 Instance = new SqlClientFactory(); 40 } 41 42 private SqlClientFactory() 43 { 44 } 45 46 47 public IDbConnection CreateConnection() 48 { 49 return new SqlConnection(); 50 } 51 52 53 public IDbCommand CreateCommand() 54 { 55 return new SqlCommand(); 56 } 57 58 public IDbDataAdapter CreateDataAdapter() 59 { 60 return new SqlDataAdapter(); 61 } 62 63 } 64 65
其中SqlClientFactory是一个在.net2.0框架下才有的类,这里因为考虑产品架构在1。0和2。0下的对应关系,这里使用了相同的类名称。而这里类在抽象类工厂模式中的位置就是ConcreateFactory部分所需要实现的代码。
同理大家可以找到另个两个项目DLL,Discuz.Data.Access中AccessProvider.cs和Discuz.Data.MySql中的MySqlProvider.cs,大家会发现类似的代码实现。
现在大家应该清楚了这个数据库链接架构的核心了吧。
另外就是发表完这篇文章后,关于DISCUZ!NT系列的随笔会暂时先告一段落。主要是因为另外一系列的文章将要登场,这也是我最想写的文章,主要是关于ICONIX(UML)的。
最后再把这个系列中的随笔进行一下分类归纳如下:
控件类:
Discuz!NT控件剖析 之 Button [原创: 附源码]
Discuz!NT控件剖析 之 TextBox [原创: 附源码]
Discuz!NT控件剖析 之 ColorPicker(颜色拾取) 和Calendar(日历) [原创: 附源码]
Discuz!NT控件剖析 之 Tab 属性页 [原创: 附源码]
架构类:
Discuz!NT 缓存设计简析 [原创]
Discuz!NT 聚合功能页面程序架构(重构到Facade与Observer模式)
Discuz!NT 中的数据库链接类(抽象类工厂模式)
插件类:
Discuz!NT 邮件插件机制分析
源代码网供稿. |