话说小菜连打数个哈欠,趴在桌上就给睡着了.
开始又梦到Discuz!NT了.老大开始在骂小菜了,过了这么久还没有做好啊.赶快给我做好,不然炒了你,拿来配酒吃.
小菜不敢怠慢,连连说是.回到电脑前,伸伸懒腰,马上开工.
小菜先打开general.config通用配置文件看看究竟.
<GeneralConfigInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ForumTitle>Discuz!NT</ForumTitle>
<ForumUrl>forumindex.aspx</ForumUrl>
<Closed>0</Closed>
<CloseDreason>抱歉!论坛暂时关闭,稍后才能访问.</CloseDreason>
<RegStatus>1</RegStatus>
</GeneralConfigInfo>
1)都是XML文件
2)ForumTitle : 论坛名称
ForumUrl : 论坛首页名称
Closed : 论坛关闭 (0为开启 1为关闭)
CloseDreason : 论坛关闭时提示信息
RegStatus : 允许新用户注册 (0不允许 1允许)
按照之前的设计思路,小菜直接就想到了为其定义一个GeneralConfigInfo通用配置文件描述类
然后定义一个GeneralConfigFileManager通用配置文件管理类来管理它
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件描述类 支持序列化与反序列化
/// </summary>
[Serializable]
public class GeneralConfigInfo
{
private string m_forumTitle; //论坛名称
private string m_forumUrl; //论坛URL地址
private int m_closed; //论坛关闭 (0开 1关闭)
private string m_closeDreason; //论坛关闭提示信息
private int m_regStatus; //允许新用户注册 (0不允许 1允许)
/// <summary>
/// 论坛名称
/// </summary>
public string ForumTitle
{
get
{
return m_forumTitle;
}
set
{
m_forumTitle = value;
}
}
/// <summary>
/// 论坛URL地址
/// </summary>
public string ForumUrl
{
get
{
return m_forumUrl;
}
set
{
m_forumUrl = value;
}
}
/// <summary>
/// 论坛关闭 (0开 1关闭)
/// </summary>
public int Closed
{
get
{
return m_closed;
}
set
{
m_closed = value;
}
}
/// <summary>
/// 论坛关闭提示信息
/// </summary>
public string CloseDreason
{
get
{
return m_closeDreason;
}
set
{
m_closeDreason = value;
}
}
/// <summary>
/// 允许新用户注册 (0不允许 1允许)
/// </summary>
public int RegStatus
{
get
{
return m_regStatus;
}
set
{
m_regStatus = value;
}
}
}
}
接着定义GeneralConfigFileManager设计类似BaseConfigFileManager.
using System.IO;
using System.Web;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件管理类
/// </summary>
public class GeneralConfigFileManager
{
private static GeneralConfigInfo m_configInfo; //通用配置信息描述对象
private static string m_configFileName = "general.config"; //通用配置文件名称
private static string m_configDirectory; //通用配置文件所在目录
private static string m_configFilePath; //通用配置文件路径
private static FileSystemWatcher watcher; //文件监测者
static GeneralConfigFileManager()
{
m_configInfo = DeserializeInfo();
watcher = new FileSystemWatcher();
watcher.NotifyFilter = NotifyFilters.LastWrite; //监测上一次向文件写入内容的日期
watcher.Path = ConfigDirectory; //监测目录
watcher.Filter = m_configFileName; //监测文件
watcher.Changed += new FileSystemEventHandler(OnChanged);//监测文件被修改时委托调用OnChanged
watcher.EnableRaisingEvents = true; //开始监测
}
/// <summary>
/// 通用配置文件所在目录
/// </summary>
private static string ConfigDirectory
{
get
{
if (m_configDirectory == null)
{
m_configDirectory = ConfigFilePath.Substring(0, ConfigFilePath.LastIndexOf('\\'));
}
return m_configDirectory;
}
}
/// <summary>
/// 通用配置文件路径
/// </summary>
private static string ConfigFilePath
{
get
{
if (m_configFilePath == null)
{
HttpContext current = HttpContext.Current;
m_configFilePath = current.Server.MapPath("~/config/" + m_configFileName);
if (!File.Exists(m_configFilePath))
{
throw new Exception("发生错误: 网站config目录中没有正确的general.config文件");
}
}
return m_configFilePath;
}
}
/// <summary>
/// 返回论坛名称
/// </summary>
public static string GetForumTitle
{
get
{
return m_configInfo.ForumTitle;
}
}
/// <summary>
/// 监测文件被修改时委托调用OnChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected static void OnChanged(object sender, FileSystemEventArgs e)
{
m_configInfo = DeserializeInfo();
}
/// <summary>
/// 反序列化通用配置信息描述类
/// </summary>
/// <returns></returns>
private static GeneralConfigInfo DeserializeInfo()
{
GeneralConfigInfo configInfo;
FileStream fs = null;
try
{
fs = new FileStream(ConfigFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XmlSerializer serializer = new XmlSerializer(typeof(GeneralConfigInfo));
configInfo = (GeneralConfigInfo)serializer.Deserialize(fs);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (fs != null)
fs.Close();
}
return configInfo;
}
}
}
测试Response.Write(Discuz.Config.GeneralConfigFileManager.GetForumTitle);
输出: Discuz!NT
将general.config配置文件中的<ForumTitle>Discuz!NT</ForumTitle>结点的值修改为 小菜论坛
刷新,立马看到 小菜论坛
接下来还有urls.config ,spread.config等等一大堆,Ctrl+C,Ctrl+V可不是好主意,因为重复的代码太多了.
虽然小菜有点菜,但是小菜立志向上发展.所以坚决不做代码工人.
小菜要做工匠.所以觉得应该第二次重构下代码
前一次重构是在 小菜梦游Discuz!NT (第三篇 配置文件处理2) 修理代码.BaseConfigFileManager
重构: BaseConfigFileManager与GeneralConfigFileManager代码重复太多,接下来还有UrlsConfigFileManager重复将更多.所以小菜决定为他们定义一个基类DefaultConfigFileManager
1)DeserializeInfo()函数首当其冲,几乎完全一样.要想改造它,除非BaseConfigInfo与GeneralConfigInfo有共同的基类
或接口,小菜决定定义一个空接口IConfigInfo然后让BaseConfigInfo与GeneralConfigInfo实现它.
namespace Discuz.Config
{
/// <summary>
/// 配置文件描述接口
/// </summary>
public interface IConfigInfo
{
}
}
namespace Discuz.Config
{
/// <summary>
/// 基本配置文件描述类 支持序列化与反序列化
/// </summary>
[Serializable]
public class BaseConfigInfo : IConfigInfo
{
省略
}
}
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件描述类 支持序列化与反序列化
/// </summary>
[Serializable]
public class GeneralConfigInfo : IConfigInfo
{
省略
}
}
using System.IO;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 配置文件管理基类
/// </summary>
public abstract class DefaultConfigFileManager
{
/// <summary>
/// 反序列化配置信息描述类
/// </summary>
/// <returns></returns>
public static IConfigInfo DeserializeInfo(string configFilePath, Type configType)
{
IConfigInfo configInfo;
FileStream fs = null;
try
{
fs = new FileStream(configFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XmlSerializer serializer = new XmlSerializer(configType);
configInfo = (IConfigInfo)serializer.Deserialize(fs);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (fs != null)
fs.Close();
}
return configInfo;
}
}
}
改造后的代码为
using System.IO;
using System.Web;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 基本配置文件管理类
/// </summary>
public class BaseConfigFileManager : DefaultConfigFileManager
{
private static BaseConfigInfo m_configInfo; //基本配置信息描述对象
private static string m_configFileName = "DNT.config"; //基本配置文件名称
private static string m_configDirectory; //基本配置文件所在目录
private static string m_configFilePath; //基本配置文件路径
private static FileSystemWatcher watcher; //文件监测者
static BaseConfigFileManager()
{
m_configInfo = (BaseConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(BaseConfigInfo));
watcher = new FileSystemWatcher();
watcher.NotifyFilter = NotifyFilters.LastWrite; //监测上一次向文件写入内容的日期
watcher.Path = ConfigDirectory; //监测目录
watcher.Filter = m_configFileName; //监测文件
watcher.Changed += new FileSystemEventHandler(OnChanged);//监测文件被修改时委托调用OnChanged
watcher.EnableRaisingEvents = true; //开始监测
}
/// <summary>
/// 基本配置文件所在目录
/// </summary>
private static string ConfigDirectory
{
get
{
if (m_configDirectory == null)
{
m_configDirectory = ConfigFilePath.Substring(0, ConfigFilePath.LastIndexOf('\\'));
}
return m_configDirectory;
}
}
/// <summary>
/// 基本配置文件路径
/// </summary>
private static string ConfigFilePath
{
get
{
if (m_configFilePath == null)
{
HttpContext current = HttpContext.Current;
m_configFilePath = current.Server.MapPath("~/" + m_configFileName);
}
if (!File.Exists(m_configFilePath))
{
throw new Exception("发生错误: 网站根目录下没有正确的DNT.config文件");
}
return m_configFilePath;
}
}
/// <summary>
/// 返回数据库类型
/// </summary>
public static string GetDbType
{
get
{
return m_configInfo.DbType;
}
}
/// <summary>
/// 论坛在站内的位置
/// </summary>
public static string GetForumPath
{
get
{
return m_configInfo.ForumPath;
}
}
/// <summary>
/// 监测文件被修改时委托调用OnChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected static void OnChanged(object sender, FileSystemEventArgs e)
{
m_configInfo = (BaseConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(BaseConfigInfo));
}
}
}
using System.IO;
using System.Web;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件管理类
/// </summary>
public class GeneralConfigFileManager : DefaultConfigFileManager
{
private static GeneralConfigInfo m_configInfo; //通用配置信息描述对象
private static string m_configFileName = "general.config"; //通用配置文件名称
private static string m_configDirectory; //通用配置文件所在目录
private static string m_configFilePath; //通用配置文件路径
private static FileSystemWatcher watcher;
static GeneralConfigFileManager()
{
m_configInfo = (GeneralConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(GeneralConfigInfo));
watcher = new FileSystemWatcher();
watcher.NotifyFilter = NotifyFilters.LastWrite; //监测上一次向文件写入内容的日期
watcher.Path = ConfigDirectory; //监测目录
watcher.Filter = m_configFileName; //监测文件
watcher.Changed += new FileSystemEventHandler(OnChanged);//监测文件被修改时委托调用OnChanged
watcher.EnableRaisingEvents = true; //开始监测
}
/// <summary>
/// 通用配置文件所在目录
/// </summary>
private static string ConfigDirectory
{
get
{
if (m_configDirectory == null)
{
m_configDirectory = ConfigFilePath.Substring(0, ConfigFilePath.LastIndexOf('\\'));
}
return m_configDirectory;
}
}
/// <summary>
/// 通用配置文件路径
/// </summary>
private static string ConfigFilePath
{
get
{
if (m_configFilePath == null)
{
HttpContext current = HttpContext.Current;
m_configFilePath = current.Server.MapPath("~/config/" + m_configFileName);
}
if (!File.Exists(m_configFilePath))
{
throw new Exception("发生错误: 网站config目录下没有正确的general.config文件");
}
return m_configFilePath;
}
}
/// <summary>
/// 返回论坛名称
/// </summary>
public static string GetForumTitle
{
get
{
return m_configInfo.ForumTitle;
}
}
/// <summary>
/// 监测文件被修改时委托调用OnChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected static void OnChanged(object sender, FileSystemEventArgs e)
{
m_configInfo = (GeneralConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(GeneralConfigInfo));
}
}
}
小菜就这样构造出了EmailConfigFileManager等等配置文件的管理.....
代码给老大过目..
老大说:恩不错,不过还漏了一个功能啊.修改配置文件啊.
小菜说,为何要修改配置文件呢?可以直接打开配置文件修改了...
老大接着说:打开配置文件修改...噢,,天呐..这是一件多么麻烦的事...我们的用户可是会抱怨的...让他们对着那么多不知所云的配置文件.还要让他们修改....这几乎不太可能.
所以小菜啊,你得加上这个功能.我们的Web层小组会定制具有亲和力的界面来帮助用户方便的修改配置文件...
这个界面怎么样,不错吧,,,比起直接修改配置文件要强很多吧...不过它们最终得依靠你提供的修改配置文件功能.
小菜听了老大这一番话后,马上回去修改代码..
毕竟小菜已经重构过代码了,现在添加功能已经容易很多.
在基类DefaultConfigFileManager中添加SaveConfig,派生类便可直接使用.
using System.IO;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 配置文件管理基类
/// </summary>
public abstract class DefaultConfigFileManager
{
其它略,同前面
/// <summary>
/// 保存(序列化)指定路径下的配置文件
/// </summary>
/// <param name="configFilePath">指定的配置文件所在的路径(包括文件名)</param>
/// <param name="configInfo">被保存(序列化)的对象</param>
/// <returns></returns>
public static bool SaveConfig(string configFilePath, IConfigInfo configInfo)
{
bool succeed = false;
FileStream fs = null;
try
{
fs = new FileStream(configFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
XmlSerializer serializer = new XmlSerializer(configInfo.GetType());
serializer.Serialize(fs, configInfo);
//成功则将会返回true
succeed = true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (fs != null)
{
fs.Close();
}
}
return succeed;
}
}
}
using System.IO;
using System.Web;
using System.Xml.Serialization;
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件管理类
/// </summary>
public class GeneralConfigFileManager : DefaultConfigFileManager
{
其它略,同前面
public static bool SaveConfig(IConfigInfo configInfo)
{
bool success = false;
if (configInfo is GeneralConfigInfo)
{
success = DefaultConfigFileManager.SaveConfig(ConfigFilePath, configInfo);
}
return success;
}
}
}
现在就让我们来测试一下.
我们修改打算修改general.config配置文件的论坛名称.从 Discuz!NT 修改为 小菜论坛 .
1)第一步.
先测试一下,论坛名称是什么.Response.Write("论坛名称:" + GeneralConfigFileManager.GetForumTitle);
输出:Discuz!NT
2)第二步.
修改论坛名称.
using Discuz.Config;
public partial class forumindex : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
GeneralConfigInfo configInfo = new GeneralConfigInfo();
configInfo.ForumTitle = "小菜论坛";
configInfo.ForumUrl = "forumindex.aspx";
configInfo.Closed = 0;
configInfo.CloseDreason = "抱歉!论坛暂时关闭,稍后才能访问.";
configInfo.RegStatus = 1;
Response.Write("是否修改配置成功:" + GeneralConfigFileManager.SaveConfig(configInfo).ToString());
Response.Write(",论坛名称:" + GeneralConfigFileManager.GetForumTitle);
}
}
程序输出:是否修改配置成功:True,论坛名称:Discuz!NT
奇怪了.修改成功.论坛名字为什么还是Discuz!NT而不是小菜论坛
到general.config中看一下
已经修改过来了,而且是还很正常.为小菜论坛 .
而且程序抛出了异常(XML文档0,0中有错误.奇怪了.general.config明明很正常)...这是为什么呢?
小菜决定把这个异常注释掉看看程序是否会照常运行.
//throw ex;
把general.config中的论坛名称重新改为Discuz!NT
运行.
程序输出:是否修改配置成功:True,论坛名称:Discuz!NT
刷新后
程序输出:是否修改配置成功:True,论坛名称:小菜论坛
一切正常.....小菜也不知道那个异常到底是为什么?希望高人指点.
这里谢谢@zahota : 小菜将DefaultConfigFileManager中的SaveConfig方法中的
fs = new FileStream(configFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
修改为
fs = new FileStream(configFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
就没有问题了,可以把上面的 //throw ex; 注释放心的去掉了.
原因是小菜也说不清楚,还是不说好,大家可以看下SDK2.0
快接近尾声了.
让我们来看看还有哪些不足.
很明显,我们修改论坛名时的代码
GeneralConfigInfo configInfo = new GeneralConfigInfo();
configInfo.ForumTitle = "小菜论坛";
configInfo.ForumUrl = "forumindex.aspx"; //我们不想要
configInfo.Closed = 0; //我们不想要
configInfo.CloseDreason = "抱歉!论坛暂时关闭,稍后才能访问."; //我们不想要
configInfo.RegStatus = 1; //我们不想要
除了一二两句,其它我们并不想要.因为我们只是想修改论坛名称而已.
但是不要又会出错,因为序列化的XML文件不完整.
怎么办呢?很简单.在GeneralConfigInfo代码中.为私有成员初始化便可.
namespace Discuz.Config
{
/// <summary>
/// 通用配置文件描述类 支持序列化与反序列化
/// </summary>
[Serializable]
public class GeneralConfigInfo : IConfigInfo
{
private string m_forumTitle = "Discuz!NT"; //论坛名称
private string m_forumUrl = "forumindex.aspx"; //论坛URL地址
private int m_closed = 0; //论坛关闭 (0开 1关闭)
private string m_closeDreason = ""; //论坛关闭提示信息
private int m_regStatus = 1; //允许新用户注册 (0不允许 1允许)
/// <summary>
/// 论坛名称
/// </summary>
public string ForumTitle
{
get
{
return m_forumTitle;
}
set
{
m_forumTitle = value;
}
}
/// <summary>
/// 论坛URL地址
/// </summary>
public string ForumUrl
{
get
{
return m_forumUrl;
}
set
{
m_forumUrl = value;
}
}
/// <summary>
/// 论坛关闭 (0开 1关闭)
/// </summary>
public int Closed
{
get
{
return m_closed;
}
set
{
m_closed = value;
}
}
/// <summary>
/// 论坛关闭提示信息
/// </summary>
public string CloseDreason
{
get
{
return m_closeDreason;
}
set
{
m_closeDreason = value;
}
}
/// <summary>
/// 允许新用户注册 (0不允许 1允许)
/// </summary>
public int RegStatus
{
get
{
return m_regStatus;
}
set
{
m_regStatus = value;
}
}
}
}
小菜梦游Discuz!NT配置文件处理部份完成,源代码:https://files.cnblogs.com/a-peng/newbie_config.rar