zoukankan      html  css  js  c++  java
  • 基于窗体设计器的企业管理软件开发工具

    因为工作的关系,接触到企业管理软件开发平台。一套很完备的工具集,方法论和应用案例。这东西有点像软件工厂,可以根据业务需求不同,生产各种类型的软件。大部分通用的功能,比如数据的增删查改,报表,都可以预先做好,然后根据各项目业务不同,加载不同的业务模块,组装成产品。
    以我的理解,做这么一套工具集,需要很强的编程功力,至少还要有一个团队,可以分工协作,做基础模块的要保证稳定,做应用模块的,做出的程序要有很强的适应能力,可以应对各种需求的变化。

    一套完整的开发平台,应该包括
    实体设计器 可以设计业务实体,生成SQL脚本代码和类代码。
    窗体设计器  设计用户界面,一次设计,可以同时生成Desktop,Web两种界面
    业务流程设计器 设计系统流程,可适应各行业的流程需求
    部署工具  部署用户定制设计的内容

    下面以我的理解,谈谈窗体设计器的前前后后相关的内容。因为这些工具是我业余时间折腾的,和公司的平台和技术毫不相关,所以我能放心的与你分享我的设计思路。
    1  首先要有一个窗体设计器。这东东,到现在为止,还是个很宝贵的工具,网上(google)几乎找不到可以拿来用的,有一些DEMO演示,但不完善,还要做很多工作。
    如果你知道rehost技术,还知道SharpDevelop这本书,可以找到窗体设计器的源码。还有这篇文章,《用.NET Framework 2.0创建 Form设计器》,都可以解决窗体设计器的源码问题。
    CodeProject上面也有几个不错的例子,可以直接拿来就用的。
    2  找到了窗体设计器的源码,接下来做的工作就是分析它的机制,要满足几条才能应用
    1)序列化机制 XML格式是最好的存储格式,因为XML可以跨平台,被任何语言和工具解析,将来被移植的可能性大,XML格式可以被各种小工具和小应用程序解析,比如在实际应用中要判断窗体对应的表是否存在,可以直接读取相应的XML片段,判断即可。
    CodeProject上面有一个很好的窗体设计器,就是因为它把窗体序列化为二进制格式,解析起来相当不方便,只好忍痛放弃。
    2)可支持扩展。比如需要在设计器中加载第三方的控件,可以通过增加一行配置就保证运行正常。
    image

    如图,Windows Forms工具箱加载.NET提供的基础控件,Flex Forms工具箱加载自定义的控件。
    为什么要加载自定义控件呢?为了平台的方便。比如,如果用TextBox接受用户的输入,输入本月购买直接物料的数量,在保存窗体文件时,需要检查输入的类型是数值类型,这样的检查需要很多重复的代码。如果把TextBox换成IntegerBox,这个控件只接受整型的数值,否则会报错。这样,检查用户输入的代码就可以移到窗体设计器的运行时码中,减少代码重复。

    3 于是,拖拖拉拉设计好窗体,点击保存,问题又来了,如何保存呢?
    1)直接保存到电脑本地文件,这样可以随时修改。因为要做一系列的窗体,比如一个采购审批系统,要有采购申请单,部门经理审核单,财务经理审核单。当这些窗体多了以后,需要规范的管理起来,不能在电脑上到处乱放。于是,在指定的目录,放相同模块的窗体文件。
    好处很明显,查找容易,修改也容易。缺点是文件容易被篡改,不安全
    2)把文件上载到服务器。点击保存按钮时,把当前的窗体文件上传到服务器的指定的目录下。
    3)把文件保存到数据库中。这个是目前我采用的方案,直接放到数据库中,安全是没有问题。但是每次需要读取数据,解析,还原成XML窗体文件。当窗体的控件很多时,运行和设计都很慢
    4)把文件编译成Assembly文件,直接放到当前程序集目录下。这个方案可以解决文本文件不安全的问题,也可以解决速度问题,因为是在本机,可以很方便的读取,而且是assembly格式,不容易被破坏。
    保存的时候,也有讲究。不能用名字,因为名字可能会重复。用不会重复的GUID,但是不容易识别,还要配合名字,方便用户查找。

    4  窗体文件被保存后,如何被快速检索呢?
    做到这一步,需要开始涉及业务方面的处理。首先,需要一个管理工具,按照系统的划分层次,可以建立应用程序(Application),建立模块(Module),然后把设计的窗体文件划分到具体的类别当中。
    比如,设计一个采购系统,命名为Purchase Management,再建立几个模块,申请模块和审批模块,还有涉及到库存,也要设计好。
    当上传窗体文件的时候,就需要按照当前的窗体的作用,放到选定的模块中。
    于是,可以按照模块来检索窗体文件,根据需要,做相应的修改或调整。
    为了方便,也可按照名字,搜索窗体,找到后,直接在设计器中打开。
    虽然窗体文件是用GUID来识别的,但是用户很少能记住这一长串的字母,很少去用ID来查找窗体。

    5  窗体设计好了,也保存成功,现在需要一个窗体运行容器(Container,Runntime),可以容纳窗体运行。在容器启动时,需要加载一系统的服务,以保证窗体的运行;容器同时也提供窗体的测试环境,把设计器设计好的文件丢到容器中跑一下,看看有什么问题,以方便诊断。
    image

    如图,可以直接打开窗体设计完成后的XML文件,看看运行的效果;也可以连到服务器,打开服务器中的窗体文件,作出适当的调整。这个工具集窗体测试,诊断分析于一体,相当的好用。

    6 做一个应用界面,加载必要的服务,根据服务器中的应用程序(Application)和模块(Module),建立导航界面,引导用户进入相应的模块。用户设计的一般是分散的应有,很少考虑整个系统的完整性,同时,用户设计的窗体也不容易加载扩展插件,比如业务插件,流程插件。需要自己写一个容器,把用户设计的界面,集成到一起,同时提供一些基础的服务。
    到这一步,一个基于窗体设计器的应用软件就已经设计完成,所有的过程不需要编码。

    7  数据如何被存储到数据库中,又是如何被查询出来?
    在设计界面的时候,界面上的控件就已经和数据库中的表进行了绑定。
    image
    在新建一个数据输入类型的窗体,会有一个DataTable属性,用于指定该窗体对应的数据库表
    在窗体中每个需要输入数据,并进行保存的控件,也有一个DataColumn属性,于是指定数据的列
    还有一个DataType属性,把用户输入的内容,输化为DataType类型的数据,存到DataColumn指定的数据列中。
    image 
    这些设计都以可视化的方式完成,减少出错。如下图,直接获取一个表的字段信息,用于填充窗体控件
    image

    如果是查询窗体,也可以用SQL智能的查询分析器,帮助用户快速构建查询结果 image
    用户可以手写SQL语句,也可以点击查询按钮,用查询分析器来写SQL。
    这里有个疑问,一直没搞懂。用ICSharpCode.TextEditor.dll作语法高亮编辑器,无论文件是否超过一屏,它都会出现横向滚动条,很不美观,在网上找了很久也搞不定。我的代码生成器也是这样。
    如果一个SQL语句只有几个字符,它也显示横向的滚动条,看着很不舒服。
    在检索窗体的时候,会检查这个窗体是否有数据,如果有数据,会加载数据。如果是新建一个窗体,比如新建一个采购申请单,则不加载数据。

    8  业务插件如何加载,系统如何扩展?
    这是同一个问题。用标准的assembly格式,写好需要被调用的方法。在窗体运行之前,会加载一系列的服务,这个服务包含加载配置文件中指定的类库。用简单的语法,在需要调用自定义逻辑的地方,指定方法名和参数,运行时引擎分析这个参数(是个字符串),解析成反射的方法调用语法,调用指定的类库中的方法。为了方便,系统会预先写好一些常用的类库,比如时间处理,序列号处理。
    如果用户需要扩展系统,把assembly放到指定的目录下,在配置文件中指定需要加载的程序集,然后只管在需要的地方调用,引擎会处理好怎么去找程序集,如何反射到方法并调用。
    比如,我为了验证这种方法的可行性,故意写了个数据库备份工具
    image 
    界面布局有点乱。取到界面上的用户输入的Server,UID,Password的值,传到Backup按钮的点击事件中,该事件运用反射,调用我写好的类库,数据库备份功能。
    public void Backup(string server, string database, string uid,string password)
       {
    SQLDMO.SQLServer svr = new SQLDMO.SQLServerClass();
    svr.Connect(ServerName, UserName, Password);
    SQLDMO.Backup bak = new SQLDMO.BackupClass();
    bak.Action = 0;
    bak.Initialize = true;
    SQLDMO.BackupSink_PercentCompleteEventHandler pceh = new SQLDMO.BackupSink_PercentCompleteEventHandler(Step);
    bak.PercentComplete += pceh;
    bak.Files = strFileName;
    bak.Database = strDbName;
    bak.SQLBackup(svr);

    }

    还有一些细节没有考虑到,比如数据库的表如何设计,表与窗体如何关联,如何验证窗体,如何把窗体与工作流程绑定。有时间的时候再补充。
    搞这个东东还是很辛苦的,也不见得有什么成效。真正做起项目来,客户需求一改再改,界面换了一次又一次,如果都用平台来做,估计会累死。我折腾过几次,也没有大的成效,技术的提升只是额外的收获。有理解的不对的地方,请各位多多指教。

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/1666796.html
Copyright © 2011-2022 走看看