我正在尝试第一次实现创建自定义配置部分,并且很快就会被打败。
例如,假设我想创建一个自定义部分,用于存储要由我的程序读取的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'
。
我无法弄清楚原因。
我的主要问题是:
非常感谢!!!
答案 0 :(得分:2)
我不确定为什么会发生这种情况,可能是框架中的错误,但是当您拥有这些嵌套的 ConfigurationElementCollection
实例时,似乎忽略了 {{1}内部集合的 AddItemName
属性。。您可以通过将 ConfigurationCollection
元素更改为 CsvColumn
元素来自行确认,并且它会正确反序列化。
将以下构造函数添加到 add
类可以解决您的问题:
CsvFile
对于您的第二个问题,您是否尝试过图书馆CsvHelper