循序渐进开发WinForm项目(2)--项目代码的分析
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了。
其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了。反过来,如果我们切换到其他领域,如IOS、android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水。
本篇继续上一篇《循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成》,继续介绍如何循序渐进开发Winform项目,继续分析介绍Winform的项目代码,从而让我们更加了解其中的分层和项目框架的组成等内容。
1、数据访问接口的定义
上面我们分析了实体类的定义,本节继续分析其他部分的内容,如数据访问接口成的定义如下所示。
namespace WHC.TestProject.IDAL
{
/// <summary>
/// 客户信息
/// </summary>
public interface ICustomer : IBaseDAL<CustomerInfo>
{
}
}
这里面的代码很简单,没有多余的代码行,那么里面究竟发生了什么呢,其中的IBaseDAL又是什么定义呢?
其实,IBaseDAL就是定义了很多我们开发用到的基础接口,如标准的增删改查,以及衍生出来的一些其他接口,如分页查询,条件查询等接口内容。这个ICustomer就是用来定义一些除了标准接口不能实现外的业务接口。
IBaseDAL通过传入一个实体类,从而方便给基类接口提供强类型的数据类型指定,提高我们的开发效率,减少出错的机会。
我们可以在VS里面查看IBaseDAL的定义,如下所示:
可以看到里面很多相关的接口定义,有返回实体T的,也有返回List<T>的,还有DataTable类型等等,这些基础接口,经过我们多个项目的应用实践,已逐步稳定并能够提供很好的接口支持,方便我们快速调用处理。
即使我们在没有实现任何业务接口的情况下,仅仅利用标准的基类API,也基本上能够完成绝大多数的数据操作功能了。
2、数据访问接口实现类的定义
我们分析完IDAL的数据访问接口成的定义后,继续了解一下,如何基于这个接口进行访问层的实现设计的。数据访问的实现层在项目中的位置如下所示(以基于SqlServer的DALSQL层进行分析)。
它的类代码定义如下所示。
namespace WHC.TestProject.DALSQL
{
/// <summary>
/// 客户信息
/// </summary>
public class Customer : BaseDALSQL<CustomerInfo>, ICustomer
{
数据访问接口实现层和接口定义层一样,都有一个基类,如基于SqlServer实现的基类为BaseDALSQL,这个基于SqlServer的数据访问基类,它也是继承自一个超级基类(大多数的实现在这里)AbstractBaseDAL。他们之间的继承关系如下所示
而我们刚才在项目工程的图里面看到,BaseDALSQL、IBaseDAL、AbstractBaseDAL这些类库由于具有很大的通用性,为了减少在不同的项目中进行复制导致维护问题,因此我们全部把这些经常使用到的基类或者接口,抽取到一个独立的类库里面,为了和普通的DotNET公用类库命名进行区分(WHC.Framework.Commons),我们把它命名为WHC.Framework.ControlUtil。
BaseDALSQL基类的定义如下所示。
这样做的好处是,在所有的模块里面,避免复制导致的版本维护问题,同时也减少代码的重复生成,增量生成的全部代码,可以一次性复制到整个项目工程里面,而不会导致基础类库的替换,因为这些基类不在生成目录里面,所有生成的类文件,都是和业务表相关的,如下所示。
具体的数据访问实现类(如Customer),它把数据库信息转换为实体类,有一个函数,在代码生成的时候已经生成;同时在把实体类的属性保存到数据库也有一个类似CRM的映射关系,从而实现可空的字段获取和更新操作。
/// <summary>
/// 将DataReader的属性值转化为实体类的属性值,返回实体类
/// </summary>
/// <param name="dr">有效的DataReader对象</param>
/// <returns>实体类对象</returns>
protected override CustomerInfo DataReaderToEntity(IDataReader dataReader)
{
CustomerInfo info = new CustomerInfo();
SmartDataReader reader = new SmartDataReader(dataReader); info.ID = reader.GetString("ID");
info.Name = reader.GetString("Name");
info.Age = reader.GetInt32("Age");
info.Creator = reader.GetString("Creator");
info.CreateTime = reader.GetDateTime("CreateTime"); return info;
} /// <summary>
/// 将实体对象的属性值转化为Hashtable对应的键值
/// </summary>
/// <param name="obj">有效的实体对象</param>
/// <returns>包含键值映射的Hashtable</returns>
protected override Hashtable GetHashByEntity(CustomerInfo obj)
{
CustomerInfo info = obj as CustomerInfo;
Hashtable hash = new Hashtable(); hash.Add("ID", info.ID);
hash.Add("Name", info.Name);
hash.Add("Age", info.Age);
hash.Add("Creator", info.Creator);
hash.Add("CreateTime", info.CreateTime); return hash;
}
3、业务逻辑层的实现分析
分析完成了数据访问层的接口和实现类后,我们来进一步看看业务逻辑层的实现分析,由于数据访问层的本意是基于特定的数据库实现,因此业务逻辑层就是抽象不同的数据库,让它们根据配置,指向不同的数据库实现类,从而实现多数据库的支持。
namespace WHC.TestProject.BLL
{
/// <summary>
/// 客户信息
/// </summary>
public class Customer : BaseBLL<CustomerInfo>
{
public Customer() : base()
{
base.Init(this.GetType().FullName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
}
}
}
业务逻辑层的代码也很简单,在构造函数里面Init一下即可,之所以使用这个Init操作,其实为了确定BLL层的业务对象名称和指定在哪个程序集里面进行构造的需要,让给基类进行必要的创建工作。
在BaseBLL的Init函数里面,我们根据子类传入的相关参数,由于我们约定了数据访问类的命名空间,因此只根据数据库配置的不同需要,替换部分名称,就可以具体的构造出一个数据访问类了。
#region 根据不同的数据库类型,构造相应的DAL层
AppConfig config = new AppConfig();
string dbType = config.AppConfigGet("ComponentDbType");
if (string.IsNullOrEmpty(dbType))
{
dbType = "sqlserver";
}
dbType = dbType.ToLower(); string DALPrefix = "";
if (dbType == "sqlserver")
{
DALPrefix = "DALSQL.";
}
else if (dbType == "access")
{
DALPrefix = "DALAccess.";
}
else if (dbType == "oracle")
{
DALPrefix = "DALOracle.";
}
else if (dbType == "sqlite")
{
DALPrefix = "DALSQLite.";
}
else if (dbType == "mysql")
{
DALPrefix = "DALMySql.";
}
#endregion this.dalName = bllFullName.Replace(bllPrefix, DALPrefix);//替换中级的BLL.为DAL.,就是DAL类的全名
baseDal = Reflect<IBaseDAL<T>>.Create(this.dalName, dalAssemblyName);//构造对应的DAL数据访问层的对象类
这样精确构造出来的数据库访问访问对象,并把它转换为基类接口,那么就可以在BaseBLL类里的基类接口进行调用了。
而构造业务对象,通过BLLFactory<T>的泛型工厂,更能够精确构造出对应的业务对象类,这样构造出来的对象具有强类型,非常方便使用。
以上就是业务逻辑层,数据访问层和数据访问接口层的设计关系,为了高效进行开发工作,我们一定要使用强类型的接口调用,这样可以大大减少出错机会,而返回的基类接口,由于传入了特定的具体类型T,也能够构造出强类型的列表或者对象。因此,合理利用泛型,能够是我们的开发体验更加美好,更加高效。
循序渐进开发WinForm项目(2)--项目代码的分析的更多相关文章
- 循序渐进开发WinForm项目(6)--开发使用混合式Winform模块
1.Winform数据访问模式定义 传统的Winform程序模块:用于传统的数据库通讯获取数据,这种方式获取数据,方便快捷,可以用于常规的业务系统的场景,用于单机版软件或者基于局域网内的业务系统软件. ...
- 循序渐进开发WinForm项目(5)--Excel数据的导入导出操作
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...
- 循序渐进开发WinForm项目(4)--Winform界面模块的集成使用
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...
- 循序渐进开发WinForm项目(3)--Winform界面层的项目设计
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...
- 循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...
- 如何快速开发Winform应用系统
在实际的业务中,往往还有很多需要使用Winform来开发应用系统的,如一些HIS.MIS.MES等系统,由于Winform开发出来的系统界面友好,响应快速,开发效率高等各方面原因,还有一些原因是独立的 ...
- Vue项目开发最新、最全代码规范文档
Vue项目开发最新.最全代码规范文档 2019年02月21日 10:43:49 yw00yw 阅读数 337 一. 目录结构 |— build 构建脚本目录 |— build.js 生产环境构建( ...
- DevExpress控件开发常用要点(项目总结版)
使用DevExpress控件来做项目开发已经有很长一段时间了,在摸索开发到客户苛刻要求的过程中,其中碰到过很多问题需要解决的,随着一个个问题的解决,也留下很多对DevExpress控件的使用经验及教训 ...
- MVC5 网站开发之二 创建项目
昨天对项目的思路大致理了一下,今天先把解决方案建立起来.整个解决包含Ninesky.Web.Ninesky.Core,Ninesky.DataLibrary等3个项目.Ninesky.Web是web应 ...
随机推荐
- vim之插入
进入vim插入模式,我们熟知的有: 字符位置插入: i 在光标之前插入 a 在光标之后追加 行位置插入: A 在一行的结尾处追加 I 在一行的开头处插入 o 在光标所在位置的 ...
- LCLFramework框架之Service模式
Service模式介绍 领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物.这些操作或动作往往会涉及到多个领域对象,并且需要协调这些领域对象 ...
- State状态设计模式
1.状态模式:改变对象的行为 一个用来改变类的(状态的)对象. 2:问题:当你自己实现 State 模式的时候就会碰到很多细节的问题,你必须根据自己的需要选择合适的实现方法, 比如用到的状态(Stat ...
- 【转】如何判断Javascript对象是否存在
Javascript语言的设计不够严谨,很多地方一不小心就会出错. 举例来说,请考虑以下情况. 现在,我们要判断一个全局对象myObj是否存在,如果不存在,就对它进行声明.用自然语言描述的算法如下: ...
- JS实现移动端图片延迟加载
图片延迟加载常见的有,jquery.lazyload.js,原生JS实现的echo.js.但是都是必须给图片设置宽高. 因为项目是移动端,而且无法在加载前知道图片的宽高,所以,只好自己写了一个. 既然 ...
- 部署tomcat在windows服务器下,将tomcat控制台日志记录到日志文件中
在Linux系统中,Tomcat 启动后默认将很多信息都写入到 catalina.out 文件中,我们可以通过tail -f catalina.out 来跟踪Tomcat 和相关应用运行的情况. ...
- HTML5应用程序缓存Application Cache详解
什么是Application Cache HTML5引入了应用程序缓存技术,意味着web应用可进行缓存,并在没有网络的情况下使用,通过创建cache manifest文件,可以轻松的创建离线应用. A ...
- 节日EDM系列:圣诞节如何进行EDM数据营销
消费关系升级,消费者看中的早已不是产品本身,场景消费以及消费带来的价值感体验已成为影响消费的重要因素.圣诞将至,如何才能将圣诞节EDM数据营销的效果发挥到极致? ① 节日元素创意融合,高辨识度加深品 ...
- 用SQL server导出到oracle,查询时提示“表或视图不存在ORA-00942”错误
用SQL server2005的导出工具,将数据导出表到oracle,表名称里看到有这张表了,但查询或删除时都提示“ORA-00942表或者试图不存在”的错误,上网查了一下,是如下原因: “查询或删除 ...
- 对象与Byte数组相互转化工具方法
/** * 对象转byte * @param obj * @return */ private byte[] ObjectToByte(Object obj) { byte[] bytes = nul ...