大千世界,合久必分,分久必合,分合之道,利之所趨。
開發過程,積少成多,聚沙成塔,模塊之理,必經之路。
本文繼續WInform界面開發系列的介紹,主要針對性介紹Winform開發過程中,經常用到的模塊:數據字典模塊、參數配置模塊、權限管理模塊的模塊化應用,以及各模塊的分合之道。
1、數據字典模塊
我們知道,一般程序基本上都涉及到了一個是數據參考用途的數據字典模塊,不管是Web還是Winform的,這個模塊基本上是必不可少的,Winform的界面效果大致如下所示:
本模塊的數據字典支持無限級樹形分層應用,可以添加大類,字典項目等數據, 系統集成只需要拷貝相關的字典表即可實現集成。
2、參數配置模塊
在程序中,一般應用就是通過代碼把相關的內容進行轉義保存或者解析,以便呈現給用戶更好的數據展示效果,這個模塊比較通用,可分可合。
另外一個也比較常用的就是參數的配置管理模塊,一般如果參數比較少,直接使用.NET的配置保存功能即可,如下圖所示。
但這種方式只能保存比較少的內容,對於比較復雜的配置,一般很少采用這種模式存放程序的參數信息,這種方式存儲的參數,如果不是放到一個獨立的文件中,還存在一個不同步的現象。
其實我們還是可以把參數的配置功能作為一個獨立的模塊進行處理,我的程序就是經常這麼干的,而且由於是相對比較獨立,並在設計時候就支持參數的編輯及展示功能,因此效率大大提高,對使用用戶來說,由於修改界面比較統一,而且參數的說明等很豐富,因此用戶修改系統的配置參數友好性大大增強,界面效果如下所示:
使用用戶看到的參數配置界面效果:
開發者在設計時刻的參數配置界面如下所示:
這些參數最終目的是為了程序的讀取和調用,調用代碼非常簡單,而且由於是強類型的屬性以及良好的提示功能,應該是比較方便的,示例代碼如下所示:
double hours = span.Hours;
hours = (hours < SystemConfig.Default.KFPartAtLeaseHoure) ?
SystemConfig.Default.KFPartAtLeaseHoure : hours;//最小的鐘點房計費
if (span.Minutes < 60 && span.Minutes >= SystemConfig.Default.KFPartHourMinutes)
{
hours += 1;
}
else if (span.Minutes > SystemConfig.Default.KFPartHalfHourMinte &&
span.Minutes < SystemConfig.Default.KFPartHourMinutes)
{
hours += 0.5;
}
其中的SystemConfig.Default.KFPartAtLeaseHoure就是參數的名稱了,根據這個名稱就可以讀取和設置該參數的值。
該參數配置模塊是一個Visual Studio的Addin插件,因此可以在設計時刻提供參數的添加、修改、刪除等支持,非常方便,而且也能在發布後給用戶界面提供修改,是一個獨立的模塊。
3、權限管理模塊
最後說說第三個模塊,權限管理模塊,我們知道,一般對於進銷存或者稍微復雜一點的系統,都需要最基本的權限控制模塊,以便控制不同用戶的訪問功能,這個可以做成獨立的應用程序進行管理,如下圖所示:
程序是一個獨立的程序,但是權限系統需要和業務應用系統結合一起才有價值,因此它們之間的結合,一個除了數據庫的整合(把權限系統需要的表整合一起),還需要在系統的代碼中進行整合(實現功能模塊的登陸及權限控制等)。登陸驗證如下所示:
try
{
string loginName = this.cmbzhanhao.Text.Trim();
User userBLL = new User();
string identity = userBLL.VerifyUser(loginName, this.tbPass.Text, Guid.NewGuid().ToString());
if (!string.IsNullOrEmpty(identity))
{
UserInfo info = userBLL.GetUserByName(loginName);
#region 獲取用戶的功能列表
Function functionBLL = new Function();
List<FunctionInfo> list = functionBLL.GetFunctionsByUser(info.ID, "HOTELMS");
if (list != null && list.Count > 0)
{
foreach (FunctionInfo functionInfo in list)
{
if (!Portal.gc.FunctionDict.ContainsKey(functionInfo.ControlID))
{
Portal.gc.FunctionDict.Add(functionInfo.ControlID, functionInfo);
}
}
}
#endregion
bLogin = true;
Portal.gc.LoginInfo = info;
this.DialogResult = DialogResult.OK;
}
else
{
MessageUtil.ShowTips("用戶帳號密碼不正確");
this.tbPass.Text = ""; //設置密碼為空
}
}
catch (Exception err)
{
MessageUtil.ShowError(err.Message);
}
用戶功能權限認證如下所示:
#region KTV包間管理
if (Portal.gc.HasFunction("KTV"))
{
OutlookBarBand myBasicBand = new OutlookBarBand("KTV包間管理");
myBasicBand.SmallImageList = this.imageList;
myBasicBand.LargeImageList = this.imageList;
if (Portal.gc.HasFunction("KTV/View"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV包間狀態視圖", 0));
}
if (Portal.gc.HasFunction("KTV/Setting"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV包間設置", 1));
}
if (Portal.gc.HasFunction("KTV/Goods"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV商品設置", 3));
}
if (Portal.gc.HasFunction("KTV/Waiter"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV服務生管理", 4));
}
if (Portal.gc.HasFunction("KTV/BookIn"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV預訂管理", 5));
}
if (Portal.gc.HasFunction("KTV/OtherIncome"))
{
myBasicBand.Items.Add(new OutlookBarItem("KTV其他款項登記", 6));
}
myBasicBand.Background = SystemColors.AppWorkspace;
myBasicBand.TextColor = Color.White;
outlookBar1.Bands.Add(myBasicBand);
}
#endregion
至此,三個常用而且比較獨立模塊介紹完畢,這幾種場景你用了幾個呢,如果覺得有價值,歡迎一起討論切磋。
開發之道,順手拈來;分合之需, 順其自然;優碼不語,潤物無聲;