Получить родительский элемент ConfigurationElement в app.config
Я создал кастом ConfigurationSection
, ConfigurationElement(s)
а также ConfigurationElementCollection(s)
для моего app.config он основан на этой документации.
Теперь я хотел бы иметь доступ к родительскому элементу в любом элементе конфигурации.
Например, что-то в строках следующего:
public class CustomSection : ConfigurationSection
{
[ConfigurationProperty("child")]
public ChildElement Child
{
get { return (ChildElement)this["child"]; }
set { this["child"] = value; }
}
}
public class ChildElement : ConfigurationElement
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("nestedchild")]
public NestedChildElement NestedChild
{
get { return (NestedChildElement)this["nestedchild"]; }
set { this["nestedchild"] = value; }
}
}
public class NestedChildElement : ConfigurationElement
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
public void Sample()
{
// How can I access parent ChildElement object
// and also its parent CustomSection object from here?
}
}
Есть ли что-то в базе ConfigurationElement
класс, который я пропускаю и который позволил бы мне сделать это?
Я надеюсь, возможно ли достичь этого с помощью какого-то общего решения;
Тот, который не потребует ввести что-то вроде Parent
свойство каждого элемента, а затем необходимо назначить это значение свойства в каждом ConfigurationProperty
добытчик.
1 ответ
Вы ничего не пропустили в ConfigurationElement
, он не может дать вам никакой иерархии или информации о заказе. Вы должны будете сохранить эту информацию самостоятельно, например, посмотрите этот ответ.
Для общего решения вы можете проверить мой POC для определения родительских заполнителей в app.config.
Как примечание, в предыдущей версии я сделал это с интерфейсом (вы могли проверить предыдущие коммиты) и в текущей версии со свойством extension.
Кроме того, ниже приведена урезанная версия, которая удовлетворяет только вашим требованиям:
public abstract class ConfigurationElementBase : ConfigurationElement
{
protected T GetElement<T>(string name) where T : ConfigurationElement
=> this.GetChild<T>(name);
}
public abstract class ConfigurationSectionBase : ConfigurationSection
{
protected T GetElement<T>(string name) where T : ConfigurationElement
=> this.GetChild<T>(name);
}
public static class ConfigurationExtensions
{
private static readonly Dictionary<ConfigurationElement, ConfigurationElement> Parents =
new Dictionary<ConfigurationElement, ConfigurationElement>();
public static T GetParent<T>(this ConfigurationElement element) where T : ConfigurationElement
=> (T)Parents[element];
private static void SetParent(this ConfigurationElement element, ConfigurationElement parent)
=> Parents.Add(element, parent);
private static object GetValue(this ConfigurationElement element, string name)
=> element.ElementInformation.Properties.Cast<PropertyInformation>().First(p => p.Name == name).Value;
internal static T GetChild<T>(this ConfigurationElement element, string name) where T : ConfigurationElement
{
T childElement = (T)element.GetValue(name);
if (!Parents.ContainsKey(childElement))
childElement.SetParent(element);
return childElement;
}
}
Теперь вы можете использовать эти базовые классы конфигурации в своем пользовательском разделе следующим образом:
public class CustomSection : ConfigurationSectionBase
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("child")]
public ChildElement Child => base.GetElement<ChildElement>("child");
}
public class ChildElement : ConfigurationElementBase
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("nestedchild")]
public NestedChildElement NestedChild => base.GetElement<NestedChildElement>("nestedchild");
}
public class NestedChildElement : ConfigurationElement
{
[ConfigurationProperty("name")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
public void Sample()
{
ChildElement parentChildElement = this.GetParent<ChildElement>();
CustomSection parentCustomSection = parentChildElement.GetParent<CustomSection>();
// TODO Use the parents ...
}