十八、EnterpriseFrameWork框架核心类库之Winform控制器

回《【开源】EnterpriseFrameWork框架系列文章索引

EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U

EFW框架中的WinController控制器可以说是整个Winform版中最具有价值的地方,能够熟练使用它的话,可以让你写得代码结构清晰不知多少倍,真正的做到了CS开发的界面层与逻辑层的完全隔离;更重要的是改变了你写界面代码的思维,让你一次性写出功能完善的代码,真的,传统的那种事件驱动的方式编码会让你的代码变得越来越臃肿,就算你懂得不断重构你的代码,也完全避免不了出现臃肿的情况;所以必须使用WinController控制器模式从源头彻底解决这种问题;

WinController控制器与界面不一定是一一对应的,一个控制器可以对应多个界面,当几个界面的操作十分密切时就可以用一个控制器来控制它们的行为;一个界面对应多个控制器这种方式最好不要这么做,这样会让你的程序变得复杂,也破坏了业务架构与框架之间的关系,参考第十一章《EnterpriseFrameWork框架的分层与系统业务的结合》。

本章主要内容通过解读框架源代码来学习WinController是怎么实现的,以及学习控制器这种设计模式;

本文要点:

1.如何使用Winform控制器

2.Winform控制器的设计思路

3.Winform控制器BaseController基类的实现代码

4.Winform控制器的自定义标签MenuAttribute和ViewAttribute

5.通过Winform控制器打开界面

Winform控制器源代码目录结构

EFW框架控制器设计图

1.如何使用Winform控制器

如上图,Books.Winform项目里的是界面文件,Books项目的是界面接口文件和控制器文件,frmBookManager对象继承IfrmBook接口,bookwinController对象依IfrmBook接口;

见上图,Books实例中保存数据功能代码调用流程,界面代码frmBookManager继承了IfrmBook接口的两个方法并实现,点击保存按钮,btnsave_Click事件内并不实现保存数据的代码而只是向控制器发送一个消息,指定需要调用的方法名称bookSave,程序开始执行控制器中的bookSave方法,利用接口属性frmBook.currBook从界面获取数据,并利用框架中的ORM保存到数据库;接着调用GetBooks方法将数据显示在界面上;GetBooks方法调用后台的IBookDao对象获取Book数据,再通过frmBook.loadbooks(dt)接口方法将数据绑定到界面控件gridBook上;

2.Winform控制器的设计思路

Winform控制器的设计思路有点类似Web系统中的MVC模式,控制器处理这后台数据对象与前台界面直接的交互,利用接口从界面获取数据,再传递给后台对象处理,处理完后再利用接口将数据传递给界面控件显示;整个交互的逻辑代码是在控制器中实现的,数据怎么从界面获取与数据怎么绑定到界面控件都是在前端界面接口中实现的,而数据怎么存储到数据库与怎么从数据库获取数据都是在后端Dao或ObjectModel中实现的,当然也可以在控制器中利用oleDb直接操作数据库,但好的程序结构还是放在Dao和ObjectModel中合适些;

Winform控制器必须继承框架中的BaseController对象,还有控制器类名上要指定菜单标签MenuAttribute和界面标签ViewAttribute,BaseController对象封装了控制器的一些处理功能,MenuAttribute和ViewAttribute一个对应系统的菜单名,一个决定控制器能操作的界面对象;

3.Winform控制器BaseController基类的实现代码

因为所有Winform控制器都必须继承BaseController基类,所以我们有必要先看一下BaseController基类的代码是怎么样的;

BaseController文件

  1 /// <summary>
  2     /// Winform控制器基类
  3     /// </summary>
  4     public abstract class BaseController : AbstractBusines
  5     {
  6         public AbstractDatabase oleDb
  7         {
  8             get
  9             {
 10                 return _oleDb;
 11             }
 12         }
 13
 14         public SysLoginRight GetSysLoginRight
 15         {
 16             get
 17             {
 18                 if (EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser") != null)
 19                 {
 20                     return (SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser");
 21                 }
 22                 else
 23                 {
 24                     return new SysLoginRight();
 25                 }
 26             }
 27         }
 28
 29         internal IBaseView _defaultView;
 30
 31         public IBaseView DefaultView
 32         {
 33             get { return _defaultView; }
 34         }
 35
 36         private Dictionary<string, IBaseView> _iBaseView;
 37         public Dictionary<string, IBaseView> iBaseView
 38         {
 39             get { return _iBaseView; }
 40             set
 41             {
 42                 _iBaseView = value;
 43                 foreach (KeyValuePair<string, IBaseView> val in _iBaseView)
 44                 {
 45                     //val.Value.ControllerEvent += new ControllerEventHandler(UI_ControllerEvent);
 46                     val.Value.InvokeController = new ControllerEventHandler(UI_ControllerEvent);
 47                 }
 48             }
 49         }
 50
 51         public CloseTab closeTab;
 52
 53         /// <summary>
 54         /// 创建BaseController的实例
 55         /// </summary>
 56         public BaseController()
 57         {
 58
 59         }
 60         /// <summary>
 61         /// 界面控制事件
 62         /// </summary>
 63         /// <param name="eventname">事件名称</param>
 64         /// <param name="objs">参数数组</param>
 65         /// <returns></returns>
 66         public virtual object UI_ControllerEvent(string eventname, params object[] objs)
 67         {
 68             switch (eventname)
 69             {
 70                 case "Close":
 71                     if (closeTab != null)
 72                         closeTab();
 73                     break;
 74                 case "this":
 75                     return this;
 76             }
 77
 78             MethodInfo meth = this.GetType().GetMethod(eventname);
 79             if (meth != null)
 80             {
 81                 MethodAttribute[] WinM = (MethodAttribute[])meth.GetCustomAttributes(typeof(MethodAttribute), true);
 82                 if (WinM.Length > 0)
 83                 {
 84                     if (WinM[0].OpenDBKeys != null && WinM[0].OpenDBKeys.ToString().Trim() != "")
 85                     {
 86                         List<string> dbkeys = WinM[0].OpenDBKeys.Split(new char[] { ‘,‘ }).ToList();
 87                         this.BindMoreDb(oleDb, "default");
 88                         foreach (string dbkey in dbkeys)
 89                         {
 90                             EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase _Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase(dbkey);
 91                             _Rdb.WorkId = GetSysLoginRight.WorkId;
 92                             //创建数据库连接
 93                             this.BindMoreDb(_Rdb, dbkey);
 94                         }
 95                     }
 96                 }
 97                 return meth.Invoke(this, objs);
 98             }
 99             return null;
100         }
101
102         /// <summary>
103         /// 初始化全局web服务参数对象
104         /// </summary>
105         public virtual void Init() { }
106
107         public virtual IBaseView GetView(string frmName)
108         {
109             return iBaseView[frmName];
110         }
111     }

BaseController基类封装了控制器的四方面的功能:

1)数据库操作对象oleDb,这样我们可以直接在控制器方法内使用它执行SQL语句操作数据库

2)系统登录后的用户信息GetSysLoginRight,这样我们可以再控制器中很方便的使用当前登录的用户信息;

3)界面对象字典iBaseView,这属性与控制器上ViewAttribute标签配置相对应,可以从中取出配置的界面接口对象来操作界面;

4)处理界面请求控制器方法的功能UI_ControllerEvent,界面使用InvokeController向控制器发送消息,而怎么效应界面的消息在此方法中实现的,利用反射机制执行对应的控制器方法;

4.Winform控制器的自定义标签MenuAttribute和ViewAttribute

这里的设计是这样的,一个控制器可以配置多个MenuAttribute,那么系统可以挂多个菜单,而这几个菜单都是公用这一个控制器,同样一个控制器可以配置多个ViewAttribute,控制器就可以同时操作这些配置的界面;

MenuAttribute文件

 1   [AttributeUsageAttribute(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
 2     public class MenuAttribute:Attribute
 3     {
 4
 5         string _defaultName;
 6
 7         /// <summary>
 8         /// 菜单名称
 9         /// </summary>
10         public string DefaultName
11         {
12             get { return _defaultName; }
13             set { _defaultName = value; }
14         }
15
16         private string _defaultViewName;
17         /// <summary>
18         /// 菜单对应打开界面
19         /// </summary>
20         public string DefaultViewName
21         {
22             get { return _defaultViewName; }
23             set { _defaultViewName = value; }
24         }
25
26         string _memo;
27         public string Memo
28         {
29             get { return _memo; }
30             set { _memo = value; }
31         }
32
33         public MenuAttribute()
34         {
35         }
36
37         public MenuAttribute(string defaultName,string memo)
38         {
39             this._defaultName = defaultName;
40             this._memo = memo;
41         }
42     }

ViewAttribute文件

 1 [AttributeUsageAttribute(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
 2     public class ViewAttribute:Attribute
 3     {
 4         private string _name;
 5         /// <summary>
 6         /// 界面名称
 7         /// </summary>
 8         public string Name
 9         {
10             get { return _name; }
11             set { _name = value; }
12         }
13
14         private bool _defaultShow;
15         public bool DefaultView
16         {
17             get { return _defaultShow; }
18             set { _defaultShow = value; }
19         }
20
21         private Type _viewType;
22         /// <summary>
23         /// 界面对象类型
24         /// </summary>
25         public Type ViewType
26         {
27             get { return _viewType; }
28             set { _viewType = value; }
29         }
30
31         private string _dllName;
32         /// <summary>
33         /// 界面存放的DLL
34         /// </summary>
35         public string DllName
36         {
37             get { return _dllName; }
38             set { _dllName = value; }
39         }
40
41         private string _viewTypeName;
42         /// <summary>
43         /// 界面类型名称
44         /// </summary>
45         public string ViewTypeName
46         {
47             get { return _viewTypeName; }
48             set { _viewTypeName = value; }
49         }
50
51         string _memo;
52         public string Memo
53         {
54             get { return _memo; }
55             set { _memo = value; }
56         }
57     }

5.通过Winform控制器打开界面

Winform系统打开一个界面是这样操作的,用户点击系统主界面上的菜单,框架就会调用WinformViewCreator对象来实例化控制器对象和实例化控制器配置的所有界面窗体对象,所以我们有必要看一下WinformViewCreator对象是怎么实现的;

WinformViewCreator文件

 1  public override Object InstanceController(CloseTab close)
 2         {
 3             try
 4             {
 5
 6                 //加载类库
 7                 Assembly assembly = null;
 8                 assembly = Assembly.LoadFrom(AppGlobal.AppRootPath + "\\" + dllfile);
 9
10                 //获得控制器类(型)
11                 Type type = assembly.GetType(controllername, false, true);
12
13                 MenuAttribute[] menuAttribute = (MenuAttribute[])type.GetCustomAttributes(typeof(MenuAttribute), true);
14                 ViewAttribute[] viewAttribute = (ViewAttribute[])type.GetCustomAttributes(typeof(ViewAttribute), true);
15                 //ServiceAttribute[] serviceAttribute = (ServiceAttribute[])type.GetCustomAttributes(typeof(ServiceAttribute), true);
16
17                 if (menuAttribute.Length > 0)
18                 {
19                     Dictionary<string, IBaseView> viewDic = new Dictionary<string, IBaseView>();
20                     //Dictionary<string, SoapHttpClientProtocol> serviceDic = new Dictionary<string, SoapHttpClientProtocol>();
21                     BaseController controller = (BaseController)System.Activator.CreateInstance(type);
22
23                     EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase();
24                     Rdb.WorkId = controller.GetSysLoginRight.WorkId;
25                     controller.BindDb(Rdb, AppGlobal.container);
26
27                     controller.closeTab = close;//关闭窗口
28
29                     for (int index = 0; index < viewAttribute.Length; index++)
30                     {
31                         if (viewAttribute[index].ViewType == null)
32                         {
33                             if (string.IsNullOrEmpty(viewAttribute[index].DllName))
34                             {
35                                 continue;
36                             }
37                             Assembly _assembly = Assembly.LoadFrom(AppGlobal.AppRootPath + "\\" + viewAttribute[index].DllName);
38                             viewAttribute[index].ViewType = _assembly.GetType(viewAttribute[index].ViewTypeName, false, true);
39                         }
40                         IBaseView view = (IBaseView)System.Activator.CreateInstance(viewAttribute[index].ViewType);
41                         if (viewAttribute[index].DefaultView) controller._defaultView = view;
42                         if (index == 0 && viewAttribute.ToList().FindIndex(x => x.DefaultView == true) == -1) controller._defaultView = view;
43                         viewDic.Add(viewAttribute[index].ViewType.Name, view);
44                     }
45                     //for (int index = 0; index < serviceAttribute.Length; index++)
46                     //{
47                     //    SoapHttpClientProtocol service = (SoapHttpClientProtocol)System.Activator.CreateInstance(serviceAttribute[index].ServiceType);
48                     //    serviceDic.Add(serviceAttribute[index].ServiceType.Name, service);
49                     //}
50
51                     controller.iBaseView = viewDic;
52                     //controller.service = serviceDic;
53
54                     controller.Init();//初始化
55                     return controller;
56                 }
57
58                 return null;
59             }
60             catch (Exception err)
61             {
62                 throw err;
63             }
64         }

上面代码中有两点需要说明一下,首先根据菜单配置的控制器名称通过反射实例化控制器对象;

接着根据控制器的配置的ViewAttribute标签,实例化界面对接并添加到iBaseView属性中;

时间: 2024-08-02 02:49:25

十八、EnterpriseFrameWork框架核心类库之Winform控制器的相关文章

十七、EnterpriseFrameWork框架核心类库之Web控制器

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WebController就是解决JqueryEasyUI与逻辑层的交互,之间的数据是通过Json字符串来传递:值得注意的是WebController的代码一定不要和EFWWeb项目放在一起,你可以单独建一个项目类库,也可以和逻辑层项目放一起:在EFWWeb项目不要编写任何C#代码,这个在前面的文章中就提过,可以让你的Web项

十二、EnterpriseFrameWork框架核心类库之与EntLib结合

从本章开始对框架的讲叙开始进入核心类库的讲解,前面都是对框架外在功能讲解,让人有个整体的概念,知道包含哪些功能与对系统开发有什么帮助.以后多章都是讲解核心类库的,讲解的方式基本按照代码的目录结构,这样阅读代码的时候也可以针对性看:还有就是为了更好理解文章中的内容把目前还不够完善的源代码发布,这个版本Winform部分基本可以直接运行,而Web部分与WCF部分的控制器代码没有完成,所以暂时还运行不起来,不过这并不影响学习核心类库,再就是尽快在下个版本发布一个完整版本给大家: EnterpriseF

十六、【适合中小企业的.Net轻量级开源框架】EnterpriseFrameWork框架核心类库之单点登录SSO

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 如上图,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录:根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返

十九、【.Net开源】EFW框架核心类库之WCF控制器

回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa 只有当你需要开发三层架构的系统并利用WCF作为系统的中间件,那么就需要使用WCF控制器.EFW框架中的Wcf控制器分为两个部分WcfClientController和WcfController,两者利用Wcf服务进行通讯,其中WcfClientController的功能与上章

十五、EnterpriseFrameWork框架核心类库之系统启动入口与初始化

本章内容是讲三种开发模式,web模式.Winform模式和Wcf模式的系统启动入口有什么区别,以及启动后系统初始化的内容:为什么要把这些单独提出来讲一章,因为我觉得本章非常重要,我们都知道程序中的main()函数,称之为主函数,是所有程序运行的入口:当你拿着一个程序肯定是从这个函数开始阅读,慢慢的深入了解整个程序的运行流程:而光看那些功能代码块是掌握不了系统运行时的一些机制的: 只有掌握本章的内容后,那么在以后项目中遇到的问题基本上都能直接定位,并找到产生的原因,不然你会觉得所有产生的问题都莫名

十四、EnterpriseFrameWork框架核心类库之简易ORM

在写本章前先去网上找了一下关于ORM的相关资料,以为本章做准备,发现很多东西今天才了解,所以在这里也对ORM做不了太深入的分析,但还是浅谈一下EFW框架中的设计的简易ORM:文中有一点讲得很有道理,Dao与ORM的区别,Dao是对数据库操作的封装,编写的代码方式像一种设计方法,而ORM支持对象与数据结构的映射,更像一种代码开发工具,有了这个工具会让我们开发代码更简单方便:但是同一类工具有简单的也有复杂的,比如文字工具有简单的Notepad,也有复杂的Word,不是说有了复杂的简单的工具就不需要了

十三、EnterpriseFrameWork框架核心类库之数据库操作(多数据库事务处理)

本章介绍框架中封装的数据库操作的一些功能,在实现的过程中费了不少心思,针对不同数据库的操作(SQLServer.Oracle.DB2)这方面还是比较简单的,用工厂模式就能很好解决,反而是在多数据库同时操作方面走了不少弯路:现在从以下几个方面进行说明: 一.不同数据库操作 此处用到了工厂模式来实现不同数据库操作,看下图 AbstractDatabase是一个抽象类,定义了所有对数据库的操作抽象方法,包括执行一个SQL语句.执行存储过程.事务操作等 [Serializable] public abs

十、EnterpriseFrameWork框架的分层架构及意义(控制器、业务对象、实体、Dao之间关系)

本章内容主要包括两个方面,一是框架分层(控制器.业务对象.实体.Dao)的详细说明,二是对比常用三层结构的区别和优势: 我们先看一下前面实例中的解决方案目录: 我们再看各层之间的调用关系: 上图描叙的控制器有四种方式来操作数据库, 1)控制器调用实体,通过框架中的ORM来实现单表的操作 2)控制器直接操作数据库对象(oleDB),通过编写SQL语句访问数据库 3)控制器通过调用Dao操作数据库 4)控制器调用业务对象,业务对象再调用Dao操作数据库 还有就是每一层在程序结构中承担的角色: 一.D

二十、【.Net开源】EFW框架核心类库之WebService服务

回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa EFW框架中的WebService服务开发方式与传统的net项目中开发不太一样,传统的开发方式虽然也挺简单但在后面的发布部署还是挺麻烦的,而在EFW框架中开发Webservice就跟编写普通的C#代码一样,并不需要单独建WebService服务项目,不需要Asmx文件:所以发