C# 卡住创建自定义配置部分

C# Stuck Creating Custom Configuration Section

我第一次尝试实现自定义配置部分的创建,我感到非常沮丧。

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

然后,每个 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 的示例/解决方案创建自定义 类,但遇到了严重的困难。我目前的代码大致如下:

Csv列:

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 以防那是我的问题所在)

Csv文件:

[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);
    }
}

Csv文件集合:

[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. 是否有更简单的(通用)方法来实现此目的,使这个过程更容易?

非常感谢!!!

我不确定为什么会发生这种情况,大概是框架中的错误,但是当你有这些嵌套的 ConfigurationElementCollection 实例时,它似乎忽略了 AddItemName 位于内部集合的 ConfigurationCollection 属性上。您可以通过将 CsvColumn 元素更改为 add 元素来自己确认这一点,它会正确反序列化。

将以下构造函数添加到您的 CsvFile class 应该可以解决您的问题:

  public CsvFile()
  {
        AddElementName = "CsvColumn";
  }

关于你的第二个问题,你试过图书馆吗CsvHelper