app.config 中的自定义配置部分 - XML 属性与元素

Custom configuration section in app.config - XML attributes Vs elements

我已经有一个自定义配置部分在工作,基于如下配置:

  <DataSourcesConfig>
    <DataSources>
      <DataSource name="test1" connectionType="Ethernet_TCP_Client" protocolType="Serial" ipAddress="127.0.0.1" port="12345"/>
      <DataSource name="test2" connectionType="Ethernet_TCP_Client" protocolType="Serial" ipAddress="127.0.0.1" port="12346"/>
    </DataSources>
  </DataSourcesConfig>

但我想知道支持以下内容 - 或者在理想情况下支持两者:

  <DataSourcesConfig>
    <DataSources>
      <DataSource>
        <name>test1</name>
        <connectionType>Ethernet_TCP_Client</connectionType>
        <protocolType>Serial</protocolType>
        <ipAddress>127.0.0.1</ipAddress>
        <port>12345</port>
      </DataSource>
      <DataSource>
        <name>test2</name>
        <connectionType>Ethernet_TCP_Client</connectionType>
        <protocolType>Serial</protocolType>
        <ipAddress>127.0.0.1</ipAddress>
        <port>12346</port>
      </DataSource>
    </DataSources>
  </DataSourcesConfig>

所以我有如下代码(有效)。在不进行自定义 Xml 解析的情况下支持第二个 Xml 示例是否可行? 我一开始就可以看到 DataSources.GetElementKey 是一个问题,因为它引用了 name 作为属性丢失的内容,但这主要是从示例代码中借用的,所以我不声称理解这些 类很好

public class DataSource : ConfigurationElement
{
    [ConfigurationProperty("name", IsRequired = true)]
    public string Name => this["name"] as string;

    [ConfigurationProperty("connectionType", IsRequired = true)]
    public string ConnectionType => this["connectionType"] as string;

    [ConfigurationProperty("protocolType", IsRequired = true)]
    public string ProtocolType => this["protocolType"] as string;

    [ConfigurationProperty("ipAddress", IsRequired = true)]
    public string IPAddress => this["ipAddress"] as string;

    [ConfigurationProperty("port", IsRequired = true)]
    public string Port => this["port"] as string;
}
public class DataSources
    : ConfigurationElementCollection
{
    public DataSource this[int index]
    {
        get
        {
            return base.BaseGet(index) as DataSource;
        }
        set
        {
            if (base.BaseGet(index) != null)
            {
                base.BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }

    public new DataSource this[string responseString]
    {
        get
        {
            return (DataSource)BaseGet(responseString);
        }
        set
        {
            if (BaseGet(responseString) != null)
            {
                BaseRemoveAt(BaseIndexOf(BaseGet(responseString)));
            }
            BaseAdd(value);
        }
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new DataSource();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((DataSource)element).Name;
    }
}

public class DataSourcesConfig : ConfigurationSection
{
    public static DataSourcesConfig GetConfig()
    {
        var o = ConfigurationManager.GetSection("DataSourcesConfig");
        return o as DataSourcesConfig;
    }

    [System.Configuration.ConfigurationProperty("DataSources")]
    [ConfigurationCollection(typeof(DataSources), AddItemName = "DataSource")]
    public DataSources DataSources
    {
        get
        {
            object o = this["DataSources"];
            return o as DataSources;
        }
    }
}

据我所知,在使用 ConfigurationManager[= 时,您不能在 app.config 文件的 xml 部分中放置 17=]

但是你有一个非常相似的选项来处理这样的配置结构:

<DataSourcesConfig>
    <DataSources>
        <DataSource>
            <name value="test1"/>
            <connectionType value="Ethernet_TCP_Client"/>
            <protocolType value="Serial"/>
            <ipAddress value="127.0.0.1"/>
            <port value="12345"/>
        </DataSource>
        <DataSource>
            <name value="test2"/>
            <connectionType value="Ethernet_TCP_Client"/>
            <protocolType value="Serial"/>
            <ipAddress value="127.0.0.1"/>
            <port value="12346"/>
        </DataSource>
    </DataSources>
</DataSourcesConfig>

首先你需要定义一个ValueElement:

public class ValueElement<T> : ConfigurationElement
{
    [ConfigurationProperty("value", IsRequired = true)]
    public T Value => (T) this["value"];
}

接下来,像这样更改 DataSource 元素:

public class DataSource : ConfigurationSection // It is section now
{
    [ConfigurationProperty("name", IsRequired = true)]
    public ValueElement<string> Name => this["name"] as ValueElement<string>;

    [ConfigurationProperty("connectionType", IsRequired = true)]
    public ValueElement<string> ConnectionType => this["connectionType"] as ValueElement<string>;

    [ConfigurationProperty("protocolType", IsRequired = true)]
    public ValueElement<string> ProtocolType => this["protocolType"] as ValueElement<string>;

    [ConfigurationProperty("ipAddress", IsRequired = true)]
    public ValueElement<string> IPAddress => this["ipAddress"] as ValueElement<string>;

    [ConfigurationProperty("port", IsRequired = true)]
    public ValueElement<int> Port => this["port"] as ValueElement<int>;
}

现在您可以像这样在代码中使用您的配置:

var configuration = DataSourcesConfig.GetConfig();
var test1name = configuration.DataSources[0].Name.Value; // test1 as string
var test2name = configuration.DataSources[1].Name.Value; // test2 as string
var portForTest1 = configuration.DataSources[0].Port.Value // 12345 as int