Winform开发框架之参数配置管理功能实现-基于SettingsProvider.net的构建
在较早时期,我写过一篇文章《
结合Control.FirefoxDialog控件,构造优秀的参数配置管理模块
》,
介绍过在我的Winform框架基础上集成的参数配置模块功能,但是参数模块的配置管理感觉还不够灵活,于是一直在寻找一个较好的替代者,用来结合FireFoxDialog界面一并展现,期间仔细研读过好几篇Codeproject网站上的关于配置管理的文章,但是总是觉得不够灵活或者简便。本文主要针对结合FireFoxDialog参数配置界面组件和SettingsProvider.net技术,实现较为美观、灵活的Winform程序参数配置管理。
在CodeProject上有两三篇文章介绍配置文件的很不错,下面给出链接大家分享下:
http://www.codeproject.com/Articles/25829/User-Settings-Applied
http://www.codeproject.com/Articles/475498/Easier-NET-settings
这两个都很不错,不过感觉不太满足我的简单、高效的需求,偶然之间在GitHub上发现一个《
SettingsProvider.net
》,做的非常不错,而且感觉扩展性也做的很好,因此就把它和FireFoxDialog界面一同整合,在框架内部实现参数管理功能。
1、SettingsProvider.net功能介绍
这个是在GitHub上的一款参数配置组件,能够基于普通配置文件、ProgramData目录文件、独立存储区文件等方式的配置文件存储,它主要是基于Json格式进行的配置保存,因此我们还可以把它存储到数据库,虽然官方没有提供例子,但是我们很容易通过扩展实现这个功能,后面我介绍我对其数据库参数保存扩展类。
它还可以通过Atrribute标识进行管理配置文件,可以把参数设置为加密、默认值、修改名称等,如下是它的一个配置参数的类的例子。
public classMySettings
{
[DefaultValue("Jake")]
[DisplayName("Your Name")]public string Name { get; set; }
[DefaultValue(true)]
[Description("Should Some App Remember your name?")]public bool RememberMe { get;set; }public List<Guid> Favourites { get;set; }
[Key("OriginalName")]public string Renamed { get; set; }
[ProtectedString]public string Encrypted { get; set; }
}
读取操作如下所示:
var settingsProvider = new SettingsProvider(); //By default uses IsolatedStorage for storage var mySettings = settingsProvider.GetSettings<MySettings>();
Assert.True(mySettings.RememberMe);
保存操作如下所示:
var settingsProvider = new SettingsProvider(); //By default uses IsolatedStorage for storage var mySettings = new MySettings { Name = "Mr Ginnivan"};
settingsProvider.Save(mySettings);
参数元数据获取操作代码如下:
var settingsProvider = newSettingsProvider();foreach (var setting in settingsProvider.ReadSettingMetadata<MySettings>())
{
Console.WriteLine("{0} ({1}) - {2}", setting.DisplayName, setting.Description, setting.DefaultValue);
}
2、参数配置功能界面截图
基于上述的SettingsProvider.net的组件,我们可以结合我前面介绍的FireFoxDialog界面效果,实现较好的参数配置管理功能,如下界面所示。
我们可以分别把不同的参数放到不同的存储介质里面去,如一些常用的,可以配置到本地目录文件里面去,一些和个人信息相关的内容,我们可以把它放到数据库里面去,这样可以在各个客户端使用都不需要重新配置,非常方便。
上面的例子,我针对性介绍两个,一个是基于本地文件参数存储,一个是基于数据库文件的参数存储。
3、基于SettingsProvider.net的整合操作的实现
介绍了基于SettingsProvider.net的功能,以及最终整合的效果,我们来看看它具体是如何整合实现不同文件类型数据的保存的。
首先,我们在设计模式下,拖动好对应的界面,由于FireFoxDialog界面本来就是用来做参数设置的,因此他们里面有一些控件就不一一介绍了,具体可以参考对应的文章(http://www.codeproject.com/KB/miscctrl/ControlFirefoxDialog.aspx?msg=1856449)。
我们看看上述效果界面的设计界面和后台代码。
设计界面就是如下所示,拖动一个参数配置用户控件到窗体上,设置好对应的内容就可以了。
后台代码如下所示。
public partial classFrmSettings : BaseForm
{publicFrmSettings()
{
InitializeComponent();
}private void FrmSettings_Load(objectsender, EventArgs e)
{this.firefoxDialog1.ImageList = this.imageList1;this.firefoxDialog1.AddPage("报表设置", new PageReport());//基于本地文件的参数存储 this.firefoxDialog1.AddPage("邮箱设置", new PageEmail());//基于数据库的参数存储//下面是陪衬的 this.firefoxDialog1.AddPage("短信设置", newPageEmail());this.firefoxDialog1.AddPage("声音设置", newPageEmail());this.firefoxDialog1.AddPage("系统设置", newPageEmail());this.firefoxDialog1.AddPage("备份设置", newPageEmail());this.firefoxDialog1.AddPage("其他设置", newPageEmail());this.firefoxDialog1.Init();
}
}
这里最有代表性的是PageReport和PageEmail两个组件对象。
1)报表模块配置管理
基于报表参数和邮件参数,我们可以定义一个参数对象类,用来方便保存和获取数据的承载对象。
报表参数对象类如下(只做了简单的一个报表路径处理):
/// <summary> ///报表设置/// </summary> public classReportParameter
{/// <summary> ///派车单报表文件/// </summary> [DefaultValue("WHC.CarDispatch.CarSendBill2.rdlc")]public string CarSendReportFile { get; set; }
}
对应的设计界面如下所示,用来提供一个报表文件的参数配置,很简单了。
我们来看看后台的组件,对参数是如何保存和显示的。
首先需要初始化相应的对象,我们这里使用了在程序运行目录下,创建一个文件用来保存这些设置。
public partial classPageReport : PropertyPage
{privateSettingsProvider settings;privateISettingsStorage store;publicPageReport()
{
InitializeComponent();if(!this.DesignMode)
{//PortableStorage: 在运行程序目录创建一个setting的文件记录参数数据 store = newPortableStorage();
settings= newSettingsProvider(store);
}
}
注意:PortableStorage是在运行程序目录创建一个setting的文件记录参数数据,运行后,最终会在目录下生成一个类似“ReportParameter.settings”的文件,它的内容格式如下所示。
[{"Key":"CarSendReportFile","Value":"\"WHC.CarDispatch.CarSendBill2.rdlc\""}]
我们看看报表组件的参数是如何初始化的:
public override voidOnInit()
{
ReportParameter parameter= settings.GetSettings<ReportParameter>();if (parameter != null)
{
EnableOtherReport(false);string reportFile =parameter.CarSendReportFile;if (reportFile == "WHC.CarDispatch.CarSendBill2.rdlc")
{this.radReport.SelectedIndex = 0;
}else if (reportFile == "WHC.CarDispatch.CarSendBill.rdlc")
{this.radReport.SelectedIndex = 1;
}else{
EnableOtherReport(true);this.radReport.SelectedIndex = 2;this.txtOtherReport.Text =reportFile;
}
}
}
通过参数的存储对象处理,这样我们就可以通过ReportParameter 进行数据获取了。
保存参数的时候,同样也是先获取到一个参数对象,并设置它的值后,然后进行保存就可以了,具体代码如下所示。
public override boolOnApply()
{bool result = false;try{
ReportParameter parameter= settings.GetSettings<ReportParameter>();if (parameter != null)
{int otherType = 2;//2代表其他类型 if (this.radReport.SelectedIndex <otherType)
{
parameter.CarSendReportFile= this.radReport.Properties.Items[this.radReport.SelectedIndex].Value.ToString();
}else{
parameter.CarSendReportFile= this.txtOtherReport.Text;
}
settings.SaveSettings<ReportParameter>(parameter);
}
result= true;
}catch(Exception ex)
{
LogTextHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
}returnresult;
}
2)邮件参数配置管理
邮件参数对象类如下:
/// <summary> ///邮箱设置/// </summary> public classEmailParameter
{/// <summary> ///邮件账号/// </summary> //[DefaultValue("wuhuacong@163.com")] public string Email { get; set; }/// <summary> ///POP3服务器/// </summary> [DefaultValue("pop.163.com")]public string Pop3Server { get; set; }/// <summary> ///POP3端口/// </summary> [DefaultValue(110)]public int Pop3Port { get; set; }/// <summary> ///SMTP服务器/// </summary> [DefaultValue("smtp.163.com")]public string SmtpServer { get; set; }/// <summary> ///SMTP端口/// </summary> [DefaultValue(25)]public int SmtpPort { get; set; }/// <summary> ///登陆账号/// </summary> public string LoginId { get; set; }/// <summary> ///登陆密码/// </summary> [ProtectedString]public string Password { get; set; }/// <summary> ///使用SSL加密/// </summary> [DefaultValue(false)]public bool UseSSL { get; set; }
}
参数显示和保存的界面设计如下所示。
界面的初始化,同样和上面的差不多,不过这里使用了数据库的存储类DatabaseStorage,内容将保存在数据库里面,而且我们通过用户的标识Create进行路径的针对性处理,可以使每个用户的配置文件不同。
public partial classPageEmail : PropertyPage
{privateSettingsProvider settings;privateISettingsStorage store;publicPageEmail()
{
InitializeComponent();if (!this.DesignMode)
{//DatabaseStorage:在数据库里面,以指定用户标识保存参数数据 string creator =Portal.gc.LoginUserInfo.Name;
store= newDatabaseStorage(creator);
settings= newSettingsProvider(store);
}
}
参数的加载代码如下所示,也就是把数据获取后,显示在界面上即可。
public override voidOnInit()
{
EmailParameter parameter= settings.GetSettings<EmailParameter>();if (parameter != null)
{this.txtEmail.Text =parameter.Email;this.txtLoginId.Text =parameter.LoginId;this.txtPassword.Text =parameter.Password;this.txtPassword.Tag =parameter.Password;this.txtPop3Port.Value =parameter.Pop3Port;this.txtPop3Server.Text =parameter.Pop3Server;this.txtSmtpPort.Value =parameter.SmtpPort;this.txtSmtpServer.Text =parameter.SmtpServer;this.txtUseSSL.Checked =parameter.UseSSL;
}
}
数据的保存操作也很简单,和前面的操作差不多,如下所示。
EmailParameter parameter = settings.GetSettings<EmailParameter>();if (parameter != null)
{
parameter.Email= this.txtEmail.Text;
parameter.LoginId= this.txtLoginId.Text;
parameter.Password= this.txtPassword.Text;
parameter.Pop3Port= Convert.ToInt32(this.txtPop3Port.Value);
parameter.Pop3Server= this.txtPop3Server.Text;
parameter.SmtpPort= Convert.ToInt32(this.txtSmtpPort.Value);
parameter.SmtpServer= this.txtSmtpServer.Text;
parameter.UseSSL= this.txtUseSSL.Checked;
settings.SaveSettings<EmailParameter>(parameter);
}
最终,我们在数据库表里面,可以看到对应记录已经保存起来了,并且用户密码部分也进行了加密处理。
这样,我们整合两者的特点,就可以实现比较不错的参数配置界面的显示和后台存储处理了,针对性的,使用不同的存储介质,以满足不同的需要。