我正在使用CSVHelper(感谢Josh Close)来读取效果很好的CSV文件。我现在正在尝试使用它来将该文件映射到一些内部类。但是,我要映射的CSV随客户而异,但都需要映射到我的内部类。我需要允许客户定义CSV如何映射到我的POCO对象。
我将客户定义的映射存储为Dictionary<string,int>
-[“”名字“,20],[”姓氏“,21],[” Address.Line1“,30],[” Address.Line2 “,31]等
我有一个动态地图类,该类用于在运行时基于给定的映射进行动态映射。我的问题在于处理引用类型属性。这是我到目前为止所拥有的。
POCO类
public class Client
{
public int Id {get; set;}
public string Firstname {get; set;}
public string Lastname {get; set;}
public Address Address {get; set;}
...
}
public class Address
{
public string Line1 {get; set;}
public string Line2 {get; set;}
public string City {get; set;}
...
}
基于我在here和here上发表的几篇文章,我提出了以下内容,这些内容使用定义的映射来动态映射CSV。
动态地图
public class BaseCSVMap<T> : ClassMap<T> where T : class
{
public void CreateMap(Dictionary<string,int> mappings)
{
foreach(var mapping in mappings)
{
var propname = mapping.Key;
var csvIndex = mapping.Value;
var member = typeof(T).GetProperty(propname);
Map(typeof(T), member).Index(csvIndex);
}
}
}
使用动态地图
var id = 2; //Customer 2
var mappings = dataContext.Mappings.Where(m => m.id = id); //Get customer 2's map
using(var reader = File.OpenText(@"c:\temp\testfile.csv"))
{
var csv = new CsvReader(reader);
csv.Configuration.HasHeaderRecord = true; //hardcoded for now
var map = new BaseCSVMap<Client>();
map.CreateMap(mappings);
csv.Configuration.RegisterClassMap(map);
var records = csv.GetRecords<Client>();
}
我在BaseCSVMap<T>
类中添加了以下内容,如果我所有的引用属性都是字符串,则该属性很好用,但是当其他属性不起作用时,效果不佳。
var member = typeof(T).GetProperty(propname);
//New code
//Mapping would look like ["Address.Line1",78]
if(member.GetType().IsClass)
{
string exp = $"c.{propname}";
var p = Expression.Parameter(typeof(T), "c");
var e = System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(new [] {p}, null, exp);
Map((Expression<Func<T,string>>)e).Index(csvIndex);
}
我还寻找一种方法来利用CSVHelper提供的Reference映射,但是无法找出如何以动态方式进行操作。
正在寻找有关如何使用CSVHelper为引用类型定义动态地图的指导。