ConfigurationManager.AppSettings 每次都从web.config文件中读取?
我只是想知道如何ConfigurationManager.AppSettings [Key]的作品?
每次我需要一个密钥时,是否从物理文件中读取?
如果是这样,我应该读取我的web.config在caching中的所有应用程序设置,然后从中读取?
或者ASP.NET或IIS在application_startup中加载web.config文件,并且只加载一次。
如何validation每次读取是否访问物理文件?
如果我更改web.config,IIS重新启动我的应用程序,所以无法validation它的方式。
谢谢,
它在第一次访问属性时被caching,所以每次你询问一个值时它都不会从物理文件中读取。 这就是为什么需要重新启动Windows应用程序(或刷新configuration)以获取最新值,以及为什么在编辑web.config时ASP.Net应用程序会自动重新启动。 为什么ASP.Net硬连接重新启动在答案中的参考文献中讨论如何防止ASP.NET应用程序在web.config被修改时重新启动 。
我们可以使用ILSpy来validation这一点,并查看System.Configuration的内部:
public static NameValueCollection AppSettings { get { object section = ConfigurationManager.GetSection("appSettings"); if (section == null || !(section is NameValueCollection)) { throw new ConfigurationErrorsException(SR.GetString("Config_appsettings_declaration_invalid")); } return (NameValueCollection)section; } }
起初,这确实看起来每次都会得到这个部分。 看GetSection:
public static object GetSection(string sectionName) { if (string.IsNullOrEmpty(sectionName)) { return null; } ConfigurationManager.PrepareConfigSystem(); return ConfigurationManager.s_configSystem.GetSection(sectionName); }
这里的关键是PrepareConfigSystem()
方法; 这将初始化由ConfigurationManager保存的IInternalConfigSystem
字段的一个实例 – 具体types是ClientConfigurationSystem
作为该负载的一部分, Configuration类的一个实例被实例化。 这个类实际上是configuration文件的一个对象表示,并且似乎被ClientConfigurationSystem的ClientConfigurationHost属性保存在一个静态字段中 – 因此被caching。
您可以通过执行以下操作(在Windows窗体或WPF应用程序中)来validation这一点:
- 启动您的应用程序了
- 在app.config中访问一个值
- 对app.config进行更改
- 检查新值是否存在
- 调用
ConfigurationManager.RefreshSection("appSettings")
- 检查新值是否存在。
事实上,如果我刚刚阅读了关于RefreshSection方法的评论,我可以节省一些时间:-)
/// <summary>Refreshes the named section so the next time that it is retrieved it will be re-read from disk.</summary> /// <param name="sectionName">The configuration section name or the configuration path and section name of the section to refresh.</param>
简单的答案是不,它并不总是从文件中读取。 正如一些人build议,如果文件被更改,然后IIS执行重新启动,但并不总是! 如果你想保证你正在从文件中读取最新的值,而不是caching,你需要调用这样的东西:
ConfigurationManager.RefreshSection("appSettings"); string fromFile = ConfigurationManager.AppSettings.Get(key) ?? string.Empty;
我在我的代码中使用了一个例子:
/// ====================================================================================== /// <summary> /// Refreshes the settings from disk and returns the specific setting so guarantees the /// value is up to date at the expense of disk I/O. /// </summary> /// <param name="key">The setting key to return.</param> /// <remarks>This method does involve disk I/O so should not be used in loops etc.</remarks> /// <returns>The setting value or an empty string if not found.</returns> /// ====================================================================================== private string RefreshFromDiskAndGetSetting(string key) { // Always read from the disk to get the latest setting, this will add some overhead but // because this is done so infrequently it shouldn't cause any real performance issues ConfigurationManager.RefreshSection("appSettings"); return GetCachedSetting(key); } /// ====================================================================================== /// <summary> /// Retrieves the setting from cache so CANNOT guarantees the value is up to date but /// does not involve disk I/O so can be called frequently. /// </summary> /// <param name="key">The setting key to return.</param> /// <remarks>This method cannot guarantee the setting is up to date.</remarks> /// <returns>The setting value or an empty string if not found.</returns> /// ====================================================================================== private string GetCachedSetting(string key) { return ConfigurationManager.AppSettings.Get(key) ?? string.Empty; }
这使得您可以非常容易地select(以及在阅读代码时看到)每次获取最新值,还是不希望应用程序启动时的值发生变化。
var file = new FileInfo(@"\\MyConfigFilePath\Web.config"); DateTime first = file.LastAccessTime; string fn = ConfigurationManager.AppSettings["FirstName"]; Thread.Sleep(2000); DateTime second = file.LastAccessTime; string sn = ConfigurationManager.AppSettings["Surname"]; Thread.Sleep(2000); DateTime third = file.LastAccessTime;
都显示相同的LastAccessTime,这意味着它在启动时被caching。
string fn1 = ConfigurationManager.AppSettings["FirstName"]; Thread.Sleep(2000); DateTime fourth = file.LastAccessTime;