Если вы ищете пользовательский раздел конфигурации, как показано ниже
<CustomApplicationConfig>
<Credentials Username="itsme" Password="mypassword"/>
<PrimaryAgent Address="10.5.64.26" Port="3560"/>
<SecondaryAgent Address="10.5.64.7" Port="3570"/>
<Site Id="123" />
<Lanes>
<Lane Id="1" PointId="north" Direction="Entry"/>
<Lane Id="2" PointId="south" Direction="Exit"/>
</Lanes>
</CustomApplicationConfig>
тогда вы можете использовать мою реализацию раздела конфигурации, чтобы начать добавлять System.Configuration
ссылку на сборку в ваш проект
Посмотрите на каждый вложенный элемент, который я использовал. Первый - это Credentials с двумя атрибутами, поэтому давайте сначала добавим его.
Элемент учетных данных
public class CredentialsConfigElement : System.Configuration.ConfigurationElement
{
[ConfigurationProperty("Username")]
public string Username
{
get
{
return base["Username"] as string;
}
}
[ConfigurationProperty("Password")]
public string Password
{
get
{
return base["Password"] as string;
}
}
}
PrimaryAgent и SecondaryAgent
Оба имеют одинаковые атрибуты и выглядят как адреса для набора серверов для первичного и аварийного переключения, поэтому вам просто нужно создать один класс элементов для обоих из них, таких как следующие
public class ServerInfoConfigElement : ConfigurationElement
{
[ConfigurationProperty("Address")]
public string Address
{
get
{
return base["Address"] as string;
}
}
[ConfigurationProperty("Port")]
public int? Port
{
get
{
return base["Port"] as int?;
}
}
}
Позже в этом посте я объясню, как использовать два разных элемента с одним классом, давайте пропустим SiteId, поскольку в нем нет различий. Вам просто нужно создать один класс, как указано выше, только с одним свойством. давайте посмотрим, как реализовать коллекцию Lanes
он разделен на две части: сначала нужно создать класс реализации элемента, а затем создать класс элемента коллекции.
LaneConfigElement
public class LaneConfigElement : ConfigurationElement
{
[ConfigurationProperty("Id")]
public string Id
{
get
{
return base["Id"] as string;
}
}
[ConfigurationProperty("PointId")]
public string PointId
{
get
{
return base["PointId"] as string;
}
}
[ConfigurationProperty("Direction")]
public Direction? Direction
{
get
{
return base["Direction"] as Direction?;
}
}
}
public enum Direction
{
Entry,
Exit
}
вы можете заметить, что одним из атрибутов LanElement
является Enumeration, и если вы попытаетесь использовать любое другое значение в конфигурации, которое не определено в приложении Enumeration, System.Configuration.ConfigurationErrorsException
при запуске будет выброшено. Хорошо, давайте перейдем к определению коллекции
[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class LaneConfigCollection : ConfigurationElementCollection
{
public LaneConfigElement this[int index]
{
get { return (LaneConfigElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(LaneConfigElement serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new LaneConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((LaneConfigElement)element).Id;
}
public void Remove(LaneConfigElement serviceConfig)
{
BaseRemove(serviceConfig.Id);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(String name)
{
BaseRemove(name);
}
}
вы можете заметить, что я установил, что AddItemName = "Lane"
вы можете выбрать все, что вам нравится для элемента коллекции, я предпочитаю использовать «добавить» по умолчанию, но я изменил его только ради этого поста.
Теперь все наши вложенные элементы были реализованы, теперь мы должны объединить все те в классе, который должен реализовать System.Configuration.ConfigurationSection
CustomApplicationConfigSection
public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
{
private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
public const string SECTION_NAME = "CustomApplicationConfig";
[ConfigurationProperty("Credentials")]
public CredentialsConfigElement Credentials
{
get
{
return base["Credentials"] as CredentialsConfigElement;
}
}
[ConfigurationProperty("PrimaryAgent")]
public ServerInfoConfigElement PrimaryAgent
{
get
{
return base["PrimaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("SecondaryAgent")]
public ServerInfoConfigElement SecondaryAgent
{
get
{
return base["SecondaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("Site")]
public SiteConfigElement Site
{
get
{
return base["Site"] as SiteConfigElement;
}
}
[ConfigurationProperty("Lanes")]
public LaneConfigCollection Lanes
{
get { return base["Lanes"] as LaneConfigCollection; }
}
}
Теперь вы можете видеть, что у нас есть два свойства с именем PrimaryAgent
и SecondaryAgent
оба имеют одинаковый тип, теперь вы можете легко понять, почему у нас был только один класс реализации для этих двух элементов.
Прежде чем вы сможете использовать этот недавно изобретенный раздел конфигурации в вашем app.config (или web.config), вам просто нужно сообщить приложению, что вы изобрели свой собственный раздел конфигурации и дать ему некоторое уважение, для этого вам нужно добавить следующие строки в app.config (может быть сразу после запуска корневого тега).
<configSections>
<section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
</configSections>
ПРИМЕЧАНИЕ. Имя MyAssemblyName должно быть без .dll, например, если имя файла сборки - myDll.dll, используйте myDll вместо myDll.dll.
чтобы получить эту конфигурацию, используйте следующую строку кода в любом месте вашего приложения
CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;
Надеюсь, что вышеприведенный пост поможет вам начать с немного сложного вида пользовательских разделов конфигурации.
Удачного кодирования :)
**** Редактировать **** Чтобы включить LINQ на LaneConfigCollection
вас необходимо реализоватьIEnumerable<LaneConfigElement>
И добавить следующую реализацию GetEnumerator
public new IEnumerator<LaneConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as LaneConfigElement;
}
}
для людей, которые все еще не понимают, как действительно работает yield, прочитайте эту хорошую статью
Два ключевых пункта, взятых из вышеприведенной статьи:
это действительно не заканчивает выполнение метода. yield return приостанавливает выполнение метода, и при следующем вызове его (для следующего значения перечисления) метод продолжит выполнение с последнего вызова yield return. Я думаю, это звучит немного странно ... (Шей Фридман)
Выход не является особенностью среды выполнения .Net. Это просто особенность языка C #, которая компилируется в простой код IL компилятором C #. (Ларс Корнелиусен)