用CsvHelper将列集映射到List <T>的任何方法吗?

时间:2019-08-08 18:38:13

标签: csvhelper

免责声明

根据我所看到的,我所追求的并不是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,...

有什么方法可以将药物列映射到药物列表中?

非选项

为避免任何人浪费时间,我确实知道有两个“可行”的选择,但在我的情况下都没有真正的选择。

  1. 使用.ConvertUsing()手动进行映射。
  2. List<Drug>替换为Drug1,Drug2,Drug3等的单独属性,然后使用ReferenceMap

问题是我处于多个客户使用不同csv格式的情况。因此,我允许用户定义从其csv到域对象的映射。在幕后,我使用它们定义的映射来生成完成用户定义的内容所必需的适当的CsvHelper ClassMapReferenceMap

我的想法

我想看的是下面的地图。 (以下内容实际上适用于第一组项目,但是我在这里缺少有关获得下一组项目的信息-只是不知道如何完全到达那里):

//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 ++;
       }

   }
   ...
}

0 个答案:

没有答案