具有惰性写入功能的基于 XML 的注册表






1.29/5 (14投票s)
2003年9月2日
4分钟阅读

98301

1030
实现了一个基于 XML 文件和延迟写入机制的注册表等效功能。
概述
Microsoft 通过 .NET 解决的一个问题是大多数应用程序所需的复杂安装过程。 .NET 应用程序不需要任何复杂的安装过程(假设 .NET Framework 已部署),允许 .NET 应用程序通过简单地将应用程序文件复制到目标位置来部署。此目标可以是用户需要使用该应用程序的可访问的网络目录。
然而,在这种情况下有一个小问题:从共享网络驱动器部署的 .NET 应用程序不应依赖注册表,原因如下:
- 这违背了将应用程序的所有部分私有化的理念,并且
- 应用程序将不得不使用远程注册表调用,以确保它写入其所在服务器的注册表,而不是调用应用程序的机器的注册表 – 至少对于应用程序的配置数据而言。
幸运的是,由于 .NET 库对 XML 的广泛支持,编写一个基于 XML 的注册表替代品相对容易。此处介绍的 XmlRegistry
类就是这样一种实现。此处介绍的 XmlRegistry
和 XmlRegistryKey
类是模仿 .NET Framework 中的 Registry
和 RegistryKey
类而设计的。
在内部,这些类将 XML 元素用作子键的等效项,将 XML 属性用作值。
特点
在写入文档类型存储(与数据库或注册表等面向记录的存储相反)时,例如 XML 文件,一个问题是即使文档的一小部分发生更改,整个文档都需要保存。试图通过最小化保存次数来优化这一点可能会很麻烦,而不进行优化则会带来不可接受的性能损失。
XmlRegistry
类(可选)实现了延迟写入机制来解决此问题:当一个键被更新时,会启动一个延迟保存线程。该线程不会立即保存文件,而是先休眠用户指定的间隔时间。在此休眠期间,可以修改其他几个键,而无需每次都保存整个文件。最终,文件会被保存。
注册表在内部同步以处理写入和延迟保存之间的冲突,但它不对多个读/写线程进行同步。对于此类多线程使用,用户应使用自己的锁定机制。
然而,如果用户不想使用延迟写入机制,他们可以简单地使用 Save()
成员来显式保存文件。
详细说明
有两种类实现了 XML 注册表:XmlRegistry
和 XmlRegistryKey
– 模仿 .NET 的 Registry
和 RegistryKey
类。要使用此实现,您首先需要实例化一个 XmlRegistry
类对象。有几个构造函数可用
-
XmlRegistry(string filename)
这是最简单的构造函数。如果需要,文件扩展名必须是文件名的一部分。如果同名文件存在,它将被打开并将 XML 数据读入内存。如果文件不存在,将在内存中创建一个带有名为“root”的根节点的空 XML 文档 – 但不会保存在磁盘上。
-
XmlRegistry(string filename, string rootkeyname, string encoding)
此构造函数允许用户指定根键名称(对于空文档)和文件的 XML 编码。如果文件已存在,其 XML 根元素的名称必须与
rootkeyname
匹配,否则将抛出异常。 -
public XmlRegistry(string filename, ErrorDelegate errhandler, int writedelay)
此构造函数启用延迟写入功能,并允许您指定延迟(以毫秒为单位)。
-
public XmlRegistry(string filename, string rootkeyname, string encoding, ErrorDelegate errhandler, int writedelay)
此构造函数也启用延迟写入功能,并允许您指定一个异步错误处理委托。该委托将在保存文件的线程上调用,而不是在执行注册表调用的线程上调用,因此其实现中必须使用适当的同步。
其他方法
-
XmlRegistry.Save()
无论是否启用了延迟写入功能,此方法都会导致文件保存。如果启用了延迟写入功能,保存将在单独的线程上进行,但保存延迟将被缩短。
-
XmlRegistryKey XmlRegistryKey.GetSubKey(string path, bool createpath)
指定的路径是相对路径,子键用“/”字符分隔。例如,如果引用的键是“root/application”,并且调用该方法时的 path 参数等于“configuration/cache”,则返回的子键将引用“root/application/configuration/cache”的完整路径。
createpath
参数指定是否应自动创建路径中任何缺失的元素。如果设置为false
,并且完整路径不存在,则将返回 null 值。
用法
使用 XmlRegistry
类非常简单
// create an xml registry file "reg1.xml",
// no error delegate
// a write delay of 200ms
XmlRegistry r1 = new XmlRegistry("Reg1.xml", null, 200);
// get the root key
XmlRegistryKey k1 = r1.RootKey;
// get a subkey, don't create it if it doesn't exist
XmlRegistryKey k2 = k1["abc/def/ghi", false];
// get a subkey, create it if it exists
XmlRegistryKey k3 = k1["a/bc/def/ghij/klmno", true];
// set some values of the subkey
k3.SetValue("v1", 0);
k3.SetValue("v2", "Hello");
k3.SetValue("v3", true);
// get the key-value collection from the root
XmlRegistryKey[] sk = k1.GetSubKeys();
foreach (XmlRegistryKey k in sk)
{
string name = k.Name;
}
此代码片段创建一个如下所示的 XML 文件
<?xml version="1.0"?>
<XmlRegistryRoot>
<a>
<bc>
<def>
<ghij>
<klmno v1="0" v2="Hello" v3="True" />
</ghij>
</def>
</bc>
</a>
</XmlRegistryRoot>
结论
此类是一种处理 XML 文件中注册表式问题的简单方法,该文件可以是本地的或放置在服务器上。由于它会自动创建子键结构,因此非常易于使用。