回《【开源】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框架控制器设计图
如上图,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 }