进行到这一步,知识管理系统Data Solution已经一共介绍了六篇文章
知识管理系统Data Solution研发日记之一 场景设计与需求列出
知识管理系统Data Solution研发日记之二 应用程序系列
知识管理系统Data Solution研发日记之三 文档解决方案
知识管理系统Data Solution研发日记之四 片段式数据解决方案
知识管理系统Data Solution研发日记之五 网页下载,转换,导入
知识管理系统Data Solution研发日记之六 窗体设计器
做程序,最终的落脚点还是在代码上。代码可以帮忙实现我们需要的功能。感谢电脑界的发明,能让我们的生活因为有代码的存在,而变得简单,轻松。
Data Solution使用Visual Studio 2010编写,目标平台是.NET 3.5,Any CPU。解决方案视图如下所示
一共有七个项目,各个项目的作用解释如下
Common和Utility Library是常用的工具类型定义,比如读取PDF,转换DOC/DOCX为RTF
Controls是窗体设计器所需要的控件,组件定义,凡是内置控件不能作为的,都选择用自定义控件
Database Enginee 是读写数据库的操作类库,基于LLBL Gen Framework
Data Loader 是插件式框架的汇总程序,它聚集了大量的Data Solution应用程序模块
Editor 是文档编辑器,RTF格式编辑器,可以编辑本地文件和服务器中的文档资料
Form Designer 是窗体设计器,我把它当成是一个代码生成器,依据组件的不同,生成界面代码。
一直以来都在研究如何写源代码的分析文章。以前写过LLBL Gen Framework的分析文章,以追踪流程,调用堆栈的方式来铺开文章,这种方法使用过好几次。这次的文章,则以总结知识要点的方式来展开,把我表达的几个知识要点理解了,再去看代码,思路会清晰很多。
嵌入的资源 Embedded Resource
在Form Designer和Data Loader中,有很多资源文件,Data Solution以嵌入资源的方式把它直接嵌入到程序集中,以减少程序运行失败的机率,下面的是组件配置文件
Assembly assm = Assembly.GetAssembly(typeof(FlexDataTable)); string file="Component.Markup.xml"; Stream input = assm.GetManifestResourceStream(Shared.ResourcePrefix+"." + file); XmlComponent.LoadXmlComponentSchema(input);
再来看光标资源文件,它的代码是这样
private Icon GetIcon( IconName iconName ) { string fileName = string.Format( "{0}.{1}.ICO", IconManager.iconFolderName, iconName.ToString() ); type.Module.Assembly.GetManifestResourceStream( type, fileName ); Assembly assembly = Assembly.GetAssembly(typeof(Shared)); Stream stream = assembly.GetManifestResourceStream(Shared.ResourceIconsPrefix + "." + fileName); Icon icon = null; if (stream != null) icon = new Icon(stream); stream.Close(); return icon; }
数据访问 Data Access
因为窗体设计器的部分代码是直接从代码仓库(Repository)中拷贝出来的,所以它的数据访问代码是这样
以Database驱动SqlDatabase和OracleDatase来实际的访问数据库,这种模式在.NET 2.0中已经内置了工厂模式的数据库访问代码,如下的代码所示
if (DbFactory == null) { DbFactory = DbProviderFactories.GetFactory(providerName); } //SQL Server数据库 if (DbFactory is System.Data.SqlClient.SqlClientFactory) { return new SqlDatabase(); } //Oracle数据库 if (DbFactory is System.Data.OracleClient.OracleClientFactory) { return new OracleDatabase(); }经过这几年的实践,逐渐发现这种代码是无用的。很少有系统的生命周期长到可以考虑升级数据库,更换数据库的地步。我见过的活的最长的ERP系统,从1998年到今天,也是被绑定在SQL Server平台上。朋友公司的一套DELPHI系统,客户非要说用ORACLE数据库,项目也被一直拖着。在网上看到一则留言说,把数据库的字段类型从VARCHAR换成NVARCHAR都不可以接受,何况是对整个数据库的完全更换。以我这里的文档系统为例,我想也很难达到把它更改为ORACLE数据库的程度,做个文档管理系统,部署起来很麻烦,肯定会把客户吓跑。
对文档数据库进行读写的新的方法,是用LLBL Gen Framework的ORM框架,我想你肯定要问效率如何了,先不要考虑效率问题,先考虑产生可以工作的代码,程序和文档。
窗体设计器 Form Designer
MSDN网站有这一篇经典的文章《用.NET Framework 2.0创建 Form设计器》,它介绍了窗体设计器的基础结构。其实以前很羡慕微软的员工,可以看到很多代码和文章,一直怀疑微软的窗体设计器有很多没有公开的内容,这导致做一个好用的设计器并不容易,窗体设计本来就是个商业的技术范畴,你不能指望像ADO.NET一样,有很多参考的资料。
如果你不懂这里面的原理,就用Google搜索,我举例说明。用Form Designer source code来找,肯定找不到什么有价值的内容,如果你换成具体的技术细节,比如custom InitializeComponet来搜索,则可以看到下面的文章
这个源于系统生成的IntializeComponet有bug,它生成的的代码如下
this.bindingsourceHeader = new System.Windows.Forms.BindingSource(this.components); this.components = new System.ComponentModel.Container(); this.bindingsourceDetail = new System.Windows.Forms.BindingSource(this.components);
当运行这段代码,会抛出null异常,this.componets在没有定义前就被引用。借助于这个方法,我解决了这个问题。
微软的MSDN论坛,会请专业的IT编程人员,在这里解答问题,沟通讨论。这不同于我们看到的论坛,他们的定位是Professional,Support。所以如果有问题,可以在这里找到一些答案。另一个我认为很专业的论坛是stackoverflow,这里面聚集了大量的IT从业人员,Data Solution的很多思路,解决方案都是从那里得到的,感谢他们。
文档编辑器 Editor
从工作到现在,用得最多的编辑文字的控件,属微软的RichTextBox,平时我们都是用它的Text属性,如果你取它的Rtf属性,则得到的是RTF格式的文件内容,再配合CodeProject上的一些文章的指导,编辑器的代码框架如下
编辑器即可以当成WordPad的替代品,编辑本机磁盘文件,也可以编辑数据库服务器中的文档,这一点是它的威力所在。原本的Editor的方案是直接写成插件放到MS WORD中,对保存和打开文件对话框进行重写,以操作数据库服务器中的文件。这一步也并非难事,Visual Studio内置Office开发组件已经很多年了。这种方案的要求是,Data Solution的客户段中必须安装WORD,在这普通用户的机器上,不是问题,90%的电脑中,都内置了WORD。问题在于服务器中,当我把Data Solution运行于服务器中时,如果要编辑数据库服务器中的文档,则必须安装WORD,这有点不可以接受。我配置的Windows Server 2008 R2 X64,除了数据库SQL Server,对其它的组件,都是很忌讳安装的。我想,要使用Data Solution的客户,也会这样想,尽可能少的在服务器中装软件。
如果拥有了Data Solution的所有源代码,上面我列举的这些问题,也许还不是问题的起源。不同的程序员,对组件的熟悉程度不同。如果发现有问题,就调试源代码吧,调试代码可以帮忙你找到发生问题的原因。甚至你可以完全重写一套,抛弃我现在的做法,尽管Data Solution已经把这些组件,应用程序,代码都连接在了一起,做为一款知识管理系统的源代码,你可以按照你喜欢的方式对它进行重写,修补。