如何用CsvHelper实现CSV列到自定义代码的映射(处理只读属性)
用CsvHelper处理只读属性并映射到字典字段
问题描述
我有自动生成的实体类(示例为MyClass,实际继承自Microsoft.Xrm.Sdk.Entity),需要读取CSV文件并返回MyClass列表。该类包含只读的CreatedOn属性,无法直接映射赋值,需求是将CSV中CreatedOn列的值存入实体的Attributes字典的"overriddencreatedon"键中。能否通过CsvHelper实现这类自定义映射?
实体类定义如下:
public class MyClass // 实际继承自Microsoft.Xrm.Sdk.Entity { public Guid Id { get; set; } public DateTime CreatedOn { get;} // 生成类自带的只读属性 public Dictionary<string, object> Attributes { get; set; } }
期望实现类似如下逻辑的自定义映射:
private class MyClassMap : ClassMap<MyClass> { public MyClassMap() { Map(f => f.Id).Name("Id"); // 目标:将CSV的CreatedOn值存入Attributes["overriddencreatedon"] // Map().XXX((row, x) => x.Attributes["overriddencreatedon"] = row.Row.GetField<DateTime>("CreatedOn")); } }
解决方案
可以通过CsvHelper提供的AfterMap回调或自定义Convert逻辑实现需求,以下是两种可行方案:
方案1:使用AfterMap(推荐)
利用AfterMap在对象完成基础属性映射后,统一处理字典赋值,逻辑更直观:
private class MyClassMap : ClassMap<MyClass> { public MyClassMap() { // 映射Id属性到CSV的Id列 Map(f => f.Id).Name("Id"); // 对象映射完成后,从CSV行读取值并写入字典 AfterMap((row, entity) => { // 读取CSV中CreatedOn列的DateTime值 var createdOnValue = row.GetField<DateTime>("CreatedOn"); // 确保Attributes字典已初始化(生成类可能未自动初始化) entity.Attributes ??= new Dictionary<string, object>(); // 将值存入指定键 entity.Attributes["overriddencreatedon"] = createdOnValue; }); } }
方案2:使用自定义Convert映射
针对CSV的CreatedOn列单独创建映射规则,在转换逻辑中完成字典赋值:
private class MyClassMap : ClassMap<MyClass> { public MyClassMap() { Map(f => f.Id).Name("Id"); // 映射CSV的CreatedOn列,在转换时写入字典 Map() .Name("CreatedOn") .Convert(context => { var entity = context.Row.GetRecord<MyClass>(); var createdOnValue = context.Row.GetField<DateTime>("CreatedOn"); entity.Attributes ??= new Dictionary<string, object>(); entity.Attributes["overriddencreatedon"] = createdOnValue; // 返回值无实际作用(无需映射到实体属性),仅满足CsvHelper的接口要求 return createdOnValue; }); } }
注意事项
- 如果生成的实体类未自动初始化
Attributes字典,必须先通过entity.Attributes ??= new Dictionary<string, object>()确保字典存在,避免空引用异常。 - 若CSV中
CreatedOn列可能存在空值,需改用GetField<DateTime?>并添加空值判断逻辑。
内容的提问来源于stack exchange,提问作者Sybaris
相关产品推荐
相关产品推荐

