65.9K
CodeProject 正在变化。 阅读更多。
Home

简化 .NET 配置

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.20/5 (4投票s)

2008年9月18日

CPOL

6分钟阅读

viewsIcon

27696

downloadIcon

192

.NET Configuration 命名空间的一个简化封装。

引言

毫无疑问,.NET 的 Configuration 命名空间功能强大。但这也有代价。它非常庞大。而且现有的文档和示例并不太好。

说实话,文档倒不怎么困扰我。让我困扰的是,尽管现有的框架可能能实现我想要的一切,但发现这些功能并不直观。

例如:

  1. 为什么我必须创建一个新的 ExeConfigurationFileMap 对象才能更改系统读取配置文件路径的地方?抱歉,这和通过喊叫来加速汽车一样不直观。
  2. 那些荒谬的 GUID/hash/hex 命名的文件夹是从哪里来的?这些是系统默认存储用户级别配置文件的地方。方便升级?是啊,也许吧,但难道没有更好的方法吗?
  3. 注册 ConfigurationSection 处理程序?嗯?为什么我必须将应用程序内部类的完整类名写到配置文件中,才能让 .NET 读取它们?

背景

我一直在寻找一种简单的方法来创建一个像这样的类:

Public Sub MySettingClass
  Public Setting1 as string = ""
  Public Setting2 as Integer = 0
End Class

无需显式使用属性,除非你需要它们。无需属性。甚至你都不应该声明类为 <Serializable>,尽管这一点倒是小事。

与其与 My.Settings 空间共存,不如它应该能够将自身持久化到配置文件中,然后在被要求时将其反序列化回来,就像这样:

Settings = New MySettingsClass
Settings.Load
...
Settings.Save

访问你的设置应该是完全早期绑定的,并内置了所有那些令人愉悦的 Intellisense 功能。

x = Settings.Setting1
y = Setting.Setting2

此外,我应该能够轻松地持久化子对象或集合,这些对象或集合可以通过根设置对象访问。例如,要保存一个窗体的当前位置和大小,然后恢复它,应该需要类似以下的代码:

Settings.FormPositions.Save(MyForm)
Settings.FormPositions.Restore(MyForm)
Debug.print "Form position is " & Settings.FormPositions(0).Position

以及一些额外的要求:

  • 首先,没有初始配置文件应该不是问题。当没有配置文件存在时,所有设置应该很容易地默认为某些“内置”默认值。
  • 其次,我应该能够立即上手。换句话说,我应该能够将设置基类的.VB文件,将其放入我的应用程序中,添加一个具有我需要的持久化属性的设置类,以及在项目的适当位置添加一个.LOAD和一个.SAVE,然后就可以开始了。无需“预设置”我的配置文件,无需调整任何东西,无需注册这个那个,无需搞乱 GAC 等等。

研究

可用的 Microsoft 配置系统文档是如此令人困惑,我相信在我读完文档后,我对它的了解比开始时还要少。

我确实找到了 CodeProject 上 Jon Rista 撰写的一篇非常好的文章,名为 Cracking the Mysteries of .NET 2.0 Configuration。如果你正在深入研究这些东西,绝对值得一读。

虽然 Jon 提供了几个代码示例,但没有一个真正阐明了我所寻找的。然而,文章中的信息足够多,足以让我开始。

长话短说,事实证明,.NET 中的配置系统,以典型的微软风格,功能强大,但对于许多小型应用程序场景来说却有点过度。

Using the Code

虽然这仍然是一个正在进行中的项目,但到目前为止它已被证明非常有用,所以我认为其他人也可能会发现它很有用。

该系统由一个文件组成,SettingsBase.vb。它定义了两个类,SettingsBaseSettingsBaseDictionary

SettingsBaseDictionary 只是对普通通用 Dictionary 类的一个简单扩展,允许它通过 XML 进行序列化。这是我在网上找到的,对于设置来说非常方便,所以我直接将其包含在文件中。

SettingsBase 是一个抽象类。要使用它,你必须创建自己的设置类(可以任意命名),并继承自 SettingsBase

Public Class Settings
   Inherits SettingsBase
 
  Public Name As String = ""
  Public Phone As String = ""
End Class

当你想要加载你的设置时,只需实例化你的 Settings 对象并调用 Settings.Load。要更改设置,像往常一样设置对象的属性即可。

要保存你的设置,调用 Settings.Save

最后,你需要添加对 System.Configuration 的引用。直接访问 ConfigurationManagerEXEConfigurationFileMap 对象需要它。

我包含的示例项目展示了从非常简单到中等复杂的几个例子。我甚至还包含了一个非常简单的关于数据绑定到设置属性的例子(在这种情况下,是一个联系人Dictionary)。

关注点

  • 你的设置文件将默认写入 CommonApplicationData 文件夹,然后在其中,有一个名为你的程序集信息屏幕中的 CompanyName 的文件夹,再然后,有一个名为你的程序集信息屏幕中的 Application Name 的文件夹。
  • Screen2.png

    在 Windows XP 下,这意味着你会在 c:\Documents and Settings\All Users\Application Data\{CompanyName}\{AppName}\Settings.config 中找到默认的设置文件,而在 Vista 下,则是在 c:\Program Data\{CompanyName}\{AppName}\Settings.config 中。

  • 这是配置文件相当标准的做法。
  • 你只需更改你的设置对象的关联属性(这些属性都继承自 SettingsBase 对象),即可更改设置文件名、公司名称和产品名称。
  • 虽然你可以在你的基类 Settings 对象中使用字段,但你无法使用任何数据绑定支持。这是 .NET 数据绑定支持的限制,而不是设置类的限制。坦白说,这很糟糕。有时完全的属性是有意义的,但在这种情况下,属性的工作量更大,但效果相同。
  • 如果你想在你的设置类中使用数据绑定,最好一开始就把你的设置类的所有持久化元素声明为属性,并且完全避免使用字段。

  • SettingsBase 对象甚至不尝试提供对配置“节”或“节组”的访问。你可以通过使用主设置对象(继承自 SettingsBase 的那个)的“子对象”来轻松地将设置分解成组或节。我在示例应用程序中说明了这一点。
  • 正如我之前提到的,这一切很可能都可以通过创建一个自定义 ConfigurationSection 类并将其注册到你的配置文件中来完成;但从我目前看来,这意味着你必须手动向配置文件添加垃圾。对我来说,这有一种代码异味,就像隔壁格子间里那个整天烧广藿香的家伙一样。它本身并不臭,但如果你待得够久,它确实会让你流泪。
  • 这里没有太多的错误处理。通常,异常会从这个类中冒出来。

下一步

  • 说真的,这应该可以封装在一个自定义 ConfigurationSection 处理程序中。我对此方法的唯一抱怨是它没有解决文件夹命名问题,并且需要对节处理程序进行笨拙的注册。我打赌总有解决这两个问题的办法,只是我还没找到。
  • 同样,我真的很想找到一种方法来实现我的想法,并且仍然使用 Visual Studio 自动定义的 My.Settings 命名空间。我正在努力解决这个问题,但这种简单的方法对最近我需要快速完成的实用工具应用程序很有效。

历史

  • 2008 年 9 月:第一个版本。
© . All rights reserved.