C# 带有参数的RegisterClassMap中的泛型类型

C# 带有参数的RegisterClassMap中的泛型类型,c#,generics,csvhelper,C#,Generics,Csvhelper,我们需要一种使用CsvHelper的通用方法。根据情况,CSV文件的格式不同。当外部系统具有所有必需的信息时,会出现更多列。我需要确定CSV文件中是否存在列的名称(这是在ResponseMap中完成的) 所以我们有一个接口 List<T> ConvertTo<T, TMap>(string file, Dictionary<string, string> headers) where T : class

我们需要一种使用CsvHelper的通用方法。根据情况,CSV文件的格式不同。当外部系统具有所有必需的信息时,会出现更多列。我需要确定CSV文件中是否存在列的名称(这是在ResponseMap中完成的)

所以我们有一个接口

List<T> ConvertTo<T, TMap>(string file, Dictionary<string, string> headers) where T : class
                                          where TMap : ClassMap<T>;
List ConvertTo(字符串文件、字典头),其中T:class
其中TMap:ClassMap;
我这样称呼它

_csvRepository.ConvertTo<ResponseNgi, ResponseMap>(file, headers);
\u csvRepository.ConvertTo(文件、标题);
字典包含的列名称取决于我们处理的情况(例如,所有信息=13列,而不是所有信息=7列)

ConvertTo方法的实现:

public List<T> ConvertTo<T, TMap>(string file, Dictionary<string,string> headers) where T : class
                            where TMap : ClassMap<T>
    {
        using (var reader = new StreamReader(file, Encoding.GetEncoding("iso-8859-1")))
        using (var csvReader = new CsvReader(reader))
        {
            var good = new List<T>();

            // Set up CSV Helper
            csvReader.Configuration.Delimiter = ";";
            csvReader.Configuration.IgnoreQuotes = true;
            csvReader.Configuration.HasHeaderRecord = true;
            csvReader.Configuration.HeaderValidated = null;
            csvReader.Configuration.MissingFieldFound = null;
            csvReader.Configuration.TrimOptions = TrimOptions.Trim;

            csvReader.Configuration.RegisterClassMap(new ResponseMap(headers)); 
            // csvReader.Configuration.RegisterClassMap<TMap>(); Can't pass dictionary like this

            // rest of the processing

            return good.ToList();
        }
    }
public List ConvertTo(字符串文件、字典头),其中T:class
其中TMap:ClassMap
{
使用(var reader=newstreamreader(文件,Encoding.GetEncoding(“iso-8859-1”))
使用(var csvReader=新csvReader(读卡器))
{
var good=新列表();
//设置CSV帮助程序
csvReader.Configuration.Delimiter=“;”;
csvReader.Configuration.IgnoreQuotes=true;
csvReader.Configuration.HasHeaderRecord=true;
csvReader.Configuration.HeaderValidated=null;
csvReader.Configuration.MissingFieldFound=null;
csvReader.Configuration.trimpoptions=trimpoptions.Trim;
csvReader.Configuration.RegisterClassMap(新的响应映射(头));
//csvReader.Configuration.RegisterClassMap();无法像这样传递字典
//其余的处理
返回good.ToList();
}
}
正如您在代码片段中看到的,为了能够传递头,我显式地使用了ResponseMap。感觉不对

还有ResponseMap类,它是ClassMap的一个子类

public class ResponseMap : ClassMap<ResponseNgi>
{
    public ResponseMap(Dictionary<string, string> headers)
    {
        Map(m => m.Street).Name(headers["street"]);
        Map(m => m.HouseNumber).Name(headers["house number"]);
        Map(m => m.PostalCode).Name(headers["postal code"]);
        Map(m => m.MunicipalitySection).Name(headers["municipality section"]);
        Map(m => m.Municipality).Name(headers["municipality"]);
        Map(m => m.StreetCode).Name(headers["street code"]);

        if (headers.ContainsKey("x"))
            Map(m => m.Xlambert).Name(headers["x"]).TypeConverter<CustomDoubleConverter>();

        if (headers.ContainsKey("y"))
            Map(m => m.YLambert).Name(headers["y"]).TypeConverter<CustomDoubleConverter>();

        if (headers.ContainsKey("z"))
            Map(m => m.ZLambert).Name(headers["z"]).TypeConverter<CustomDoubleConverter>();

        if (headers.ContainsKey("nrn"))
            Map(m => m.Nrn).Name(headers["nrn"]);

        if (headers.ContainsKey("source"))
            Map(m => m.Source).Name(headers["source"]);

        if (headers.ContainsKey("method"))
            Map(m => m.Method).Name(headers["method"]);

        Map(m => m.GeoadresId).Name(headers["geoadresId"]);
    }
}
公共类响应映射:类映射
{
公共响应映射(字典标题)
{
地图(m=>m.Street)。名称(标题[“Street”]);
地图(m=>m.HouseNumber).Name(标题[“HouseNumber]”);
Map(m=>m.PostalCode).Name(标题[“邮政编码]);
地图(m=>m.MunicipalitySection).Name(标题[“市政区]);
地图(m=>m.citificity).Name(标题[“citificity”]);
地图(m=>m.StreetCode).Name(标题[“街道代码]);
if(headers.ContainsKey(“x”))
Map(m=>m.Xlambert).Name(headers[“x”]).TypeConverter();
if(标题为“y”)
Map(m=>m.YLambert).Name(headers[“y”]).TypeConverter();
if(headers.ContainsKey(“z”))
Map(m=>m.ZLambert).Name(headers[“z”]).TypeConverter();
if(标题.容器(“nrn”))
Map(m=>m.Nrn).Name(头[“Nrn”]);
if(headers.ContainsKey(“源”))
Map(m=>m.Source).Name(headers[“Source”]);
if(headers.ContainsKey(“方法”))
Map(m=>m.Method).Name(headers[“Method”]);
Map(m=>m.GeoadresId).Name(headers[“GeoadresId”]);
}
}

如何使用泛型类型(TMap)调用RegisterClassMap,并根据情况正确映射CSV

我有一个扩展方法,用于将头映射到泛型类型。我必须允许相同的扩展方法传入一个
可选的
变量。不幸的是,可选部分目前不起作用,但是您可以在
ResponseMap
中设置不总是用于
optional
的6列。您还可以将扩展方法与
Dictionary
一起使用,而不是
IEnumerable

publicstaticlist-ConvertTo(字符串文件,IEnumerable头文件),其中T:class
其中TMap:ClassMap
{
使用(var reader=newstreamreader(文件,Encoding.GetEncoding(“iso-8859-1”))
使用(var csvReader=新csvReader(读卡器))
{
var good=新列表();
//设置CSV帮助程序
csvReader.Configuration.Delimiter=“;”;
csvReader.Configuration.IgnoreQuotes=true;
csvReader.Configuration.HasHeaderRecord=true;
csvReader.Configuration.HeaderValidated=null;
csvReader.Configuration.MissingFieldFound=null;
csvReader.Configuration.trimpoptions=trimpoptions.Trim;
var classMap=csvReader.Configuration.RegisterClassMap();
Map(标题);
good=csvReader.GetRecords().ToList();
返回good.ToList();
}
}
公共类CsvMapping
{
公共字符串CsvHeaderName{get;set;}
公共字符串PropertyName{get;set;}
公共bool可选{get;set;}
}
公共静态类CsvHelperExtensions
{
公共静态void映射(此类映射类映射,IEnumerable csvMappings)
{
foreach(csvMappings中的var映射)
{
var property=typeof(T).GetProperty(mapping.PropertyName);
if(属性==null)
{
抛出新ArgumentException($“类{typeof(T).Name}没有名为{mapping.PropertyName}的属性”);
}
if(mapping.CsvHeaderName!=null)
{
Map(typeof(T),property).Name(mapping.CsvHeaderName);
}
////向CsvHelper请求修复可选()方法。2019年3月14日
//if(mapping.Optional)
//{
//Map(typeof(T),property).Optional();
//}
}
}
}
公共类响应映射:类映射
{
公众回应地图(
{
地图(m=>m街);
地图(m=>m.HouseNumber);
Map(m=>m.PostalCode);
地图(m=>m.市政区);
地图(m=>m.自治市);
地图(m=>m.StreetCode);
Map(m=>m.Xlambert).TypeConverter().Optional();
Map(m=>m.YLambert).TypeConverter().Optional();
映射(m=>m.ZLambert).TypeConvert