如何通过数据驱动映射器类

时间:2019-08-26 20:51:11

标签: csvhelper

我正在尝试接受客户端CSV文件,将其映射为标准格式,并生成标准输出。除此之外,每个客户可以使用不同的名称命名标题,并且不保证顺序位置。

我已经为标准格式创建了Class。我什至为此创建了一个映射器。我只想将映射器放在数据库中,这样我就可以为映射添加行,而不是每次客户端更改源文件时都重新构建和部署此代码。

static void Main()
        {
            using (var reader = new StreamReader("filepath\\filename.csv"))
            using (var writer = new StreamWriter("filepath\\Output filename.csv"))
            using (var csvIn = new CsvReader(reader))
            {
                csvIn.Configuration.RegisterClassMap<CsvMap>();
                csvIn.Configuration.PrepareHeaderForMatch = (string header, int index) => header.ToUpper();
                var records = csvIn.GetRecords<CsvClass>();
                using (var csvOut = new CsvWriter(writer))
                {
                    csvOut.WriteRecords(records);
                }
            }

        }

public class CsvClass
        {
            [Optional]
            public Guid CompanyID{ get; set; }
            [Optional]
            public string RecordID{ get; set; }
        }
        public sealed class CsvMap : ClassMap<CsvClass>
        {
            public CsvMap()
            {
                Map(m => m.CompanyID).Name("OrganizationID").Optional();
                Map(m => m.CompanyID).Name("CompanyID").Optional();
                Map(m => m.RecordID).Name("RecordID").Optional();
            }
        }

我是一名数据库开发人员,对c#不太了解,并且需要一个指向我应使用的指针,以便可以通过数据库或json完成这些映射,并将其构建并易于维护。

{"target_field" : "CompanyID"
 "source_field" : "OrganizationID"},
{"target_field" : "CompanyID"
 "source_field" : "CompanyID"},
{"target_field" : "RecordID"
 "source_field" : "RecordID"},

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

这里是我使用的,以便我的用户输入他们使用的标题的名称并将其保存在数据库表中。

CsvMapping类存储标头名称和类的属性名称。

public class CsvMapping 
{
    public string CsvHeaderName { get; set; }
    public string PropertyName { get; set; }
}

然后,我使用一个辅助扩展程序,该扩展程序接受CsvMapping的列表并将其添加到ClassMap

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

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

            if (mapping.CsvHeaderName != null)
            {
                classMap.Map(typeof(T), property).Name(mapping.CsvHeaderName);
            }
        }
    }
}

然后您可以像这样使用它。

public static void Main(string[] args)
{
    using (MemoryStream stream = new MemoryStream())
    using (StreamWriter writer = new StreamWriter(stream))
    using (StreamReader reader = new StreamReader(stream))
    using (CsvReader csv = new CsvReader(reader))
    {
        writer.WriteLine("OrganizationID,RecordID");
        writer.WriteLine("0CEB1F84-4EA6-4C6D-B758-93BFCDF2B8DE,Record1");
        writer.Flush();
        stream.Position = 0;

        var mappings = new List<CsvMapping>
        {
            new CsvMapping { CsvHeaderName = "OrganizationID", PropertyName = "CompanyID" },
            new CsvMapping { CsvHeaderName = "RecordID", PropertyName = "RecordID" }
        };

        var csvMap = new CsvMap();

        csvMap.Map(mappings);

        csv.Configuration.RegisterClassMap(csvMap);

        var records = csv.GetRecords<CsvClass>().ToList();    
    }
}

public sealed class CsvMap : ClassMap<CsvClass>
{
    public CsvMap()
    {
        Map(m => m.CompanyID).Optional();
        Map(m => m.RecordID).Optional();
    }
}