CsvHelper 动态列映射

Fra*_*nky 1 c# csvhelper

我按照此示例将自定义列名称映射到我的类模型:

CsvHelper 按名称映射

在这个特定部分:

public FooMap()
{
    Map(m => m.Id).Name("ColumnA");
    Map(m => m.Name).Name("ColumnB");
}
Run Code Online (Sandbox Code Playgroud)

是否可以使用字符串作为列名而不是对其进行硬编码?像这样的事情——

public FooMap()
{
    Map("Col1").Name("ColumnA");
    Map("Col2").Name("ColumnB");
}
Run Code Online (Sandbox Code Playgroud)

“Col1”和“Col2”是我的班级模型的属性。我尝试过使用反射,但没有成功:

Map(x => typeof(MyClassModel).GetProperty("Col1")).Name("ColumnA");
Run Code Online (Sandbox Code Playgroud)

请让我知道我想要实现的目标是否可能。一些附加信息——列映射(源和目标)都存储在表中。

谢谢!

Dav*_*cht 6

这应该允许您使用字符串来映射属性名称和标头名称。

void Main()
{
    var mapping = new Dictionary<string, string>
    {
        {"Id","FooId"},
        {"Name","FooName"}
    };
    
    using (var reader = new StringReader("FooId,FooName\n1,Jordan"))
    using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        var fooMap = new DefaultClassMap<Foo>();

        fooMap.Map(mapping);
        
        csv.Context.RegisterClassMap(fooMap);
        
        var records = csv.GetRecords<Foo>().ToList();
    }   
}

public static class CsvHelperExtensions
{
    public static void Map<T>(this ClassMap<T> classMap, IDictionary<string, string> csvMappings)
    {
        foreach (var mapping in csvMappings)
        {
            var property = typeof(T).GetProperty(mapping.Key);

            if (property == null)
            {
                throw new ArgumentException($"Class {typeof(T).Name} does not have a property named {mapping.Key}");
            }

            classMap.Map(typeof(T), property).Name(mapping.Value);
        }
    }
}

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Run Code Online (Sandbox Code Playgroud)