开通了blog这么长时间,一直没来写篇文章,原因是实在太忙.…(其实也是有点偷懒).最近在开发CSDN新社区的过程中遇到了一个与配置文件操作有关的问题,觉得比较有代表性,干脆就以此为主题,作为我的第一篇文章好了:)
需求很简单,我们需要一个XML形式的配置文件,记录了单个论坛的配置信息,现在我们就需要一个解决方案来方便的对配置信息进行存取.
脑子几乎没多想,立刻想到了使用类的序列化方式来实现.实际正是如此,很快,我的代码按我的想法就出来了.
一个RoomConfig类,包含room的基本信息,既有基础数据类型,也有对象在里面.代码片段如下:

members#region members
private int rommID = -1;
private OpWithOneTemplate list = new OpWithOneTemplate();
//
.
#endregion


public properties#region public properties

public int RoomID

{
get

{
return rommID;
}
set

{
rommID = value;
}
}

public OpWithOneTemplate List

{
get

{
return list;
}
set

{
list = value;
}
}
//
#endregion
接下来定义一个ConfigManager.把存取操作的细节封装.
部分代码如下:
public class ConfigManager

{

make config#region make config

public static void MakeConfig(RoomConfig config, string filePath)

{
XmlSerializer formatter = new XmlSerializer(typeof(RoomConfig));
FileStream fs = new FileStream(filePath, FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(fs, config);
fs.Close();
}
#endregion


get config#region get config

public static RoomConfig2 GetConfig(string filePath)

{
XmlSerializer formatter = new XmlSerializer(typeof(RoomConfig));
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
RoomConfig config = (RoomConfig2)formatter.Deserialize(fs);
fs.Close();
return config;
}
#endregion
}
这样,就完成了需求,过程非常轻松.但,很快,我就从蝈蝈那里得到了新需求:必须使用,net2.0的推荐的方式对配置文件进行操作.参考了他的文章:http://blog.joycode.com/ghj/archive/2006/02/11/71309.aspx
本以为按着例子写一遍OK了,但实际上由于这里的配置对象包含子对象,直接用类似
config.Sections.Add("SettingsData", configData);
config.Save();
的方式立刻出错了,无法把对象和string进行转换.
然后试了许多方法,总是没法解决这个问题,现在想起来,始终是我把问题想的过于简单,这里面,需要额外做的工作还很多.
首先把RoomConfig从ConfigurationSection继承,顾名思义,这是表示一个section,里面还包含子对象;
在此处,我们包含了一个OpWithOneTemplate对象,我们对这个类也需要做额外的事.
把它从 ConfigurationElement继承,其实这种关系很明显,是section的单个对象.类里面的操作,与RoomConfig的属性操作大同小异,可以参照上面提到的蝈蝈的文章.
如果你的子对象包含的都是基础数据类型,那OK,到这一步,就算完成了,但偏偏在这里OpWithOneTemplate还包含子对象,并且那个子对象还是个集合类型!
又郁闷了一阵子,跟蝈蝈大哥讨论了这个问题.得出的结论是查资料.期间,我们参考了企业库的做法和http://blogs.conchango.com/pauloreichert/archive/2005/05/31/1514.aspx 这篇文章.虽然获得了许多启发,但依然没有解决问题.
郁闷的下班回去思考,最后换了一个思路终于解决了这个问题.集合的呈现,问题就在于无法自动的给你生成列表(实际上后来证明是可以的),那么我就给集合类增加一个专门用于写入配置文件的属性,这个属性代表了集合里的核心数据,并且通过它可以转换回数据集合.代码如下:(注,RoleList为OpWithOneTemplate包含的子类)
[Serializable()]
public class RoleList : ConfigurationElement

{

Private Static Variables#region Private Static Variables
private readonly ConfigurationProperty _propRoles;
private ConfigurationPropertyCollection _properties;
#endregion


members#region members
private ArrayList roles = new ArrayList();
#endregion


public properties#region public properties

public ArrayList Roles

{
get

{
MakeRoles(RoleString);
return roles;
}
set

{
roles = value;
}
}

[ConfigurationProperty("roles")]
public string RoleString

{
get

{
return (string)base[this._propRoles];
}
set

{
MakeRoles(value);
base[this._propRoles] = value;
}
}


/**//// <summary>
/// read only
/// </summary>
public int Count

{
get

{
return roles.Count;
}
}
#endregion


construct#region construct
public RoleList()

{
this._propRoles = new ConfigurationProperty("roles", typeof(string), null, ConfigurationPropertyOptions.IsRequired);
this._properties = new ConfigurationPropertyCollection();
this._properties.Add(this._propRoles);
this.Add(RoleEnum.Administrator);
}
#endregion


methods#region methods
public void Add(RoleEnum role)

{
if (!HasRole(role))

{
roles.Add(role);
base[this._propRoles] = GetRolesString();
}
}


/**//// <summary>
/// 队列里是否存在某角色
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
public bool HasRole(RoleEnum role)

{
foreach (RoleEnum rl in roles)

{
if (rl == role)
return true;
}
return false;
}


/**//// <summary>
/// 返回角色字符串
/// </summary>
/// <returns></returns>
public string GetRolesString()

{
string str = string.Empty;
foreach (RoleEnum rl in roles)

{
str += rl.ToString() + ";";
}
return str;
}


/**//// <summary>
/// 反向生成角色队列
/// </summary>
/// <param name="str"></param>
private void MakeRoles(string str)

{

string[] list = str.Split(new char[]
{';'},StringSplitOptions.RemoveEmptyEntries);
foreach (string li in list)

{
Add((RoleEnum)Enum.Parse(typeof(RoleEnum), li));
}
}
#endregion
}
这样,终所有的配置类里的信息都可以在配置文件里呈现了.
正当我兴冲冲跑来上班,要告诉蝈蝈我的解决方案时,蝈蝈却有了更好的解决方案,这里帮他介绍下,呵呵
这种方法依然是严格依照.net推荐的方式进行,处理集合时,使用ConfigurationElementCollection,上面提到的RoleList从这个类派生,具体的集合对象再细化成一个类(上面的方法是直接把数据封存到list里面了)
关键的地方还是RoleList,从ConfigurationElementCollection派生后,需要重写2个函数
protected override ConfigurationElement CreateNewElement()

{
//throw new Exception("The method or operation is not implemented.");
return new Role(RoleEnum.Administrator);
}

protected override object GetElementKey(ConfigurationElement element)

{
//throw new Exception("The method or operation is not implemented.");
Role r = element as Role;
if (r == null)
return "Administrator";
else
return r.RoleName;
}
这样,在返回集合对象时,将按上面的函数来创建单个对象,这也就是为什么要把数据再进一步封到一个类里的原因,要不Create函数就没法返回了.
Role类非常简单,如下:

/**//// <summary>
/// 只是单纯的把一个枚举封装起来,目的只是要使枚举值可被操作(从ConfigurationElement继承).
/// </summary>
public class Role : ConfigurationElement

{
public Role(RoleEnum e)

{
this["RoleName"] = e;
}

[ConfigurationProperty("RoleName")]
public RoleEnum RoleName

{
get

{
return (RoleEnum)this["RoleName"];
}
set

{
this["RoleName"] = value;
}
}
到这里,3种配置文件存取的方法都介绍完了,写的很乱,也不知道对大家会不会有用,各取所需好了:)
参考文献:
http://blog.joycode.com/ghj/category/1257.aspx
http://blogs.conchango.com/pauloreichert/archive/2005/05/31/1514.aspx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述