从配置文件加载设置
如何在不重新编译代码的情况下从 app.config 加载设置。
引言
本文展示了如何在 Visual Studio 中从配置文件加载应用程序设置,而无需重新编译代码。如果您的项目是单个 EXE,则 .NET 会自动提供此功能。但是,当我尝试用 DLL 做同样的事情时,此功能对我不起作用,应用程序启动时未加载配置文件。有很多相关的文章,但我找不到随时可用的解决方案。因此,我决定花一些时间贡献这篇文章。我希望它对像我一样的人有用...
背景
最近,我一直在开发一个需要高度可配置性的插件(DLL),包括用户和应用程序级别。我的首选是利用 .NET Framework 提供的 app.config 机制。使用此机制,可以在 Visual Studio 前端方便地定义应用程序和用户设置。并且这些设置可以通过 My.Settings 对象立即在代码中使用。此外,系统会自动创建一个与二进制文件一起存储的配置文件。如果需要更新 My.Settings,应该可以使用 Reload() 方法。到目前为止,一切都很好...不幸的是,我发现应用程序启动时不会加载配置文件。这意味着如果用户手动修改配置文件,则不会反映新值。为了更改配置设置,用户必须使用 Visual Studio 然后重新编译代码! . 所以,如果我们想在大量的用户/机器之间重新分发新的配置文件,则不会使用新的设置。我简直不敢相信这对 Microsoft 的人来说是正确的行为,所以我开始寻找解决方案。在花了一些时间寻找解决方案后,我决定编写自己的代码来重新加载 .NET 提供的配置文件中的设置值。
使用代码
为了演示这个概念,我用 VB.NET 创建了一个小型测试应用程序。该应用程序从配置文件加载设置,并将其显示为属性网格。 如下所示:
用户可以通过文件->编辑打开配置文件进行编辑,在他喜欢的编辑器中修改设置,然后使用文件->重新加载将这些值重新加载到应用程序中。
配置文件解析器的实现在 SettingsHelper.vb 模块中提供。必须从检索配置文件句柄开始。
Dim config = ConfigurationManager.OpenExeConfiguration(My.Application.Info.AssemblyName + ".exe")
可以如下访问配置文件的各个部分:
Dim settingsSection As ClientSettingsSection = config.GetSection(sectionName)
然后,需要复制每个设置并将其从字符串转换为其实际类型。可以从 My.Settings 项目中恢复此类型。
For Each st As SettingElement In settingsSection.Settings
'get setting name and value
Dim name As String = st.Name
Dim value As String = st.Value.ValueXml.InnerText
'skip unknown settings
Dim mySettingsItem = My.Settings.Item(name)
If mySettingsItem Is Nothing Then
Continue For
End If
'get setting type
Dim itemType = mySettingsItem.GetType
'check setting type name
'some types require special treatment
If itemType.Name = "StringCollection" Then
mySettingsItem.Clear()
'populate new string collection
Dim arrayOfString = st.Value.ValueXml.SelectNodes("ArrayOfString/string")
For i = 0 To arrayOfString.Count - 1
Dim newString = arrayOfString.Item(i).InnerText
mySettingsItem.Add(newString)
Next
ElseIf itemType.Name = "Color" Then
If value.Contains(",") Then
Dim rgbValues As String() = value.Split(",")
Dim r As Integer = Convert.ToInt32(rgbValues(0))
Dim g As Integer = Convert.ToInt32(rgbValues(1))
Dim b As Integer = Convert.ToInt32(rgbValues(2))
mySettingsItem = Color.FromArgb(r, g, b)
Else
mySettingsItem = Color.FromName(value)
End If
Else
'try to cast
Try
mySettingsItem = CTypeDynamic(value, itemType)
Catch ex As Exception
MsgBox("Cannot read " + name + " from config file!", MsgBoxStyle.Critical)
Continue For
End Try
End If
'update My.Settings
My.Settings.Item(name) = mySettingsItem
Next
请注意,某些类型无法直接转换,需要特殊处理。在当前的示例中,我们处理最常用的 StringCollection 和 Color。但是,您可能需要扩展此代码以处理更复杂的类型。一旦成功检索到项目值,它将被设置回 My.Settings 对象中。
兴趣点
重要的是要记住,Visual Studio 创建的原始 app.config 文件在代码编译后被复制到 Bin 目录中。根据您的情况,您可能不想覆盖 USER 设置,而只想覆盖 APPLICATION 设置。用户设置允许为每个用户自定义应用程序行为,因此这些设置的值是单独存储的。