在我們很多程序的登陸過程中,如果對(duì)于一些復(fù)雜的內(nèi)容,可能都有一些配置管理的對(duì)話框,本文介紹的混合式開發(fā)框架,是指什么呢,我下面給了一個(gè)定義。
《混合式開發(fā)框架》是指混合了傳統(tǒng)《Winform開發(fā)框架》和《WCF開發(fā)框架》的特點(diǎn),可以在兩者之間自由切換,統(tǒng)一了系統(tǒng)界面層對(duì)業(yè)務(wù)服務(wù)的調(diào)用模式,所有組件模塊均實(shí)現(xiàn)兩種方式的調(diào)用,是一種彈性化非常好的框架應(yīng)用,既可用于單機(jī)版軟件或者基于局域網(wǎng)內(nèi)的應(yīng)用軟件,也可以用于分布式技術(shù)的互聯(lián)網(wǎng)環(huán)境應(yīng)用。
對(duì)于這種混合式模式,上面說到了有兩種方式,一種是常規(guī)的訪問數(shù)據(jù)庫方式,一種是訪問WCF服務(wù)方式,而訪問WCF服務(wù),可能有基于局域網(wǎng)(內(nèi)網(wǎng))模式,也可能是基于互聯(lián)網(wǎng)(外網(wǎng))模式,那么我們就可能配置三種登陸方式,如果每次需要手工修改配置文件,可能比較麻煩,如果我們能夠通過程序方式來實(shí)現(xiàn)參數(shù)的界面化配置,那么工作就輕松很多,也不容易出錯(cuò)。
1、配置界面和配置內(nèi)容介紹
關(guān)于配置的管理,我肯定是首先推薦SettingsProvider.net這個(gè)組件,大家需要了解這個(gè)組件的使用,可以參考我的隨筆《Winform開發(fā)框架之參數(shù)配置管理功能實(shí)現(xiàn)-基于SettingsProvider.net的構(gòu)建》,這里可以結(jié)合FireFoxDialog界面效果實(shí)現(xiàn)比較友好的配置管理,界面效果如下所示。

在WCF的配置文件中,我們可以看到很多對(duì)于IP地址的配置,而一般我們把WCF的配置信息放到一個(gè)獨(dú)立的配置文件里面,方便管理。
對(duì)于局域網(wǎng)的WCF客戶端的配置信息,大概效果如下所示。

而對(duì)于外網(wǎng),也只是把這些IP換成公網(wǎng)IP即可,一般來說,這些是獨(dú)立的配置文件,我們一般還有一個(gè)主配置文件**.exe.config,用來配置我們框架常用到的一些配置信息。
如下所示,在我們混合式需要訪問本地?cái)?shù)據(jù)庫的時(shí)候,就可以在主配置文件里面保存主要的數(shù)據(jù)庫連接信息。

2、配置對(duì)話框的設(shè)計(jì)和實(shí)現(xiàn)
前面介紹了關(guān)于參數(shù)配置和WCF配置文件的一些相關(guān)信息,基于這些考慮,我們應(yīng)該在混合式模式的登陸界面里面,設(shè)計(jì)好相關(guān)界面,讓用戶可以方便配置訪問不同的數(shù)據(jù)源,以便實(shí)現(xiàn)真正混合式的強(qiáng)大功能和便利性。
首先我們來介紹一下我的混合式框架,登陸界面的設(shè)計(jì)。

單擊參數(shù)設(shè)置按鈕,可以進(jìn)入登陸訪問參數(shù)的界面對(duì)話框,在里面可以友好直觀的配置相關(guān)的WCF訪問參數(shù),界面如下所示,這里面使用了類似FireFox的界面組件,后臺(tái)的文件存儲(chǔ),主要是基于本地的XML存儲(chǔ),使用了SettingsProvider.net這個(gè)組件進(jìn)行數(shù)據(jù)的存儲(chǔ)管理。

如果是選擇“單機(jī)版模式”,那么我們把對(duì)應(yīng)的網(wǎng)絡(luò)方式設(shè)置為不可選擇,這樣的效果比較好體現(xiàn)本地模式的排他性。

這些界面基本上介紹了如何處理混合式開發(fā)框架的參數(shù)配置內(nèi)容了,具體的實(shí)現(xiàn)操作是如何的呢?下面我們來一步步分析介紹下。
首先我們定義一個(gè)用來保存和加載參數(shù)的一個(gè)實(shí)體類,用來存儲(chǔ)對(duì)應(yīng)的參數(shù)信息。
/// <summary>
/// 用戶登錄的連接方式、訪問方式
/// </summary>
public class LoginParameter
{
/// <summary>
/// 系統(tǒng)最后登錄賬號(hào)
/// </summary>
[DefaultValue("admin")]
public string LoginId { get; set; }
/// <summary>
/// 登陸密碼
/// </summary>
[ProtectedString]
public string Password { get; set; }
/// <summary>
/// 記住密碼
/// </summary>
[DefaultValue(false)]
public bool RememberPassword { get; set; }
/// <summary>
/// 是否為本地?cái)?shù)據(jù)庫連接方式,否則為使用WCF服務(wù)模式(內(nèi)網(wǎng),外網(wǎng))
/// </summary>
[DefaultValue(false)]
public bool IsLocalDatabase { get; set; }
/// <summary>
/// 內(nèi)網(wǎng)WCF的主機(jī)地址
/// </summary>
[DefaultValue("192.168.1.10")]
public string InternalWcfHost { get; set; }
/// <summary>
/// 內(nèi)網(wǎng)WCF的端口
/// </summary>
[DefaultValue(8000)]
public int InternalWcfPort { get; set; }
/// <summary>
/// 外網(wǎng)WCF的主機(jī)地址
/// </summary>
[DefaultValue("183.6.161.193")]
public string ExternalWcfHost { get; set; }
/// <summary>
/// 外網(wǎng)WCF的端口
/// </summary>
[DefaultValue(8000)]
public int ExternalWcfPort { get; set; }
}
這樣我們就可以以實(shí)體類為載體,對(duì)數(shù)據(jù)進(jìn)行獲取和保存操作了。
配置信息的加載和保存操作代碼如下所示,這些保存操作就是基于SettingsProvider.net的。
/// <summary>
/// 從本地XML文件中加載參數(shù)信息
/// </summary>
private void LoadParameter()
{
store = new PortableStorage();//保存在本地計(jì)算機(jī)
settings = new SettingsProvider(store);
parameter = settings.GetSettings<LoginParameter>();
if (parameter != null)
{
this.cmbzhanhao.Text = parameter.LoginId;
this.chkRemember.Checked = parameter.RememberPassword;
if (parameter.RememberPassword)
{
this.tbPass.Text = parameter.Password;
}
else
{
this.tbPass.Text = "";
}
this.chkLocalVersion.Checked = parameter.IsLocalDatabase;
//確保為正確的訪問方式,網(wǎng)絡(luò)版還是單機(jī)版
SetAccessType(this.chkLocalVersion.Checked);
}
}
/// <summary>
/// 把用戶的信息保存到本地XML文件里面
/// </summary>
private void SaveParameter()
{
store = new PortableStorage();//保存在本地計(jì)算機(jī)
settings = new SettingsProvider(store);
parameter = settings.GetSettings<LoginParameter>();
if (parameter != null)
{
parameter.LoginId = this.cmbzhanhao.Text;
if (parameter.RememberPassword)
{
parameter.Password = this.tbPass.Text;
}
else
{
parameter.Password = "";
}
parameter.IsLocalDatabase = this.chkLocalVersion.Checked;
settings.SaveSettings<LoginParameter>(parameter);
}
}
對(duì)于如果選擇單機(jī)版模式,那么我們需要設(shè)置相應(yīng)的參數(shù),用來告訴混合式框架采用本地?cái)?shù)據(jù)庫模式,具體代碼如下所示。
/// <summary>
/// 單機(jī)版模式的復(fù)選框事件處理
/// </summary>
private void chkLocalVersion_CheckedChanged(object sender, EventArgs e)
{
SetAccessType(this.chkLocalVersion.Checked);
}
/// <summary>
/// 設(shè)置為網(wǎng)絡(luò)方式還是單機(jī)版模式
/// </summary>
/// <param name="localType">是否為單機(jī)版模式</param>
private void SetAccessType(bool localType)
{
this.lblNetType.Enabled = !localType;
this.radNetType.Enabled = !localType;
AppConfig config = new AppConfig();
config.AppConfigSet("CallerType", localType ? "win" : "wcf");
ConfigurationManager.RefreshSection("appSettings");
}
如果是網(wǎng)絡(luò)方式,還需要區(qū)分內(nèi)網(wǎng)模式,還是外網(wǎng)模式,根據(jù)參數(shù)來對(duì)相關(guān)的配置文件進(jìn)行修改,具體邏輯代碼如下所示。
/// <summary>
/// 網(wǎng)絡(luò)方式(內(nèi)網(wǎng)、外網(wǎng))切換處理事件
/// </summary>
private void radNetType_SelectedIndexChanged(object sender, EventArgs e)
{
ChangeConfig();
}
/// <summary>
/// 修改配置文件
/// </summary>
private void ChangeConfig()
{
if (parameter != null)
{
bool isIntranet = radNetType.EditValue.ToString() == "內(nèi)網(wǎng)";
if (isIntranet)
{
UpdateConfig(parameter.InternalWcfHost, parameter.InternalWcfPort);
}
else
{
UpdateConfig(parameter.ExternalWcfHost, parameter.ExternalWcfPort);
}
}
else
{
MessageDxUtil.ShowError("獲取參數(shù)信息失敗");
}
}
/// <summary>
/// WCF模式下,修改配置文件中的主機(jī)地址信息和端口
/// </summary>
/// <param name="serverIPAddress">主機(jī)地址信息</param>
/// <param name="serverPort">端口</param>
private void UpdateConfig(string serverIPAddress, int serverPort)
{
string basePath = System.Environment.CurrentDirectory;
UpdateConfigFile(serverIPAddress, serverPort, Path.Combine(basePath, "BaseWcfConfig.config"));
UpdateConfigFile(serverIPAddress, serverPort, Path.Combine(basePath, "WcfConfig.config"));
}
/// <summary>
/// 通過正則標(biāo)識(shí)方式替換其中的主機(jī)信息和端口參數(shù)
/// </summary>
/// <param name="serverIPAddress">主機(jī)地址信息</param>
/// <param name="serverPort">端口</param>
/// <param name="exeFilePath">配置文件地址</param>
private void UpdateConfigFile(string serverIPAddress, int serverPort, string exeFilePath)
{
string address = File.ReadAllText(exeFilePath, System.Text.Encoding.UTF8);
string pattern = "://.*?/";
string replacement = string.Format("://{0}:{1}/", serverIPAddress, serverPort);
address = Regex.Replace(address, pattern, replacement);
File.WriteAllText(exeFilePath, address, System.Text.Encoding.UTF8);
}
以上就是我對(duì)于混合式開發(fā)框架的登陸方式和登陸參數(shù)進(jìn)行的配置信息管理的一個(gè)案例,希望對(duì)大家有幫助。