C#泛型返回类型与不同的泛型参数

3

我正在处理一系列不同的CSV文件,希望编写一个通用的读写器,只需传递必要的类型即可。RegisterClassMap()通常需要您定义的映射器。第一个示例是不使用泛型的工作代码。

    public static IEnumerable<CacheEntryRequest> ReadCacheRequestFile(string filename)
    {
        List<CacheEntryRequest> requests;
        using (var sr = new StreamReader(filename))
        {
            var csv = new CsvReader(sr);
            csv.Configuration.RegisterClassMap<CacheEntryRequestMapper>();
            requests = csv.GetRecords<CacheEntryRequest>().ToList();
        }

        return requests;
    }

以下是我尝试写一个通用方法,使用Mapper类型的通用参数,但失败了:
    public static IEnumerable<TR> Read<TR, TMap>(string filename)
    {
        List<TR> records;
        using (var sr = new StreamReader(filename))
        {
            var csv = new CsvReader(sr);
            csv.Configuration.RegisterClassMap<TMap>();
            records = csv.GetRecords<TR>().ToList();
        }
        return records;
    }

接下来,RegisterClassMap会抱怨:

类型“TMap”无法用作泛型类型或方法“CsvConfiguration.RegisterClassMap()”中的类型参数“TMap”。从“TMap”到“CsvHelper.Configuration.CsvClassMap”没有装箱、拆箱转换或类型参数转换。

期望的用法是:

        var records = CsvFile.Read<CacheEntryRequest, CacheEntryRequestMapper>(filename);

1
看起来 RegisterClassMap 有一个泛型约束,只允许它与 CsvClassMap 或其派生类一起使用,但是你的 Read 方法没有在 TMap 上放置类似的约束。 - Pieter Witvoet
2个回答

5
为了能够使用 TMapTMap 需要与 RegisterClassMap<T> 方法的输入类型兼容。
你可以使用泛型约束来实现。请参阅 https://msdn.microsoft.com/en-us/library/d5x73970.aspx
在你的情况下,你需要更改方法签名为 public static IEnumerable<TR> Read<TR, TMap>(string filename) where TMap : CsvClassMap 或类似的方法。
可能类 CacheEntryRequest 有一个基类。那就是你的泛型约束。
现在假设你有一个类映射如下:
public class CustomCacheEntryRequestMapper :  CsvClassMap
{
    ...
}

你可以像下面这样调用你的方法:
var records = CsvFile.Read<CacheEntryRequest, CustomCacheEntryRequestMapper >(filename); 

需要如何更改调用?“类型...CacheEntryRequestMapper不能用作泛型类型或方法'CsvFile.Read<TR.TMap>(string)'中的类型参数'TMap'。” - disassemble-number-5
哦,我觉得你上面已经回答了。在这种情况下,调用方必须提供一个从TMap派生的类型,即CsvClassMap。调用方的定义是...public sealed class CacheEntryRequestMapper:CsvClassMap<CacheEntryRequest>。 - disassemble-number-5

4

在@PeterBons提供的答案中,若要添加多个约束条件,则需要按以下方式添加:

public static IEnumerable<TR> Read<TR, TMap>(string filename) 
    where TMap : OneClass
    where TR : AnotherClass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接