我为我的 app.config 创建了自定义ConfigurationSection
,ConfigurationElement(s)
和ConfigurationElementCollection(s)
,它基于this documentation。
现在,我希望能够访问任何配置元素中的父元素。
例如以下行中的内容:
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
getter中分配该属性值。
答案 0 :(得分:3)
您在ConfigurationElement
中没有错过任何内容,它无法为您提供任何层次结构或订单信息。您必须自己保留此信息,例如,参见this answer。
对于通用解决方案,您可能需要检出my POC以便在app.config中定义父占位符。
附带说明一下,在以前的版本中,我使用界面(您可以检查以前的提交)完成此操作,而在当前版本中,我具有扩展程序属性。
此外,以下是仅满足您要求的精简版本:
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 ...
}