Изучение обработчиков разделов настроек
Итак, я уже описал, где следует вводить параметры, как эти параметры наследуются, как указать, к чему они относятся, и как их заблокировать. Теперь давайте рассмотрим, как используются настроечные параметры. Обработчики разделов настроек обрабатывают параметры, указанные в настроечных файлах, и делают их доступными для приложений. Обработчики разделов настроек – это классы, которые реализуют интерфейс IConfigurationSectionHandler. Данные классы интерпретируют и обрабатывают параметры из настроечного файла и возвращают объект конфигурации, основанный на этих параметрах.
Как уже было сказано ранее, обработчики разделов настроек сначала объявляются в configSections. Давайте снова посмотрим на объявление обработчика настроек.
<section name="appSettings" type="System.Configuration.NameValueFileSectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<appSettings> <add key="MyPassword" value="Secret" /> <add key="ServerIP" value="192.168.31.1" /> </appSettings>
Это объявление раздела <appSettings> настроечного файла. Данный раздел используется для хранения пар имя/значение, к которым нужно получать доступ из любого файла приложения. Данное объявление указывает настроечному файлу на класс, который будет обрабатывать этот раздел. Вот пример раздела <appSettings>, который добавляет еще две пары имя/значение.
<appSettings> <add key="MyPassword" value="Secret"> <add key="ServerIP" value="192.168.31.1"> </appSettings>
Теперь доступ к этим параметрам можно получить из приложений, что значительно облегчает отслеживание и изменение параметров, используемых на различных страницах или в приложениях. Мы знаем, где располагается объявление обработчика, но еще не увидели реального кода .NET Framework для объявления обработчика. Взглянуть на пример обработчика можно в исходном коде Microsoft Shared Source CLI Implementation (кодовое имя: Rotor), который является замечательной вещью.
Дополнительная информация. Microsoft Shared Source CLI Implementation, известная как Rotor, – это реализация с открытыми исходными текстами значительной части .NET Framework, доступная для разработчиков. Это не совсем тот код, который используется в .NET Framework, но он очень похож на него и выполняет те же функции. Однако между ними имеются многочисленные отличия, так как код Rotor разработан для того, чтобы быть наиболее переносимым и читаемым. За дополнительной информацией обратитесь по адресу http://msdn.microsoft.com/downloads/default.asp?url=/downloads/topic.asp?URL=/MSDN-FILES/028/000/123/topic.xml.
Следующий код – это обработчик раздела настроек для раздела <appSettings>, который называется NameValueFileSectionHandler. Я удалил из него код, не имеющий отношения к этому обсуждению.
//——————————————————––––––––––––——————————————— // <copyright file="NameValueFileSectionHandler.cs" company="Microsoft"> // // Copyright (c) 2002 Microsoft Corporation All rights reserved. // The use and distribution terms for this software are contained in the // file named license.txt, which can be found in the root of this // distribution. By using this software in any fashion, you are agreeing // to be bound by the terms of this license // You must not remove this notice, or any other, from this software. // // </copyright> //——————————————————––––––––––––——————————————— #if !LIB namespace System.Configuration { using System.IO; using System.Xml; public class NameValueFileSectionHandler : IConfigurationSectionHandler { public object Create(object parent, object configContext, XmlNode section) { object result = parent; // parse XML XmlNode fileAttribute = section.Attributes.RemoveNamedItem("file"); result = NameValueSectionHandler.CreateStatic(result, section); if (fileAttribute != null && fileAttribute.Value.Length != 0) { /* Удалено для краткости. Этот раздел будет срабатывать, если имеется свойство file="", расположенное в разделе appSettings */ } return result; } } } #endif
Данный обработчик проверяет, имеется ли свойство file=", а затем, если это свойство пустое, возвращает значение, основанное на вызове метода NameValueSectionHandler.CreateStatic(). Это метод, создающий объект конфигурации. Ниже приведен код NameValueSectionHandler.
//———————————————————————————––––––––––––—————— // <copyright file="NameValueSectionHandler.cs" company="Microsoft"> // // Copyright (c) 2002 Microsoft Corporation All rights reserved. // The use and distribution terms for this software are contained in the // file named license.txt, which can be found in the root of this // distribution. By using this software in any fashion, you are agreeing // to be bound by the terms of this license // You must not remove this notice, or any other, from this software. // // </copyright> //——————————––––––––––––——————————————————————— #if !LIB namespace System.Configuration { using System.Collections; using System.Collections.Specialized; using System.Xml; using System.Globalization; public class NameValueSectionHandler : IConfigurationSectionHandler { const string defaultKeyAttribute = "key"; const string defaultValueAttribute = "value"; public object Create(object parent, object context, XmlNode section) { return CreateStatic(parent, section, KeyAttributeName, ValueAttributeName); } internal static object CreateStatic(object parent, XmlNode section) { return CreateStatic(parent, section, defaultKeyAttribute, defaultValueAttribute); } internal static object CreateStatic(object parent, XmlNode section, string keyAttriuteName, string valueAttributeName) { ReadOnlyNameValueCollection result; // start result off as a shallow clone of the parent if (parent == null) result = new ReadOnlyNameValueCollection(new CaseInsensitiveHashCodeProvider( CultureInfo.InvariantCulture), new CaseInsensitiveComparer( CultureInfo.InvariantCulture)); else { ReadOnlyNameValueCollection parentCollection = (ReadOnlyNameValueCollection)parent; result = new ReadOnlyNameValueCollection(parentCollection); } // process XML HandlerBase.CheckForUnrecognizedAttributes(section); foreach (XmlNode child in section.ChildNodes) { // skip whitespace and comments if (HandlerBase.IsIgnorableAlsoCheckForNonElement( child)) continue; // handle <set>, <remove>, <clear> tags if (child.Name == "add") { String key = HandlerBase.RemoveRequiredAttribute( child, keyAttriuteName); String value = HandlerBase.RemoveRequiredAttribute( child, valueAttributeName, true /*allowEmptyString*/); HandlerBase.CheckForUnrecognizedAttributes(child); result[key] = value; } else if (child.Name == "remove") { String key = HandlerBase.RemoveRequiredAttribute( child, keyAttriuteName); HandlerBase.CheckForUnrecognizedAttributes(child); result.Remove(key); } else if (child.Name.Equals("clear")) { HandlerBase.CheckForUnrecognizedAttributes(child); result.Clear(); } else { HandlerBase.ThrowUnrecognizedElement(child); } } result.SetReadOnly(); return result; } protected virtual string KeyAttributeName { get { return defaultKeyAttribute;} } protected virtual string ValueAttributeName { get { return defaultValueAttribute;} } } } #endif
Данный код создает объект коллекции настроек, содержащий пары различных ключей и значений из раздела настроек <appSettings>. Я не буду тратить много времени на объяснение кода обработчика, но давайте рассмотрим несколько наиболее важных пар. Метод CreateStatic() вызывается из первого обработчика раздела и создает объект конфигурации ReadOnlyNameValueCollection, который будет хранить всю информацию о парах различных ключей и значений. Давайте посмотрим на код, который используется для разбора XML.
if (child.Name == "add") { String key = HandlerBase.RemoveRequiredAttribute(child, keyAttriuteName); String value = HandlerBase.RemoveRequiredAttribute(child, valueAttributeName, true/*allowEmptyString*/); HandlerBase.CheckForUnrecognizedAttributes(child); result[key] = value; }
Если имя дочернего элемента XML равно "add", то этот код добавляет в объект типа ReadOnlyNameValueCollection с именем result пару ключ/значение. Когда вы в своем коде ссылаетесь на коллекцию <appSettings>, то осуществляете доступ к этой коллекции и обращаетесь к значениям, сохраненным в этом разделе.
Обработчики разделов настроек интерпретируют все параметры из конкретных разделов и делают их доступными для приложений. В лекции 9 описывется, как создавать собственные обработчики разделов настроек для интерпретации параметров из собственных разделов.