跨F#/C#边界保留字段名



作为一个学习练习,我正在使用F#和F#的类型提供程序功能对一个5000行的csv文件进行一些数据分析。当我在f#中使用类型提供者生成的类型时,csv文件的头行自然会成为该类型的字段名。

type restaurantCsv = CsvProvider<"C:UsersPaulDesktopHealthDepartmentRestaurantRatings2013.csv",HasHeaders=true>
type RawInspectionData(filename : string) = 
member this.allData = restaurantCsv.Load(filename)
member public this.inspectionsList = this.allData.Data.ToList()
member this.FilterByName(name : string) =
this.allData.Data 
|> Seq.filter (fun x -> x.EstablishmentName.Contains(name))

此外,我正在从一个单元测试C#文件中调用F#代码(在上面代码创建的库中)。它运行良好。但是,当我使用F#从FilterByName返回的IEnumberable时,字段名称信息不会被保留。因此,我有了将新字段名映射到的代码。元组中的第1项、第2项等:

var inspectionsOnCafes = inspections2013.FilterByName("Cafe");
var inspections = (from row in inspectionsOnCafes
select new
{
inspectorID = row.Item3,
restaurantName = row.Item5,
inspectionDate = row.Rest.Item6
}).ToList();

我的问题有没有办法让C#识别F#生成的类型中的字段名,这样我就不必映射行了。项目#转换为易于阅读的字段名称?换句话说,有没有一种方法可以让我拥有这样的代码:

inspectorID = row.InspectorID,
// etc.

注意:我看了如何创建一个可以从C#使用的F#类型提供程序?但Cameron Taggert的问题和Tomas Petricek的回答在我看来似乎是关于类型提供者的一个稍微不同的方面。即使他们在现场,我也不明白,所以我仍然需要更多的帮助。

在F#中有两种不同类型的类型提供程序。更常见和更简单的是擦除类型提供程序。更复杂的是生成型提供者。

区别对于C#来说非常重要,因为:

  • 擦除类型提供程序只是编译器的魔法。这是一种确保代码格式良好、正确使用底层API的方法。但这只是编译时,并且不会生成任何类型。而是将参考底图类型用作内部表达。从C#使用这种类型提供程序不是很方便,因为在C#中只能获得底层类型。

  • 生成类型提供程序是编译时真正的代码生成步骤。在这种情况下,类型是生成的,因此实际上存在于程序集中,并且可以从C#中使用。

您所描述的问题正是您对已擦除类型提供程序的期望。而底层类型只是一个元组,但没有生成像类或记录这样的好类型。并且不能在C#中使用F#名称,除非类型提供程序作为生成类型提供程序以不同的方式编写。

最新更新