這幾個月一直忙APP的項目,沒來得及更新項目,想想該抽出時間整理一下開發思路,跟大家分享,同時也希望得到寶貴的建議。 先說一下我們的許可權管理的的設計思路,首先一個企業信息化管理系統一定會用到許可權管理, 那麼一個動態的菜單在企業信息化管理系統占有一定的分量。 下麵介紹我的一些思路。 由於原聲的winf ...
這幾個月一直忙APP的項目,沒來得及更新項目,想想該抽出時間整理一下開發思路,跟大家分享,同時也希望得到寶貴的建議。
先說一下我們的許可權管理的的設計思路,首先一個企業信息化管理系統一定會用到許可權管理, 那麼一個動態的菜單在企業信息化管理系統占有一定的分量。
下麵介紹我的一些思路。
由於原聲的winform界面美觀性不夠, 系統採用dotnetbar第三方控制項來輔助編程。
首先我們看紅色方框部分為我們的動態模塊功能。這樣我們獲得到了以下幾個信息, 我們需要記錄模塊功能, 並且需要父子集關係, 那麼對應的我們就需要在資料庫中建立一張表來維護我們的動態菜單模塊。我們舉例命名為BaseModuleTabel, 那麼會有一下的內容,Id ParentId Name,並且由於需要跟不同的用戶有對應的關係, 我們還要建立用戶以及菜單的關係表,來維護用戶與菜單的許可權關係。
這裡就不介紹表的設計。我們先來看看在dotnetbar中如何呈現動態菜單邏輯。
我們先從資料庫中獲取到所有菜單模塊。並通過迴圈便利動態的載入模塊按鈕。 並添加對應的模塊按鈕事件,
1 /// <summary> 2 /// 載入菜單 3 /// </summary> 4 private void LoadMenu() 5 { 6 var parentEntity = _baseModuleBll.Repository().FindEntity("ParentId", "0"); 7 8 var result = _baseModuleBll.GetModuleList().Select(p => new BaseTreeViewMenuModel() 9 { 10 Id = p.ModuleId, 11 ParentId = p.ParentId, 12 Name = p.FullName, 13 Class = p.Location, 14 Namespace = StringHelper.SubFirstChart(p.Location, '.'), 15 IsForm = p.Target == "iframe" 16 }).ToList(); 17 RibbonTabItem ribbonTabItemFrist = null; 18 var rabbonTabItemEntities = result.Where(p => p.ParentId == parentEntity.ModuleId); 19 foreach (var ribbonTabItemEntity in rabbonTabItemEntities) 20 { 21 var ribbonPanel = new RibbonPanel 22 { 23 Text = ribbonTabItemEntity.Name, 24 Dock = DockStyle.Fill 25 }; 26 var ribbonTabItem = new RibbonTabItem 27 { 28 Text = ribbonTabItemEntity.Name, 29 Panel = ribbonPanel 30 }; 31 if (ribbonTabItemFrist == null) 32 ribbonTabItemFrist = ribbonTabItem; 33 this.ribbonControlMenu.Controls.Add(ribbonPanel); 34 this.ribbonControlMenu.Items.Add(ribbonTabItem); 35 36 var ribbonBar = new RibbonBar { Text = ribbonTabItemEntity.Name }; 37 var buttonItemEntities = result.Where(p => p.ParentId == ribbonTabItemEntity.Id); 38 foreach (var buttonItem in buttonItemEntities.Select(buttonItemEntitiy => 39 new ButtonItem("ButtonItem" + buttonItemEntitiy.Name) 40 { 41 Text = buttonItemEntitiy.Name, 42 Tag = buttonItemEntitiy 43 })) 44 { 45 buttonItem.Click += ButtonItem_Click; 46 ribbonBar.Items.Add(buttonItem); 47 ribbonPanel.Controls.Add(ribbonBar); 48 } 49 } 50 this.ribbonControlMenu.SelectedRibbonTabItem = ribbonTabItemFrist; 51 52 } 53 54 #endregion
當然我們的框架採用了反射機制來實現組件式開發。通常在一個項目里,為了降低耦合度,我一邊將模塊力度最小話,並將按一定的規則分類, 處理成摸個模塊,在我們的系統中並不影響彼此開發的同時, 每個成員都可以獨立的去完成自己的小任務, 說句不好聽的, 就算是能力很差的新手,開發出來的耦合度極高的代碼, 通過這樣一種方式,他的影響範圍也緊緊在與他的模塊內, 並不影響其他模塊操作。 僅作為個人的一種方式,當然通過我們的代碼生成器,會生成一定的代碼規範,這雖然能避免一些, 但起不到決定性的作用。 畢竟每個人的能力也是大不相同的。作為PM我們需要做的就是降低項目整體風險,按照規定的項目周期,制定完善的項目計劃,系統模塊劃分力度越大,項目把控的越高。
下麵打開點擊模塊按鈕來,通過反射來實現對各個模塊的初始化以及載入。代碼效率目前開無太大障礙。當然如果一個模塊dll你要弄個幾百兆,那我也只能無語了。你的力度相對較小,會跟你反射的時間掛鉤的。
1 /// <summary> 2 /// 打開模塊菜單 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void ButtonItem_Click(object sender, EventArgs e) 7 { 8 var isOpened = false; 9 var buttonItem = (ButtonItem)sender; 10 var baseTreeViewMenuModel = (BaseTreeViewMenuModel)buttonItem.Tag; 11 if (baseTreeViewMenuModel == null) return; 12 if (!baseTreeViewMenuModel.IsForm) return; 13 if (string.IsNullOrWhiteSpace(baseTreeViewMenuModel.Namespace)) return; 14 //遍歷現有的Tab頁面,如果存在,那麼設置為選中即可 15 foreach (var tabitem in 16 superTabControlContent.Tabs.Cast<SuperTabItem>() 17 .Where(tabitem => tabitem.Name == "superTabItem" + baseTreeViewMenuModel.Name)) 18 { 19 superTabControlContent.SelectedTab = tabitem; 20 isOpened = true; 21 break; 22 } 23 if (isOpened) return; 24 var dll = Application.StartupPath + "\\" + baseTreeViewMenuModel.Namespace + ".dll"; 25 if (!File.Exists(dll)) return; 26 var assembly = Assembly.LoadFrom(dll); 27 var type = assembly.GetType(baseTreeViewMenuModel.Class); 28 if (type == null) return; 29 var form = (FormBase)Activator.CreateInstance(type); 30 form.ModuleId = baseTreeViewMenuModel.Id; 31 form.FormBorderStyle = FormBorderStyle.None; 32 form.TopLevel = false; 33 form.Visible = true; 34 form.Dock = DockStyle.Fill; 35 var superTabItem = superTabControlContent.CreateTab(baseTreeViewMenuModel.Name); 36 superTabItem.Text = baseTreeViewMenuModel.Name; 37 superTabItem.Name = "superTabItem" + baseTreeViewMenuModel.Name; 38 superTabItem.AttachedControl.Controls.Add(form); 39 superTabControlContent.SelectedTab = superTabItem; 40 } 41 42 #endregion
通過以上的代碼我們就可以實現如下圖所示的動態菜單功能 。
分享是美德,要提倡!