循序渐进开发WinForm项目(6)--开发使用混合式Winform模块

1、Winform数据访问模式定义

传统的Winform程序模块:用于传统的数据库通讯获取数据,这种方式获取数据,方便快捷,可以用于常规的业务系统的场景,用于单机版软件或者基于局域网内的业务系统软件。

WCF的Winform程序模块:采用了WCF技术的分布式开发模式,系统能够通过远程的WCF服务获取数据,而不用直接和数据库相连,提高数据的安全性和可维护性,适用于互联网、局域网环境下的业务系统的搭建,是一种稳定、安全的框架应用。

混合式Winform程序模块:是指混合了传统数据访问和WCF数据访问的特点,可以在两者之间自由切换,统一了系统界面层对业务服务的调用模式,所有组件模块均实现两种方式的调用,是一种弹性化非常好的框架应用,既可用于单机版软件或者基于局域网内的应用软件,也可以用于分布式技术的互联网环境应用。

每种技术都有其存在的合理性,对于混合式的Winform程序而言,也是一样。在数据越发集中的今天,单机版的数据很难进行共享,只在一定范围内进行使用;混合式的Winform程序,结合了Winform程序丰富的体验和强大的功能外,还整合了B/S的这种分布式特点,因此这种模式的存在生命力很强,有一些程序的操作使用Winform方式能够给客户提供非常好的界面效果体验。

2、混合式框架的原理

混合式框架,结合了普通Winform方式和WCF访问数据的分布式框架,因此他们是基于一个跳转开关进行指定,如下示意图所示。

为了适应模块化的特点,所有使用混合式框架的业务模块,除了一个启动的主程序模块外,其他的都是一个个独立的模块,这样方便我们业务横向的划分,可以使大家按照统一模式进行开发,然后再进行统一集成,这种模式可以有效提高开发效率,并且能够使得模块能够反复使用,组合出更多更强的业务系统模块。

下面是一个字典模块的内部设计图,我们可以看到,整个混合式的架构,分为了UI层、接口调用层、Facade接口层、Winform调用层、WCF服务调用层、业务层、实体层、以及数据库层等;其中的业务层还可以细化为BLL业务逻辑层、数据接口层、数据访问层、实体层等,整个模块通过实体层进行数据的传输载体。

3、混合式模块的项目结构

混合型框架把业务系统的WCF服务和辅助性公用模块的WCF服务分开,首先是服务分开,然后是客户端配置文件分开。

下面是一个实际业务系统的WCF服务的截图,可以看出里面的主业务服务和基础服务模块的服务层是分开的,这样方便管理,不至于太多太乱。

WCF服务的客户端配置文件是分开管理的,基础服务和业务服务的配置信息分别用不同的文件表示,如基础模块服务的WCF配置文件为BaseWcfConfig.config,业务系统的WCF配置文件为WcfConfig.config,通过这样的分离设置,我们在主配置文件app.Config文件里面,就清爽很多了。

    <!--WCF服务的配置文件地址-->
    <add key="BaseWcfConfig" value="BaseWcfConfig.config"/>
    <add key="WcfConfig" value="WcfConfig.config"/>

4、开发使用混合式Winform模块

例如,我们在业务逻辑层里面增加一个方法,根据客户名称获取客户列表,如下所示。 

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);
        }

        /// <summary>
        /// 根据客户名称获取客户列表
        /// </summary>
        /// <param name="name">客户名称</param>
        /// <returns></returns>
        public List<CustomerInfo> FindByName(string name)
        {
            string condition = string.Format("Name like '%{0}%'", name);
            return baseDal.Find(condition);
        }
    }
}

图上红色部分的函数是我们新增的内容,完成这个函数,我们来看看完成整个混合式框架,需要增加哪些东西。

1)添加Facade接口

为了统一的接口调用需要,需要先定义Facade层的接口,这是一切的开始。

namespace WHC.TestProject.Facade
{
    [ServiceContract]
    public interface ICustomerService : IBaseService<CustomerInfo>
    {
        /// <summary>
        /// 根据客户名称获取客户列表
        /// </summary>
        /// <param name="name">客户名称</param>
        /// <returns></returns>
        [ServiceContract]
        List<CustomerInfo> FindByName(string name);
    }
}

2)增加Winform接口调用层实现

基于Winform的实现,就是根据接口封装对业务逻辑层BLL的调用,BaseLocalService基类,可以看成是具有常规增删改查等等的基础性API,是基于泛型的强类型接口基类。

namespace WHC.TestProject.WinformCaller
{
    /// <summary>
    /// 基于传统Winform方式,直接访问本地数据库的Facade接口实现类
    /// </summary>
    public class CustomerCaller : BaseLocalService<CustomerInfo>, ICustomerService
    {
        private Customer bll = null;

        public CustomerCaller() : base(BLLFactory<Customer>.Instance)
        {
            bll = baseBLL as Customer;
        }

        /// <summary>
        /// 根据客户名称获取客户列表
        /// </summary>
        /// <param name="name">客户名称</param>
        /// <returns></returns>
        public List<CustomerInfo> FindByName(string name)
        {
            return bll.FindByName(name);
        }
    }
}

3)增加WCF的接口调用层实现

基于WCF的实现,就是根据接口封装对WCF服务层的调用,BaseWCFService基类,可以看成是具有常规增删改查等等的基础性API,是基于泛型的强类型接口基类。

namespace WHC.TestProject.ServiceCaller
{
    /// <summary>
    /// 基于WCF服务的Facade接口实现类
    /// </summary>
    public class CustomerCaller : BaseWCFService<CustomerInfo>, ICustomerService
    {
        public CustomerCaller()  : base()
        {
            this.configurationPath = EndPointConfig.WcfConfig; //WCF配置文件
            this.endpointConfigurationName = EndPointConfig.CustomerService;
        }

        /// <summary>
        /// 子类构造一个IChannel对象转换为基类接口,方便给基类进行调用通用的API
        /// </summary>
        /// <returns></returns>
        protected override IBaseService<CustomerInfo> CreateClient()
        {
            return CreateSubClient();
        }

        /// <summary>
        /// 创建一个强类型接口对象,供本地调用
        /// </summary>
        /// <returns></returns>
        private ICustomerService CreateSubClient()
        {
            CustomClientChannel<ICustomerService> factory = new CustomClientChannel<ICustomerService>(endpointConfigurationName, configurationPath);
            return factory.CreateChannel();
        }

        /// <summary>
        /// 根据客户名称获取客户列表
        /// </summary>
        /// <param name="name">客户名称</param>
        /// <returns></returns>
        public List<CustomerInfo> FindByName(string name)
        {
            List<CustomerInfo> result = new List<CustomerInfo>();

            ICustomerService service = CreateSubClient();
            ICommunicationObject comm = service as ICommunicationObject;
            comm.Using(client =>
            {
                result = service.FindByName(name);
            });

            return result;
        }
    }
}

由于WCF的接口封装层相对内容比较复杂一些,这里介绍一下。

构造函数通过代码指定具体的配置文件:this.configurationPath = EndPointConfig.WcfConfig; //WCF配置文件

并通过代码指定具体的WCFEndPoint节点名称:this.endpointConfigurationName = EndPointConfig.CustomerService;

构造WCF服务的代理类,我们通过CustomClientChannel的辅助方法,传入配置文件和配置节点名称,使得它能顺利通过函数 CreateSubClient 构造出一个对应类型的WCF代理类。

            CustomClientChannel<ICustomerService> factory = new CustomClientChannel<ICustomerService>(endpointConfigurationName, configurationPath);
            return factory.CreateChannel();

每次调用WCF服务类接口的时候,我们就使用创建的代理类进行调用,调用操作如下所示。

            ICustomerService service = CreateSubClient();
            ICommunicationObject comm = service as ICommunicationObject;
            comm.Using(client =>
            {
                result = service.FindByName(name);
            });

4)增加WCF服务逻辑层的实现

我们通过上面的代码可以了解到,已经创建了Winform的调用层、WCF服务的调用层,但是这里,我们对WCF服务还没有实现,这样我们就需要实现WCF服务层的内容了,否则程序试用WCF方式访问的时候,就找不到这个FindByName的接口实现了。

我们看看WCF服务层里面,看看具体如何实现,双击打开里面的CustomerService.Svc看到只是一个服务的声明,没有任何背后的代码逻辑。

因为为了便于管理,WCF服务一般是定义和具体的实现是分开的,这样就引入了一个WCF服务逻辑层的概念。

这样它的接口实现,就放在了WHC.TestProject.WCFLibrary项目里面了,WCF服务逻辑层的接口调用封装如下所示。这里我们看到,他和Winform的调用逻辑几乎一样,只是他们的类名称不同而已。

namespace WHC.TestProject.WCFLibrary
{
    /// <summary>
    /// 基于WCFLibrary的Customer对象调用类
    /// </summary>
    public class CustomerService : BaseLocalService<CustomerInfo>, ICustomerService
    {
        private Customer bll = null;

        public CustomerService() : base(BLLFactory<Customer>.Instance)
        {
            bll = baseBLL as Customer;
        }

        /// <summary>
        /// 根据客户名称获取客户列表
        /// </summary>
        /// <param name="name">客户名称</param>
        /// <returns></returns>
        public List<CustomerInfo> FindByName(string name)
        {
            return bll.FindByName(name);
        }
    }
}

5)界面层的调用操作 

 界面层的调用操作代码如下所示。

string name = "张"
List<CustomerInfo> list= CallerFactory<ICustomerService>.Instance.FindByName(name)

 这个操作模式,和普通使用BLLFactory的方式非常相似的。

5、混合式框架的业务模块组成

混合型框架可以看成是Winform框架高级版本,除了它本身是一个完整的业务系统外,它外围的所有辅助性模块均(如通用权限、通用字典、通用附件管理、通用人员管理。。。。)都实现了这种混合型的框架,因此使用非常方便,整个框架如果简化来看,就是在原有的Winform界面层,用接口调用方式,避免和业务逻辑类的紧耦合关系。由于他是通过接口方式的调用方式,它本身又可以通过配置指定指向WCF的实现,因此也囊括了WCF框架的一切特点。

虽然整体性的混合型框架比其他两种框架模块,总体增加了一些难度及复杂性,不过,为了使得整个混合型框架开发和使用更加方便,我已经在设计上做了很多相关的工作,力求更好、更高效的使用好这种混合型框架,下面是我对整体性的框架做了的优化改进工作。

1)把所有通用的模块开发好,方便更好的集成使用,更加高效利用通用模块,重复利用度更高;

2)把WCF服务发布和服务逻辑分开,更好管理和发布WCF服务,服务发布只需要svc文件,不含任何后台代码;

3)统一的业务调用规则和命名规则,所有模块的接口调用统一为CallerFactory<I***Service>方式,通用模块和框架的命名规则和机制完全一样。

4)WCF服务配置文件分离,通用性的辅助模块的配置文件为BaseWcfConfig.config,业务系统的WCF配置文件为WcfConfig.config,配置文件分离更方便管理和维护,减少主配置文件app.Config的复杂性。

5)最后一条,也是最重要的一条,就是代码生成工具Database2Sharp的同步支持。通过代码生成工具,更好、更快的生成整个混合性框架的代码和项目工程,一键解决所有的烦恼。Winform界面,利用代码生成工具Database2Sharp进行生成,然后在项目中整合即可。

循序渐进开发WInform项目--系列文章导引:

循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

循序渐进开发WinForm项目(4)--Winform界面模块的集成使用

循序渐进开发WinForm项目(3)--Winform界面层的项目设计

循序渐进开发WinForm项目(2)--项目代码的分析

循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

本文转自博客园伍华聪的博客,原文链接:循序渐进开发WinForm项目(6)--开发使用混合式Winform模块,如需转载请自行联系原博主。

时间: 2024-10-18 07:14:02

循序渐进开发WinForm项目(6)--开发使用混合式Winform模块的相关文章

循序渐进开发WinForm项目(2) 项目代码的分析

在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资 料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经 形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计 的规则不甚了解,开始可能也是一头雾水. 本篇继续上一篇<循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成>

从拼死拼活开发软件项目到远程遥控管理

现在想想开发软件都有整整12年以上了人生最美好的时光都用在这个上了,在这期间有不少酸甜苦辣,有时候真不好意思说自己是35岁的老程序员了,有尝到过创业失败的滋味,有过人生的困难时期,多少遇到了很多贵人相助,日子就一天比一天好起来了.其实每天怀着感恩的心里,生活就一天比一天好,心态也会越来越健康了. AD: 交流很重要,沟通无极限 现在想想开发软件都有整整12年以上了人生最美好的时光都用在这个上了,在这期间有不少酸甜苦辣,有时候真不好意思说自己是35岁的老程序员了,有尝到过创业失败的滋味,有过人生的

循序渐进开发WinForm项目(1) 数据库设计和项目框架的生成

在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资 料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经 形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计 的规则不甚了解,开始可能也是一头雾水. 本篇想作为我的<循序渐进开发WinForm项目>系列的开篇,主要介绍数据库设计方面注

循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水. 本篇想作为我的<循序渐进开发WinForm项目>系列的开篇,主要介绍数据库设计方

循序渐进开发WinForm项目(4)--Winform界面模块的集成使用

随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水. 本篇继续上一篇<循序渐进开发WinForm项目(3)--Winform界面层的项目

循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水. 本篇继续上一篇<循序渐进开发WinForm项目(4)--Winform界面模块的集

循序渐进开发WinForm项目(3)--Winform界面层的项目设计

随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了.反过来,如果我们切换到其他领域,如IOS.android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水. 本篇继续上一篇<循序渐进开发WinForm项目(2)--项目代码的分析>,继续介

新手开发!项目开发遇到问题。!求助!

问题描述 刚上手接触项目中一个模块,忘高手指教求助!!项目介绍:这是一个活动考勤页面,当单击"活动考勤"button的时候,出现winform窗体,里面有考勤模块,考勤结束后,数据提交!这里要问的是1:怎么将活动信息传值到这个winform页面:2:怎么生成这个winform页面,(是不是一个exe文件?)3:怎么将数据导到数据库希望大家给我点思路或者这个方面的资料的链接地址 解决方案 解决方案二:该回复于2012-03-05 10:07:03被版主删除解决方案三:????网页中打开W

技巧应用:怎样提高J2EE项目的开发速度

j2ee|技巧|速度|项目 在J2EE技术体系中,往往被灌输了太多容器的概念,什么EJB容器.Servlet容器等等,而开发过程也在开发.配置.部署之间迭代与反复:如此一来常会出现令人尴尬的状况:往往花几分钟时间去改一个Bug.却要再花双倍或者更多时间去部署和测试,开发工程师们不得不中断思路,看着服务器如蜗牛般启动,并在开发工具和部署工具之间来回切换. 事实上,配置也好.部署也罢,都是开发过程中一个必不可少的阶段.如何通过集成式的开发环境将这些开发阶段有机集成在一起,是摆在我们面前的迫切需要.在