在F#/ C#边界保留字段名称

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

type restaurantCsv = CsvProvider<"C:\Users\Paul\Desktop\HealthDepartment\RestaurantRatings2013.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时,不保留字段名称信息.所以我有代码将新的字段名称映射到元组中的.Item1,Item2等:

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#生成类型中的字段名称,所以我不必将row.Item#映射到一个易于阅读的字段名称?换句话说,有没有办法可以拥有这样的代码:

inspectorID = row.InspectorID,
// etc.

注意:我看了How do I create an F# Type Provider that can be used from C#?,但Cameron Taggert的问题和Tomas Petricek的回答在我看来与类型提供者的方面略有不同.即使它们是正确的,我也没有得到它所以我仍然需要更多的帮助.

最佳答案 在F#中有两种不同类型的提供者.更常见和更简单的是擦除类型提供者.更复杂的是生成型提供者.

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

>擦除类型提供程序只是编译器魔术.这是一种确保代码格式正确,正确使用底层API的方法.但这只是编译时间,不会生成任何类型.相反,底层类型用作内部表示.这种类型的提供者在C#中使用起来不是很方便,因为在C#中你只能得到底层类型.
>生成类型提供程序是编译时真正的代码生成步骤.在这种情况下,会生成类型,因此实际存在于程序集中,可以从C#中使用.

您所描述的问题正是人们对擦除类型提供程序的期望.虽然底层类型只是一个元组,但是没有生成类似于类或记录的好类型.并且你不能在C#中使用F#名称,除非类型提供者作为生成类型提供者被不同地编写.

点赞