C#Stuck创建自定义配置部分

时间:2016-03-31 13:37:13

标签: c# .net configuration app-config configuration-files

我正在尝试第一次实现创建自定义配置部分,并且很快就会被打败。

例如,假设我想创建一个自定义部分,用于存储要由我的程序读取的CSV文件列表 - 每个文件,因此具有:

  • 文件路径
  • 分隔符
  • CsvColumn(另一种类型)
  • 的列表

然后,每个CsvColumn都可以具有以下属性:

  • 文件中的名称
  • 类型

(请忽略这是否可以通过配置完成,这只是一个给出层次结构的例子,所以我可以学习如何做到这一点。)

所以,我创建了以下配置文件:

<configSections>
    <section name="CsvData" type="CSV_Loader.CsvData, CSV_Loader" />
</configSections>

<CsvData>
    <CsvFiles>
        <CsvFile Path="MyPath1" Delimiter=",">
            <CsvColumn NameInFile="Col1" Type="System.String"/>
            <CsvColumn NameInFile="Col2" Type="System.String"/>
            <CsvColumn NameInFile="Col3" Type="System.Double"/>
        </CsvFile>
        <CsvFile Path="MyPath2" Delimiter=",">
            <CsvColumn NameInFile="Col1" Type="System.String"/>
        </CsvFile>
    </CsvFiles>
</CsvData>

而且,现在我正在寻找基于给定here的示例/解决方案来创建自定义类,并且我非常困难。我目前的代码大致如下:

CsvColumn:

public class CsvColumn : ConfigurationElement
{
    [ConfigurationProperty("NameInFile", IsRequired = true, IsKey = true)]
    public string NameInFile
    {
        get { return (string)this["NameInFile"]; }
    }

    [ConfigurationProperty("Type", IsRequired = true, DefaultValue = "")]
    public string Type
    {
        get { return (string)this["Type"]; }
    }
}

(仅供参考 - 我想将Type存储为实际的Type变量,但我将其设置为String,以防我的问题出现在哪里)

CsvFile:

[ConfigurationCollection(typeof(CsvColumn), AddItemName = "CsvColumn", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class CsvFile : ConfigurationElementCollection
{
    [ConfigurationProperty("Path", DefaultValue = "", IsKey = true, IsRequired = true)]
    public string Path
    {
        get { return (string)(base["Path"]); }
    }

    [ConfigurationProperty("Delimiter", DefaultValue = ",", IsRequired = true)]
    public string Delimiter
    {
        get { return (string)(base["Delimiter"]); }
    }

    public CsvColumn this[int index]
    {
        get { return (CsvColumn)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }

    public void Add(CsvColumn column)
    {
        BaseAdd(column);
    }

    public void Clear()
    {
        BaseClear();
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((CsvColumn)element).NameInFile;
    }

    public void Remove(CsvColumn column)
    {
        BaseRemove(column.NameInFile);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }

    public void Remove(String name)
    {
        BaseRemove(name);
    }
}

CsvFile Collection:

[ConfigurationCollection(typeof(CsvFile), AddItemName = "CsvFile", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class CsvFiles : ConfigurationElementCollection
{
    public CsvFile this[int index]
    {
        get { return (CsvFile)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }

    public void Add(CsvFile file)
    {
        BaseAdd(file);
    }

    public void Clear()
    {
        BaseClear();
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((CsvFile)element).Path;
    }

    public void Remove(CsvFile file)
    {
        BaseRemove(file.Path);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }

    public void Remove(String name)
    {
        BaseRemove(name);
    }   
}

CsvData:

public class CsvData : ConfigurationSection
{
    [ConfigurationProperty("CsvFiles")]
    public CsvFiles CsvFiles
    {
        get { return base["CsvFiles"] as CsvFiles; }
    }
}

我试图在我的代码中调用它,如下所示:

var csvData = (ConfigurationManager.GetSection("CsvData") as CsvData);

但我得到ConfigurationException Unrecognized element 'CsvColumn'。 我无法弄清楚原因。

我的主要问题是:

  1. 我做错了什么?
  2. 是否有更简单的方式(通用)实现此方法,这会使此过程更容易?
  3. 非常感谢!!!

1 个答案:

答案 0 :(得分:2)

我不确定为什么会发生这种情况,可能是框架中的错误,但是当您拥有这些嵌套的 ConfigurationElementCollection 实例时,似乎忽略了 {{1}内部集合的 AddItemName 属性。。您可以通过将 ConfigurationCollection 元素更改为 CsvColumn 元素来自行确认,并且它会正确反序列化。

将以下构造函数添加到 add 类可以解决您的问题:

CsvFile

对于您的第二个问题,您是否尝试过图书馆CsvHelper