c# - 是否可以从 xml 文本创建 ConfigurationElement?

标签 c# xml configuration configurationsection configurationelement

我们有一个继承自 ConfigurationElement 的自定义类叫SignalConfigurationElement并使用 ConfigurationProperty 定义了一堆属性属性。

SignalConfigurationElement类是更大的配置元素层次结构的一部分,并且没有构造函数。我可以通过 ConfigurationManager.GetSection() 检索整个配置调用,提供根元素的名称 SystemConfiguration ,它在 <configSections> 中定义。 app.config 文件的内容。

我无法控制自定义配置元素,因此无法更改它们以提供构造函数。我也无法修改 app.config,因为它被更大的应用程序使用。

是否可以创建 SignalConfigurationElement 的实例或集合给定一个 XML 字符串 <signals>条目?该类没有构造函数,因此我假设 ConfigurationManager.GetSection我们的其他应用程序用于检索整个配置(不是我想要的)的调用使用反射来创建其实例。

代码(根本无法更改任何内容。):

应用程序配置

<configSections>
    <section name="SystemConfiguration" type="Fully.Qualified.Namespace.SystemConfiguration, SystemConfiguration"/>
</configSections>

<SystemConfiguration id="System1" name="System 1">
    <equipments>
      <clear />
      <add id="Equipment11" equipmentType="EQ">
        <signals>
          <clear />
          <add id="EQ11Signal1" signalId="EQ11Signal1" type="Version" />
          <add id="EQ11Signal2" signalId="EQ11Signal2" type="Status" />
          <add id="EQ11Signal3" signalId="EQ11Signal3" type="Status" />
        </signals>
      </add>
      <add id="Equipment21" equipmentType="EQ">
        <signals>
          <clear />
          <add id="EQ21Signal1" signalId="EQ21Signal1" type="Version" />
          <add id="EQ21Signal2" signalId="EQ21Signal2" type="Status" />
          <add id="EQ21Signal3" signalId="EQ21Signal3" type="Status" />
        </signals>
      </add>
     </equipments>
<!-- And a whole lot more. Somewhere in the avenue of 30,000 <signals> entries.-->
</SystemConfiguration>

类(class):

public class SystemConfigurationSection : ConfigurationSection
{
/// <summary>
/// Determines the XML tag that will contain this Configuration Section in an .config file.
/// </summary>
public const string SystemConfigurationSectionName = "SystemConfiguration";

/// <summary>
/// Instance factory method for an instance of the Configuration Section creation.
/// </summary>
/// <returns>
/// Instance of the System Configuration section created based on the .config file of the application.
/// </returns>
public static SystemConfigurationSection GetSystemConfigurationSection()
{
    SystemConfigurationSection result =
        (SystemConfigurationSection) ConfigurationManager.GetSection(SystemConfigurationSectionName);
    return result;
}

/// <summary>
/// Represents the XML attribute used to store ID of the System.
/// </summary>
[ConfigurationProperty(IdConfigurationElementName, IsRequired = true)]
public string Id
{
    get { return (string) this[IdConfigurationElementName]; }
    set { this[IdConfigurationElementName] = value; }
}

/// <summary>
/// Determines name of the XML attribute that will contain ID of the System.
/// </summary>
public const string IdConfigurationElementName = "id";

/// <summary>
/// Represents the XML attribute used to store Name of the System.
/// </summary>
[ConfigurationProperty(NameConfigurationElementName, IsRequired = true)]
public string Name
{
    get { return (string) this[NameConfigurationElementName]; }
    set { this[NameConfigurationElementName] = value; }
}

/// <summary>
/// Determines name of the XML attribute that will contain Name of the System.
/// </summary>
public const string NameConfigurationElementName = "name";

/// <summary>
/// Represents the XML attribute used to store Description of the System
/// </summary>
[ConfigurationProperty(DescriptionConfigurationElementName, IsRequired = false, DefaultValue = "")]
public string Description
{
    get { return (string) this[DescriptionConfigurationElementName]; }
    set { this[DescriptionConfigurationElementName] = value; }
}

/// <summary>
/// Determines name of the XML attribute that will contain Name of the System.
/// </summary>
public const string DescriptionConfigurationElementName = "description";

/// <summary>
/// Represents the collection of the System's Equipments as they are described in the .config file.
/// </summary>
[ConfigurationProperty(EquipmentsConfigurationElementCollectionName, IsDefaultCollection = false)]
[ConfigurationCollection(typeof (EquipmentConfigurationElementCollection), AddItemName = "add",
    ClearItemsName = "clear", RemoveItemName = "remove")]
public EquipmentConfigurationElementCollection Equipments
{
    get { return (EquipmentConfigurationElementCollection) base[EquipmentsConfigurationElementCollectionName]; }
}

/// <summary>
/// Determines name of the XML tag that will contain collection of the System's Equipments.
/// </summary>
public const string EquipmentsConfigurationElementCollectionName = "equipments";

}

 

/// <summary>
/// Extends the standard .Net ConfigurationElementCollection re-definind commectio manipulation members and making them strongly-typed.
/// </summary>
/// <typeparam name="TElementType">Type of the Configuration Elements that can be included into the collection.</typeparam>
public class ConfigurationElementCollectionBase<TElementType> : ConfigurationElementCollection, IEnumerable<TElementType>
where TElementType : ConfigurationElement, new()
{
/// <summary>
/// Makes the addition operation public.
/// </summary>
/// <param name="customElement">Configuration element to add to the collection.</param>
public virtual void Add(TElementType customElement)
{
    BaseAdd(customElement);
}

/// <summary>
/// Overrides the base implementation of the overloaded method masking an exception throwing.
/// </summary>
/// <param name="element">Configuration element to add.</param>
protected override void BaseAdd(ConfigurationElement element)
{
    BaseAdd(element, false);
}

/// <summary>
/// Overrides the base property hardcoding the returned value.
/// </summary>
public override ConfigurationElementCollectionType CollectionType
{
    get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
}

/// <summary>
/// Overrides the base implementation of the instance factory method.
/// </summary>
/// <returns>A new instance of the Configuration Element type determined by the type parameter.</returns>
protected override ConfigurationElement CreateNewElement()
{
    return new TElementType();
}

/// <summary>
/// Overrides the base implementation of the method determining the indexing algorithm used in the collection.
/// </summary>
/// <param name="element">The configuration element to get index of.</param>
/// <returns></returns>
protected override object GetElementKey(ConfigurationElement element)
{
    return ((TElementType)element);
}

/// <summary>
/// Collection's element accessor by index property.
/// </summary>
/// <param name="index">Index of the desired element in the collection.</param>
/// <returns>The requested collection element if exists.</returns>
public TElementType this[int index]
{
    get { return (TElementType)BaseGet(index); }
    set
    {
        if (BaseGet(index) != null)
        {
            BaseRemoveAt(index);
        }
        BaseAdd(index, value);
    }
}

/// <summary>
/// Overrides the collection's element accessor by key property.
/// </summary>
/// <param name="id">Key of the desired collection element.</param>
/// <returns>The requested collection element if exists</returns>
public new TElementType this[string id]
{
    get { return (TElementType)BaseGet(id); }
}

/// <summary>
/// Implements a standard collection method looking for an element in the collection and returning the element's index if found.
/// </summary>
/// <param name="element">The element to look for.</param>
/// <returns>Index of the element in the collection if exists.</returns>
public int GetIndexOf(TElementType element)
{
    return BaseIndexOf(element);
}

/// <summary>
/// Implements a standard collection method removing an element from the collection.
/// </summary>
/// <param name="url">The element to be removed from the collection.</param>
public void Remove(TElementType url)
{
    if (BaseIndexOf(url) >= 0)
        BaseRemove(url);
}

/// <summary>
/// Implements the standard collection member removing an element from the collection by the element's index.
/// </summary>
/// <param name="index">Index of the element to be removed from the collection.</param>
public void RemoveAt(int index)
{
    BaseRemoveAt(index);
}

/// <summary>
/// Implements a standard collection method removing an element by the element's key.
/// </summary>
/// <param name="id">Key of the element to be removed from the collection.</param>
public void Remove(string id)
{
    BaseRemove(id);
}

/// <summary>
/// Implements the standard collection method that clears the collection.
/// </summary>
public void Clear()
{
    BaseClear();
}


public new IEnumerator<TElementType> GetEnumerator()
{
    for (int i = 0; i < Count; i++)
    {
        yield return this[i];
    }
}

 

public class EquipmentConfigurationElement : ConfigurationElement
{
    /// <summary>
    /// Represents the collection of the Equipment Unit's Signals as they are described in the .config file.
    /// </summary>
    [ConfigurationProperty(signalsConfigurationElementCollectionName, IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(SignalConfigurationElementCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
    public SignalConfigurationElementCollection Signals
    {
        get
        {
            return (SignalConfigurationElementCollection)base[signalsConfigurationElementCollectionName];
        }
    }
    /// <summary>
    /// Determines name of the XML tag that will contain collection of the Equipment Unit's Signals.
    /// </summary>
    private const string signalsConfigurationElementCollectionName = "signals";

}

 

/// <summary>
/// Represents a type-safe collection of Equipment Unit Configuration Elements.
/// </summary>
public class EquipmentConfigurationElementCollection : ConfigurationElementCollectionBase<EquipmentConfigurationElement>
{
}

 

/// <summary>
/// Represensts a Signal's configuration element
/// </summary>
/// <remarks>
/// As the class is derived from ConfigurationElementBase, a Signal's configuration element will expect "is", "name", and "description" XML attributes defined in the configuration file.
/// </remarks>
public sealed class SignalConfigurationElement : ConfigurationElement
{

    /// <summary>
    /// Represents an XML attribute used to determine type of the Signal.
    /// </summary>
    /// <remarks>
    /// The attribute is expected to have a string value which is equal to one of SignalType enumeration member names: "Status" or "Command".
    /// </remarks>
    [ConfigurationProperty(typeConfigurationElementName, IsRequired = false, DefaultValue = "status")]
    public string Type
    {
        get { return (string) this[typeConfigurationElementName]; }
        set { this[typeConfigurationElementName] = value; }
    }

    /// <summary>
    /// Determines name of the XML attribute that will contain type of the Signal.
    /// </summary>
    private const string typeConfigurationElementName = "type";
}

 

/// <summary>
/// Represents a type-safe collection of Signal Configuration Elements.
/// </summary>
public class SignalConfigurationElementCollection : ConfigurationElementCollectionBase<SignalConfigurationElement>
{
}

最佳答案

这可以通过黑暗的反射(reflection)艺术来实现。鉴于问题中显示的 XML,您可以执行以下操作:

    var configXml = GetAppConfigXml(); // Returns the XML shown in your question.

    var config = (SystemConfigurationSection)Activator.CreateInstance(typeof(SystemConfigurationSection), true);

    using (var sr = new StringReader(configXml))
    using (var xmlReader = XmlReader.Create(sr))
    {
        if (xmlReader.ReadToDescendant("SystemConfiguration"))
            using (var subReader = xmlReader.ReadSubtree())
            {
                var dynMethod = config.GetType().GetMethod("DeserializeSection", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(XmlReader) }, null);
                dynMethod.Invoke(config, new object[] { subReader });
            }
    }
    Debug.Assert(config.Equipments.Count == 2); // No assert

引用:source for ConfigurationSection.DeserializeSection .

顺便说一句,附加到您的问题的配置类与 XML 不匹配。缺少一些属性,与 XML 中的属性对应的属性必须有 IsKey = true 。如果 XML 与配置类不匹配,DeserializeSection 将引发异常。

关于c# - 是否可以从 xml 文本创建 ConfigurationElement?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32896165/

相关文章:

c# - ASP.NET core 2.2 web api 记录与数据保护 key 相关的警告 : how should we handle this issue?

c# - 使用 for 循环将自定义对象分配给数组?

java - checkstyle-maven-plugin 3.0.0 已弃用参数 sourceDirectory

symfony - 如何从 Symfony2 config.yml 读取配置设置?

java - 从 log4j 2 库禁用日志记录,如何?

.net - WebReference 即使在库程序集项目中也会创建 App.config

c# - 如何在做某事时检查 C# 中的标准输入

c# - 创建一个返回实现通用接口(interface)的对象的方法

java - 在 Java 中将 RSA key 对象导出到 XML

xml - 将新的子项追加到特定节点