本章內容是講三種開發模式,web模式、Winform模式和Wcf模式的系統啓動入口有什麼區別,以及啓動後系統初始化的內容;爲何要把這些單獨提出來說一章,由於我以爲本章很是重要,咱們都知道程序中的main()函數,稱之爲主函數,是全部程序運行的入口;當你拿着一個程序確定是從這個函數開始閱讀,慢慢的深刻了解整個程序的運行流程;而光看那些功能代碼塊是掌握不了系統運行時的一些機制的;javascript
只有掌握本章的內容後,那麼在之後項目中遇到的問題基本上都能直接定位,並找到產生的緣由,否則你會以爲全部產生的問題都莫名其妙,不知道從哪裏下手調試;項目中的配置文件也是在系統初始化中使用的,要了解配置的值到底有什麼做用也必須搞清楚系統初始化的過程,還有就是框架中的不少設計思想就是基於此處產生的,最典型的就是控制器的設計,爲何控制器要如此設計,看完後應該會深有體會;html
接下來我就分別對框架中的幾種模式的系統啓動入口進行講解:前端
1.Web版系統啓動入口java
2.Winform版系統啓動入口jquery
3.Wcf版系統啓動入口web
4.啓動後初始化內容數據庫
源代碼目錄結構:json
Web版是三層結構程序,但跟wcf版又不同,分爲瀏覽器、Web服務器和數據庫,全部代碼都是部署在Web服務器上的,Windows下的經常使用web服務器就是IIS了;Net下的web系統啓動入口一般都是使用Global.asax文件;是能夠把初始化代碼AppGlobal放在此文件中,可是框架爲何沒有這麼作,由於開始的設計就是在EFWWeb項目中是不能寫任何cs代碼的,想一想看若是EFWWeb項目沒有cs代碼,那麼就只有html代碼和javascript代碼,這樣EFWWeb項目就不須要編譯,要編譯的代碼都放在邏輯層項目中,咱們發佈就變得很是方便,只需拷貝更新邏輯層項目的dll和EFWWeb項目的aspx文件和js文件;若是隻修改了界面那編譯都不用了;瀏覽器
那麼啓動入口不在Global.asax文件中那又在哪了,框架利用了httpModules來實現;先看AppGlobalHttpModule對象的代碼,繼承net框架中的IHttpModule接口,在實現的Init方法中經過context.BeginRequest事件調用了AppGlobal.AppStart方法實現系統初始化;緩存
1 /// <summary> 2 /// web系統啓動調用此對象 3 /// </summary> 4 public class AppGlobalHttpModule : IHttpModule 5 { 6 7 #region IHttpModule 成員 8 9 public void Dispose() 10 { 11 AppGlobal.AppEnd(); 12 } 13 private HttpApplication _context; 14 public void Init(HttpApplication context) 15 { 16 _context = context; 17 context.BeginRequest += new EventHandler(context_BeginRequest); 18 } 19 20 void context_BeginRequest(object sender, EventArgs e) 21 { 22 AppGlobal.AppRootPath = _context.Server.MapPath("~/"); 23 AppGlobal.AppStart(AppGlobalType.Web); 24 } 25 26 #endregion 27 }
在Web.config配置文件中須要對AppGlobalHttpModule 對象進行配置;
Web版系統就是利用httpModules來實現的,再討論一下頁面想後臺控制器進行Http請求的的流程;以下圖,界面javascript代碼利用jquery中的Ajax功能向Web服務器發送請求,Url地址指定控制器的名稱和控制器方法名稱;
Web服務器利用httpHandlers來接收前端的全部請求,看一下APIHttpHandler的代碼,繼承net框架中的IHttpHandler接口,在實現接口的ProcessRequest方法中根據url中的控制器名稱和方法名稱,利用反射機制建立Web控制器,並執行控制器中的方法返回結果輸出到頁面;
1 /// <summary> 2 /// Http請求處理對象 3 /// </summary> 4 public class APIHttpHandler : IHttpHandler, IRequiresSessionState 5 { 6 /// <summary> 7 /// 您將須要在您網站的 web.config 文件中配置此處理程序, 8 /// 並向 IIS 註冊此處理程序,而後才能進行使用。有關詳細信息, 9 /// 請參見下面的連接: http://go.microsoft.com/?linkid=8101007 10 /// </summary> 11 #region IHttpHandler Members 12 13 public void ProcessRequest(HttpContext context) 14 { 15 16 try 17 { 18 if (AppGlobal.IsRun == false) throw new Exception("系統未正常啓動!"); 19 string sController = context.Request["controller"].ToString().Trim(); 20 string sMothod = context.Request["method"].ToString().Trim(); 21 22 23 if (!String.IsNullOrEmpty(sController) && !String.IsNullOrEmpty(sMothod)) 24 { 25 26 CmdInvoke(context, sController, sMothod); 27 } 28 else 29 { 30 context.Response.Write("error");//命令錯誤 31 } 32 } 33 catch (Exception err) 34 { 35 context.Response.Write("exception");//執行異常 36 //記錄錯誤日誌 37 ZhyContainer.CreateException().HandleException(err, "HISPolicy"); 38 } 39 finally 40 { 41 context.Response.End(); 42 } 43 } 44 45 public bool IsReusable 46 { 47 get 48 { 49 return false; 50 } 51 } 52 53 #endregion 54 55 private void CmdInvoke(HttpContext context, string sController, string sMothod) 56 { 57 List<Cmd_Controller> cmd = (List<Cmd_Controller>)AppGlobal.cache.GetData("cmdWebController"); 58 59 Cmd_Controller cmdC = cmd.Find(x => x.controllerName == sController); 60 if (cmdC != null) 61 { 62 Cmd_Method cmdM= cmdC.cmdMethod.Find(x => x.methodName == sMothod); 63 if (cmdM != null) 64 { 65 if (System.Configuration.ConfigurationManager.AppSettings["TurnOnLoginRight"] == "true" && cmdC.webController.GetSysLoginRight.UserId == 0) 66 { 67 context.Response.Write("nologin");//沒登錄 68 } 69 else 70 { 71 //每次請求控制器必須建立一個新的數據庫連接 72 //if (cmdC.webController.GetDb() == null) 73 //{ 74 EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase(); 75 Rdb.WorkId = cmdC.webController.GetSysLoginRight.WorkId; 76 //建立數據庫鏈接 77 cmdC.webController.BindDb(Rdb, AppGlobal.container); 78 79 if (cmdM.dbkeys != null && cmdM.dbkeys.Count > 0) 80 { 81 cmdC.webController.BindMoreDb(Rdb, "default"); 82 foreach (string dbkey in cmdM.dbkeys) 83 { 84 EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase _Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase(dbkey); 85 _Rdb.WorkId = cmdC.webController.GetSysLoginRight.WorkId; 86 //建立數據庫鏈接 87 cmdC.webController.BindMoreDb(_Rdb,dbkey); 88 } 89 } 90 91 //} 92 BeginInvoke(context, cmdC.webController); 93 cmdM.methodInfo.Invoke(cmdC.webController, null); 94 EndInvoke(context, cmdC.webController); 95 } 96 } 97 else 98 { 99 context.Response.Write("error");//命令錯誤 100 } 101 } 102 else 103 { 104 context.Response.Write("error");//命令錯誤 105 } 106 }
在Web.Config配置文件中須要對APIHttpHandler對象進行配置
總結一下,Web版頁面調用後臺控制器的過程,利用Ajax發送Http請求被APIHttpHandler對象接收,APIHttpHandler對象解析Http請求經過反射建立控制器對象並執行方法,最後講結果用Json格式輸出到頁面;
相關資料:
關於HttpHandlers和HttpModules的不一樣
http://www.cnblogs.com/ricksun/articles/1545491.html
httpModules 與 httpHandlers
http://www.cnblogs.com/chenlulouis/archive/2009/12/18/1626918.html
Winform版是一個兩層結構的程序,客戶端和服務端,服務端就是數據庫,每個客戶端運行都是獨立的程序運行環境,Winform版客戶端就是一個Windows窗體應用程序,因此咱們直接找啓動項目的Program類的Main函數;
上面AppGlobal_Init()是經過界面FrmSplash用委託的方式調用的,這是因爲系統作初始化的時候須要必定時間,爲了讓用戶以爲程序正在運行,顯示一個正在加載的界面效果比較好;咱們接着看AppGlobal_Init()函數代碼,這裏會讀配置文件中值,進行判斷是Winform仍是WCFClient方式,本節先說Winform方式,先執行AppGlobal.AppStart(AppGlobalType.Winform)進行系統初始化,AppGlobal對象封裝了全部模式的初始化代碼;
到此Winform版的初始化入口就講完了,AppGlobal對象最後一節咱們再看;Winform版是三種模式中相對最容易看懂的了;
另外再講一下Winform版的操做請求流程,系統登陸進入菜單主界面後,點擊菜單按鈕就會打開窗體界面,咱們講講這個過程的實現代碼。
先找到按鈕的點擊事件,從菜單的Tag對象獲取菜單的配置信息,最後調用ShowForm(winmenu)方法;
1 //點擊菜單 2 void btnmenu_Click(object sender, EventArgs e) 3 { 4 btnImage = sender; 5 BaseItem baseItem = sender as BaseItem; 6 7 if (baseItem.Tag.ToString() != "" && baseItem.Tag.GetType() != typeof(BaseModule)) 8 { 9 BaseMenu menu = (BaseMenu)baseItem.Tag; 10 11 WinMenu winmenu = new WinMenu(); 12 if (Program.clienttype == "Winform") 13 { 14 winmenu.DllName = menu.DllName; 15 winmenu.FunName = menu.FunName; 16 } 17 else if (Program.clienttype == "WCFClient") 18 { 19 string[] names = menu.FunWcfName.Split(new char[] { '@' }); 20 if (names.Length == 2) 21 { 22 winmenu.DllName = names[0]; 23 winmenu.FunName = names[1]; 24 } 25 } 26 else if (Program.clienttype == "WEBClient") 27 { 28 winmenu.DllName = ""; 29 winmenu.FunName = ""; 30 } 31 32 //winmenu.DllName = menu.DllName; 33 //winmenu.FunName = menu.FunName; 34 winmenu.IsOutlookBar = menu.MenuLookBar; 35 winmenu.IsToolBar = menu.MenuToolBar; 36 winmenu.Memo = menu.Memo; 37 winmenu.MenuId = menu.MenuId; 38 winmenu.ModuleId = menu.ModuleId; 39 winmenu.Name = menu.Name; 40 winmenu.PMenuId = menu.PMenuId; 41 winmenu.SortId = menu.SortId; 42 winmenu.UrlPath = System.Configuration.ConfigurationSettings.AppSettings["WEB_serverUrl"] + menu.UrlName; 43 44 ShowForm(winmenu); 45 } 46 }
打開ShowForm()方法的代碼,這段代碼的意思就是找到須要打開的界面Form對象,在顯示在主界面的Tab中;其中BaseController basec = ControllerCreatorFactory.ControllerCreator(menu, delegateCloseTable)是本段代碼的重點,調用此方法建立控制器對象,並獲取控制器包含的界面Form;
1 public void ShowForm(WinMenu menu) 2 { 3 int index = this.barMainContainer.Items.IndexOf(menu.MenuId.ToString()); 4 if (index < 0) 5 { 6 if (string.IsNullOrEmpty(menu.FunName) == false || string.IsNullOrEmpty(menu.UrlPath) == false) 7 { 8 #region winform界面 9 List<DockContainerItem> listitem = new List<DockContainerItem>(); 10 11 CloseTab delegateCloseTable = delegate() 12 { 13 foreach (DockContainerItem item in listitem) 14 barMainContainer.CloseDockTab(item); 15 }; 16 17 18 19 Form form = null; 20 if (Program.clienttype == "Winform") 21 { 22 BaseController basec = ControllerCreatorFactory.ControllerCreator(menu, delegateCloseTable); 23 if (string.IsNullOrEmpty(menu.FunName) == false) 24 { 25 string[] funs = menu.FunName.Split(new char[] { '|' }); 26 if (funs.Length == 1) 27 form = (Form)basec.DefaultView; 28 else 29 form = (Form)basec.iBaseView[funs[1]]; 30 }else 31 form = (Form)basec.DefaultView; 32 } 33 else if (Program.clienttype == "WCFClient") 34 { 35 //string dllfile = menu.DllName; 36 //string controllername = menu.FunName.Split(new char[] { '|' })[0]; 37 BaseWCFClientController basec = ControllerCreatorFactory.WCFControllerCreator(menu, delegateCloseTable); 38 if (string.IsNullOrEmpty(menu.FunName) == false) 39 { 40 string[] funs = menu.FunName.Split(new char[] { '|' }); 41 if (funs.Length == 1) 42 form = (Form)basec.DefaultView; 43 else 44 form = (Form)basec.iBaseView[funs[1]]; 45 } 46 else 47 form = (Form)basec.DefaultView; 48 } 49 50 if (form != null) 51 { 52 barMainContainer.BeginInit(); 53 int displayWay = EFWCoreLib.WinformFrame.Common.CustomConfigManager.GetDisplayWay();//顯示方式 0 標準 1全屏 54 if (displayWay == 1) 55 form.Dock = DockStyle.Fill; 56 form.Size = new Size(1000, 600); 57 form.FormBorderStyle = FormBorderStyle.None; 58 form.TopLevel = false; 59 if (this.barMainContainer.Width > form.Width) 60 { 61 form.Location = new Point((barMainContainer.Width - form.Width) / 2, 0); 62 } 63 else 64 form.Location = new Point(0, 0); 65 form.Show(); 66 67 PanelDockContainer panelDockMain = new PanelDockContainer(); 68 panelDockMain.Dock = DockStyle.Fill; 69 panelDockMain.Controls.Add(form); 70 panelDockMain.Location = new System.Drawing.Point(3, 28); 71 panelDockMain.Style.Alignment = System.Drawing.StringAlignment.Center; 72 panelDockMain.Style.GradientAngle = 90; 73 panelDockMain.BackColor = Color.FromArgb(227, 239, 255); 74 panelDockMain.AutoScroll = true; 75 76 77 78 DockContainerItem item = new DockContainerItem(form.Text); 79 item.Text = menu.Name; 80 item.Name = menu.MenuId.ToString(); 81 item.Control = panelDockMain; 82 item.Visible = true; 83 item.Tag = form;//綁定界面對象 84 item.Image = GetButtonImage(btnImage); 85 86 item.VisibleChanged += new EventHandler(item_VisibleChanged); 87 //this.barMainContainer.Controls.Add(panelDockMain); 88 this.barMainContainer.Items.Add(item); 89 this.barMainContainer.SelectedDockContainerItem = item; 90 91 92 listitem.Add(item); 93 94 95 barMainContainer.EndInit(); 96 this.barMainContainer.Show(); 97 } 98 #endregion 99 } 100 } 101 else 102 { 103 this.barMainContainer.SelectedDockContainerItem = (DockContainerItem)this.barMainContainer.Items[index]; 104 string formname = ((DockContainerItem)this.barMainContainer.Items[index]).Tag.GetType().Name; 105 if (formname == "FrmWebBrowser") 106 { 107 EFWCoreLib.WinformFrame.WebBrowser.IfrmWebBrowserView webbrowser = (EFWCoreLib.WinformFrame.WebBrowser.IfrmWebBrowserView)((DockContainerItem)this.barMainContainer.Items[index]).Tag; 108 webbrowser.NavigateUrl();//從新加載網址 109 } 110 } 111 112 }
接着咱們將ControllerCreatorFactory建立控制器的工廠類,因此這裏使用了一個工廠模型用來建立不一樣的控制器,包含Winform界面控制器、WcfClient界面控制器和瀏覽器界面控制器;咱們這裏先看建立Winform界面控制器的實現方法InstanceController();此方法經過菜單配置的控制器名稱,利用反射機制找到控制器與控制器自定義標籤訂義的界面Form,這樣主界面就能夠顯示此界面Form在Tab頁中;
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 }
總結一下Winform版調用控制器的過程,點擊菜單按鈕根據菜單的配置信息,ViewCreator對象建立對應的控制器,顯示控制器自定義標籤包含的界面;接着界面能夠經過InvokeController方法執行控制器中的代碼;
Wcf版是三層結構的程序,包括客戶端、中間件和數據庫,其中客戶端的啓動入口與上面Winform版的差很少,實現的方式同樣的,用配置參數ClientType進行區分;重點講一下中間件WCFHosting服務主機的啓動入口;
查看WCFHosting程序點擊啓動按鈕的事件代碼,代碼打開一個WCF的ServiceHost,綁定WCFHandlerService對象;
1 private void StartAppHost() 2 { 3 Loader.hostwcfclientinfoList = new HostWCFClientInfoListHandler(BindGridClient); 4 Loader.hostwcfMsg = new HostWCFMsgHandler(AddMsg); 5 6 mAppHost = new ServiceHost(typeof(WCFHandlerService)); 7 8 ServiceMetadataBehavior smb = mAppHost.Description.Behaviors.Find<ServiceMetadataBehavior>(); 9 if (smb == null) 10 { 11 mAppHost.Description.Behaviors.Add(new ServiceMetadataBehavior()); 12 } 13 mAppHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); 14 15 mAppHost.Open(); 16 17 AddMsg(DateTime.Now, "WCF主機啓動完成"); 18 19 }
接着查看WCFHandlerService服務對象代碼,執行構造函數調用了 AppGlobal.AppStart(AppGlobalType.WCF)進行系統初始化;
1 public WCFHandlerService() 2 { 3 //mCallBackList = new List<IClientService>(); 4 Loader.ShowHostMsg(DateTime.Now, "WCFHandlerService服務正在初始化..."); 5 AppGlobal.AppRootPath = System.Windows.Forms.Application.StartupPath + "\\"; 6 AppGlobal.AppStart(AppGlobalType.WCF); 7 Loader.ShowHostMsg(DateTime.Now, "WCFHandlerService服務初始化完成"); 8 9 if (Convert.ToInt32(HostSettingConfig.GetValue("heartbeat")) == 1) 10 Loader.StartListenClients(); 11 }
服務主機的啓動過程就是這樣,接着咱們再講一下WCF版的客戶端向WCFHosting中間件請求的流程;先看客戶端控制器調用Wcf服務的代碼,是經過InvokeWCFService方法指定後臺wcf控制器的名稱和方法名;
接着看InvokeWCFService方法的實現代碼,經過調用WCFService對象的ProcessRequest來執行WCFHandlerService服務;這段代碼利用wcf服務實現了客戶端和中間件之間的通信;
1 public virtual Object InvokeWCFService(string controller, string method, string jsondata) 2 { 3 4 string retJson; 5 using (var scope = new OperationContextScope(WCFService as IContextChannel)) 6 { 7 var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, AppGlobal.cache.GetData("routerID").ToString()); 8 OperationContext.Current.OutgoingMessageHeaders.Add(router); 9 retJson = WCFService.ProcessRequest(ClientID, controller, method, jsondata); 10 } 11 object Result = JavaScriptConvert.DeserializeObject(retJson); 12 int ret = Convert.ToInt32(((Newtonsoft.Json.JavaScriptObject)(Result))["flag"]); 13 string msg = ((Newtonsoft.Json.JavaScriptObject)(Result))["msg"].ToString(); 14 if (ret == 1) 15 { 16 throw new Exception(msg); 17 } 18 else 19 { 20 return ((Newtonsoft.Json.JavaScriptObject)(Result))["data"]; 21 } 22 }
再接着看WCFHandlerService服務對於ProcessRequest方法的實現,經過參數傳遞的控制器名稱和方法名稱利用反射機制執行wcf控制器中的代碼;
1 public string ProcessRequest(string mProxyID, string controller, string method, string jsondata) 2 { 3 try 4 { 5 if (Convert.ToInt32(HostSettingConfig.GetValue("debug")) == 1) 6 Loader.ShowHostMsg(DateTime.Now, "客戶端[" + mProxyID + "]正在執行:" + controller + "." + method + "(" + jsondata + ")"); 7 string retJson = Loader.ProcessRequest(mProxyID, controller, method, jsondata); 8 return "{\"flag\":0,\"msg\":" + "\"\"" + ",\"data\":" + retJson + "}"; 9 } 10 catch (Exception err) 11 { 12 if (err.InnerException == null) 13 { 14 Loader.ShowHostMsg(DateTime.Now, "客戶端[" + mProxyID + "]執行失敗:" + controller + "." + method + "(" + jsondata + ")\n錯誤緣由:" + err.Message); 15 return "{\"flag\":1,\"msg\":" + "\"" + err.Message + "\"" + "}"; 16 } 17 else 18 { 19 Loader.ShowHostMsg(DateTime.Now, "客戶端[" + mProxyID + "]執行失敗:" + controller + "." + method + "(" + jsondata + ")\n錯誤緣由:" + err.InnerException.Message); 20 return "{\"flag\":1,\"msg\":" + "\"" + err.InnerException.Message + "\"" + "}"; 21 } 22 } 23 }
1 public static string ProcessRequest(string mProxyID, string controller, string method, string jsondata) 2 { 3 if (remoteLoaderDic[mProxyID] != null) 4 { 5 RemoteLoaderController mRemoteLoader = remoteLoaderDic[mProxyID]; 6 return mRemoteLoader.InvokeController(wcfClientDic[mProxyID], controller, method, jsondata); 7 } 8 return ""; 9 }
1 public string InvokeController(WCFClientInfo clientinfo, string controller, string method, string jsondata) 2 { 3 try 4 { 5 //ViewHandler = _viewH; 6 object[] paramValue = null;//jsondata? 7 object retObj = null; 8 string retJson = null; 9 10 List<Cmd_WCFController> cmd = (List<Cmd_WCFController>)AppGlobal.cache.GetData("cmdWcfController"); 11 Cmd_WCFController cmdC = cmd.Find(x => x.controllerName == controller); 12 if (cmdC != null) 13 { 14 cmdC.wcfController.ParamJsonData = jsondata; 15 cmdC.wcfController.ClientInfo = clientinfo; 16 Cmd_WCFMethod cmdM = cmdC.cmdMethod.Find(x => x.methodName == method); 17 if (cmdM != null) 18 { 19 if (controller == "LoginController" || controller == "TestWCFController") 20 { 21 } 22 else 23 { 24 if (System.Configuration.ConfigurationManager.AppSettings["TurnOnLoginRight"] == "true" && clientinfo.LoginRight == null) 25 { 26 //context.Response.Write("nologin");//沒登錄 27 throw new Exception("沒登錄"); 28 } 29 } 30 31 //每次請求控制器必須建立一個新的數據庫連接 32 EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase(); 33 Rdb.WorkId = cmdC.wcfController.GetSysLoginRight.WorkId; 34 //建立數據庫鏈接 35 cmdC.wcfController.BindDb(Rdb, AppGlobal.container); 36 37 if (cmdM.dbkeys != null && cmdM.dbkeys.Count > 0) 38 { 39 cmdC.wcfController.BindMoreDb(Rdb, "default"); 40 foreach (string dbkey in cmdM.dbkeys) 41 { 42 EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase _Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase(dbkey); 43 _Rdb.WorkId = cmdC.wcfController.GetSysLoginRight.WorkId; 44 //建立數據庫鏈接 45 cmdC.wcfController.BindMoreDb(_Rdb, dbkey); 46 } 47 } 48 retObj = cmdM.methodInfo.Invoke(cmdC.wcfController, paramValue); 49 } 50 else 51 { 52 //context.Response.Write("error");//命令錯誤 53 throw new Exception("控制器[" + cmdC.controllerName + "],沒有[" + cmdM.methodName + "]方法!"); 54 } 55 } 56 else 57 { 58 //context.Response.Write("error");//命令錯誤 59 throw new Exception("沒有控制器[" + cmdC.controllerName + "]"); 60 } 61 if (retObj != null) 62 retJson = retObj.ToString(); 63 return retJson; 64 } 65 catch (Exception ex) 66 { 67 if (ex.InnerException == null) 68 throw new Exception(ex.Message); 69 else 70 throw new Exception(ex.InnerException.Message); 71 } 72 }
總結一下wcf版的客戶端向中間件發送請求的過程,客戶端控制器利用WCFHandlerService服務通信中間件,併發送須要執行的控制器名稱和方法,中間件WCFHandlerService服務接收請求並根據參數利用反射調用wcf控制器的代碼返回執行結果;
經過上面對系統啓動入口的講解咱們知道全部模式的初始化內容都是封裝在AppGlobal對象中的,初始化的類型包括四種Web、Winform、WCF、WCFClient;WCFClient類型最簡單,只要建立EntLib中的緩存對象;另外三種類型內容包括:
1)EntLib中的Unity對象、Cache對象
2)定義定時任務、委託代碼對象
3)配置信息,BusinessDll、IsSaas、EFWUnity
4)Web類型加載實體、web控制器、WebService服務
5)WCF類型加載實體、wcf控制器
6)Winform類型加載實體
7)初始化定時任務、委託代碼和系統啓動中止擴展
8)測試數據庫鏈接
再就是對啓動的過程進行了日誌記錄,還有整個過程在系統中只能執行一次;
public enum AppGlobalType { Web,Winform,WCF,WCFClient }
AppGlobal對象代碼
1 /// <summary> 2 /// 系統啓動前初始化環境 3 /// </summary> 4 public class AppGlobal 5 { 6 /// <summary> 7 /// 應用程序根目錄 8 /// </summary> 9 public static string AppRootPath; 10 11 /// <summary> 12 /// 邏輯層程序集 13 /// </summary> 14 public static List<string> BusinessDll; 15 16 /// <summary> 17 /// 是否啓動成功 18 /// </summary> 19 public static bool IsRun = false; 20 /// <summary> 21 /// 是否Saas模式,where條件是否加workid 22 /// </summary> 23 public static bool IsSaas = false; 24 25 /// <summary> 26 /// Unity對象容器 27 /// </summary> 28 public static IUnityContainer container; 29 /// <summary> 30 /// 企業庫緩存 31 /// </summary> 32 public static ICacheManager cache; 33 34 /// <summary> 35 /// 定製任務 36 /// </summary> 37 public static List<TimingTask> taskList; 38 39 /// <summary> 40 /// 委託代碼 41 /// </summary> 42 public static Hashtable codeList; 43 44 45 private static bool _isCalled = false; 46 47 private static object locker = new object(); 48 49 public static void AppStart(AppGlobalType appType) 50 { 51 lock (locker) 52 { 53 if (_isCalled == false) 54 { 55 try 56 { 57 WriterLog("--------------------------------"); 58 WriterLog("應用開始啓動!"); 59 if (appType == AppGlobalType.WCFClient) 60 { 61 cache = ZhyContainer.CreateCache(); 62 } 63 else 64 { 65 //初始化靜態變量 66 container = ZhyContainer.CreateUnity(); 67 cache = ZhyContainer.CreateCache(); 68 taskList = new List<TimingTask>(); 69 codeList = new Hashtable(); 70 //加載引用業務程序集 71 BusinessDll = new List<string>(); 72 string[] dllfiles = System.Configuration.ConfigurationManager.AppSettings["BusinessDll"].Split(new char[] { '|' }); 73 BusinessDll = dllfiles.ToList(); 74 75 IsSaas = System.Configuration.ConfigurationManager.AppSettings["IsSaas"] == "true" ? true : false; 76 //加載Unity配置 77 var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = AppRootPath + "Config/EFWUnity.config" }; 78 System.Configuration.Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); 79 var unitySection = (UnityConfigurationSection)configuration.GetSection("unity"); 80 ZhyContainer.AddUnity(unitySection);//判斷EntLib的路徑對不對 81 82 83 if (BusinessDll.Count > 0) 84 { 85 switch (appType) 86 { 87 case AppGlobalType.Web: 88 //加載Entity自定義配置 89 EFWCoreLib.CoreFrame.BusinessArchitecture.Entity_Attribute.LoadEntityAttribute(AppRootPath+"bin/",BusinessDll, cache); 90 //加載WebController到緩存(此地方可能存在併發BUG) 91 EFWCoreLib.WebFrame.Controller.Cmd_Controller.LoadCmdController(BusinessDll, cache); 92 EFWCoreLib.WebFrame.HttpHandler.WebServiceInvoker.LoadWebService(BusinessDll, cache); 93 break; 94 case AppGlobalType.WCF: 95 //加載Entity自定義配置 96 EFWCoreLib.CoreFrame.BusinessArchitecture.Entity_Attribute.LoadEntityAttribute(AppRootPath, BusinessDll, cache); 97 EFWCoreLib.WCFHandler.Cmd_WCFController.LoadCmdController(BusinessDll, cache); 98 break; 99 case AppGlobalType.Winform: 100 //加載Entity自定義配置 101 EFWCoreLib.CoreFrame.BusinessArchitecture.Entity_Attribute.LoadEntityAttribute(AppRootPath, BusinessDll, cache); 102 break; 103 } 104 } 105 //初始化Web定製任務 106 MultiTask.Init(container, taskList);//任務 107 //是否開啓Web控制器請求權限認證 108 109 //擴展Global,網站程序啓動、中止可自定義代碼 110 GlobalExtend.StartInit(); 111 //初始化委託代碼 112 ExecuteFun.Init(container, codeList);//執行函數 113 114 //測試數據庫鏈接 115 EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.TestDbConnection(); 116 117 } 118 _isCalled = true; 119 WriterLog("應用啓動成功!"); 120 WriterLog("--------------------------------"); 121 122 IsRun = true; 123 } 124 catch(Exception err) 125 { 126 AppGlobal.WriterLog("應用啓動失敗!"); 127 AppGlobal.WriterLog("--------------------------------"); 128 throw err; 129 } 130 } 131 } 132 } 133 134 public static void AppStart() 135 { 136 AppStart(AppGlobalType.WCF); 137 } 138 139 public static void AppEnd() 140 { 141 GlobalExtend.EndInit(); 142 } 143 144 public static void WriterLog(string info) 145 { 146 info = "時間:" + DateTime.Now.ToString() + "\t\t" + "內容:" + info + "\r\n"; 147 File.AppendAllText(AppRootPath + "startlog.txt", info); 148 } 149 150 }