免责声明
根据我所看到的,我所追求的并不是CsvHelper的本机内置-我正在寻找是否有人有创造性的方法来实现这一目标。
问题
我正在使用 CsvHelper (对Josh Close表示敬意)将来自客户的csv文件动态映射到我的域对象中。
给出这样的域对象
public class Episode {
public int Id {get; set;}
public DateTime EpisdoeDate {get; set;}
...
public List<Drug> Drugs {get; private set;}
}
public class Drug
{
public int Id {get; set;}
public int EpisodeId {get; set;} //EF Navigation property
public string Name {get; set;}
public DateTime? LastAdministered {get; set;}
public string AdministrationMethod {get; set;}
}
还有这样的csv文件:
EPISODE_ID,EPISODE_DATE,DRUG 1,DRUG 2,DRUG 3,LAST_USE 1,LAST_USE 2,LAST_USE 3, ...
1,1/1/2017,Benzodiaz,Cigarette,Alcohol,12/20/2016,1/1/2017,12/30/2017,...
有什么方法可以将药物列映射到药物列表中?
非选项
为避免任何人浪费时间,我确实知道有两个“可行”的选择,但在我的情况下都没有真正的选择。
.ConvertUsing()
手动进行映射。List<Drug>
替换为Drug1,Drug2,Drug3等的单独属性,然后使用ReferenceMap
。问题是我处于多个客户使用不同csv格式的情况。因此,我允许用户定义从其csv到域对象的映射。在幕后,我使用它们定义的映射来生成完成用户定义的内容所必需的适当的CsvHelper ClassMap
和ReferenceMap
。
我的想法
我想看的是下面的地图。 (以下内容实际上适用于第一组项目,但是我在这里缺少有关获得下一组项目的信息-只是不知道如何完全到达那里):
//In parsing code
...
reader.Configuration.TypeConverterCache.AddConverter(typeof(List<Drug>), new MyTestConverter<Drug>(reader));
reader.Configuration.RegisterClassMap<EpisodeMap>();
reader.Configuration.RegisterClassMap<DrugMap>();
...
public EpisodeMap : ClientMap<Episode>
{
public EpisodeMap()
{
Map(e => e.EpisodeDate).Name("EPISODE_DATE");
Map(e => e.Drugs).Name("DRUG 1", "LAST_USE 1", "HOW_TAKEN 1");
}
}
public DrugMap : ClientMap<Drug>
{
public DrugMap()
{
Map(e => e.Name).Name("DRUG 1");
Map(e => e.LastAdministered).Name("LAST_USE 1");
Map(e => e.AdministrationMethod).Name("HOW_TAKEN 1");
}
}
public class MyTestConverter<T> : ITypeConverter where T:new()
{
private _reader;
public MyTestConverter(CsvReader reader)
{
_reader = reader;
}
public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
{
var list = new List<T>();
var index = 1;
var creator = new ObjectRecordCreator(_reader);
while(true){
try{
//Somehow use index here to change mapping so look for
//DRUG {index}, LAST_USE {index}
var item = creator.Create<T>();
list.Add(item);
}
catch
{
break;
}
index ++;
}
}
...
}