# ConfigManager **Repository Path**: yangtb2/config-manager ## Basic Information - **Project Name**: ConfigManager - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-07-20 - **Last Updated**: 2021-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: Csharp, dotNET, Winforms ## README # 使用.ini文件方便地管理WindowsForm中控件的值或状态 --- ### 应用背景 现有一个IniFile类,通过包装kernel32.dll中的函数提供了以下几个读写.ini文件的方法: ``` public int ReadInt(string section, string name, int def) public string ReadString(string section, string name, string def = "") public void WriteInt(string section, string name, int Ival) public void WriteString(string section, string name, string strVal) ``` 希望使用IniFile类来读取/保存WindowsForm程序中某些控件(例如ComboBox, CheckBox, NumericUpDown, TextBox...)的值或状态,但存在以下问题: * 根据控件类型的不同,可能要保存不同的成员,如ComboBox.SelectedIndex, CheckBox.Checked...,而IniFile类只提供了读写整型数或字符串的方法,因此需要根据控件类型做不同的转换操作; * 需要在控件的值或状态改变时将其写入文件,所以该过程往往是在控件的ValueChanged等类似的事件中进行处理,但是如果直接将过程写到事件响应函数里面,则容易和控件本身的业务逻辑耦合在而一起,而且每个控件都要写这样一段代码,非常麻烦,例如 ``` private void numericUpDown1_ValueChanged(object sender, EventArgs e) { //业务功能代码 //将值写入.ini文件的代码 } ``` ### 解决方案 * 使用一个数组对象保存所有需要进行管理的控件 * 使用策略模式,对不同类型的控件执行不同的读写操作 * 利用委托(delegate)动态地将保存操作绑定到控件相应的事件上 ### 使用说明 ##### 初始化 1. 新建一个ConfigManager类的实例,构造函数可以传入一个IniFile类的实例或一个获取.ini文件路径的委托实例。如果使用获取路径的委托实例创建类,则改方法会在每次调用实例方法Init时执行,这使得我们可以将不同模式(或不同本地用户)下控件的值或状态保存在不同文件中,方便地实现模式切换或用户切换时更新控件的值或状态 ``` //使用IniFile类的实例初始化 ConfigManager configManger = new ConfigManager(new IniFile(path)); //使用获取文件路径的委托实例初始化 ConfigManager configManger = new ConfigManager(new GetConfig(getPathMethod)); ``` 2. 使用ConfigManager类的实例方法Add添加需要管理的控件 ``` configManger.Add(checkBox1, “Section1”, “Name1”); configManger.Add(comboBox1, “Section1”, “Name2”); configManger.Add(numericUpDown1, “Section2”, “Name1”); ``` 如果不需要自定义节/键名,推荐使用控件所在窗口的完全限定类型名称作为节,控件的Name属性作为键,可保证唯一性,且操作更简单 ``` foreach (Control item in this.Controls) { Type t = item.GetType(); if(t == typeof(CheckBox) || t == typeof(ComboBox) || t == typeof(NumericUpDown)) { configManger.Add(item,this.GetType().ToString(),item.Name); } } ``` ##### 读取操作 使用ConfigManager的实例方法Init可对所有控件执行读操作,并返回错误信息的列表 ``` IList errors = configManger.Init(); ``` 也可以对单个控件执行读操作,前提是控件已使用Add方法添加到列表中 ``` string error = configManger.Read(item) ``` ##### 保存操作 当使用Add方法添加控件时,已将保存操作绑定到了控件对应的事件上,当事件触发时将自动保存。如果不想再执行保存,可以使用实例的Remove方法,该方法将控件从列表中移除,同时也将保存操作从控件的事件响应委托链上移除 ``` configManager.Remove(item) ``` ##### 添加新策略 ConfigManager类中初始化了ComboBox, CheckBox, NumericUpDown控件的策略,可以为ConfigManager实例动态地添加新的策略,例如下面代码为它添加一个针对TextBox控件的策略 ``` private string readTextBox(object item) { //读取操作 } private void bindTextBox(object item, bool remove = false) { //这里要提供移除委托的方法,否则移除控件时保存操作不会从事件响应委托链上移除 if (remove) { (item as TextBox).TextChanged -= this.TextBoxTextChange; } else { (item as TextBox).TextChanged += this.TextBoxTextChange; } } private void TextBoxTextChange(object sender, EventArgs e) { //保存操作 } configManager.AddReader(typeof(TextBox).ToString(), new ConfigManager.Reader(readTextBox)); configManager.AddEventBind(typeof(TextBox).ToString(), new ConfigManager.EventBind(bindTextBox)); ``` ##### 移除策略 可以通过指定控件的类型名称来移除相应的策略 ``` configManager.RemoveEventBind(typeof(TextBox).ToString()); configManager.RemoveReader(typeof(TextBox).ToString()); ```