Gần đây tôi đã tham dự hướng dẫn của Keith Battochi về nhà cung cấp loại, trong đó ông đã giới thiệu một biến thể của nhà cung cấp loại MiniCsv trong hướng dẫn MSDN. Thật không may, máy tính xách tay của tôi không có sẵn, vì vậy tôi đã phải viết mã bằng tay cũng như tôi có thể. Tôi tin rằng tôi đã tái tạo các nhà cung cấp loại, nhưng tôi nhận đượcNhà cung cấp loại tùy chỉnh F #: Lỗi "Loại vùng chứa đã được đặt"
error FS3033: The type provider 'CsvFileTypeProvider+CsvFileTypeProvider' reported an error: container type for 'CsvFileProvider.Row' was already set to 'CsvFileProvider.CsvFile,Filename="events.csv"
Khi tôi nhìn vào mã này, tôi không thể nhìn thấy như thế nào tôi thêm loại Row để container hai lần (hoặc một số container khác). Việc xóa các dòng mã đã chọn không có tác dụng.
Đây là cách tôi đang kêu gọi các mã trong FSI:
#r "CsvFileTypeProvider.dll"
open CsvFileProvider
let eventInfos = new CsvFile<"events.csv">() ;;
Và đây là mã bản thân:
module CsvFileTypeProvider
open Samples.FSharp.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
let getType str =
if System.DateTime.TryParse(str, ref Unchecked.defaultof<_>) then
typeof<System.DateTime>, (fun (str:Quotations.Expr) -> <@@ System.DateTime.Parse(%%str) @@>)
elif System.Int32.TryParse(str, ref Unchecked.defaultof<_>) then
typeof<System.Int32>, (fun (str:Quotations.Expr) -> <@@ System.Int32.Parse(%%str) @@>)
elif System.Double.TryParse(str, ref Unchecked.defaultof<_>) then
typeof<System.Double>, (fun (str:Quotations.Expr) -> <@@ System.Double.Parse(%%str) @@>)
else
typeof<string>, (fun (str:Quotations.Expr) -> <@@ %%str @@>)
[<TypeProvider>]
type CsvFileTypeProvider() =
inherit TypeProviderForNamespaces()
let asm = typeof<CsvFileTypeProvider>.Assembly
let ns = "CsvFileProvider"
let csvFileProviderType = ProvidedTypeDefinition(asm, ns, "CsvFile", None)
let parameters = [ProvidedStaticParameter("Filename", typeof<string>)]
do csvFileProviderType.DefineStaticParameters(parameters, fun tyName [| :? string as filename |] ->
let rowType = ProvidedTypeDefinition(asm, ns, "Row", Some(typeof<string[]>))
let lines = System.IO.File.ReadLines(filename) |> Seq.map (fun line -> line.Split(','))
let columnNames = lines |> Seq.nth 0
let resultTypes = lines |> Seq.nth 1 |> Array.map getType
for idx in 0 .. (columnNames.Length - 1) do
let col = columnNames.[idx]
let ty, converter = resultTypes.[idx]
let prop = ProvidedProperty(col, ty)
prop.GetterCode <- fun [row] -> converter <@@ (%%row:string[]).[idx] @@>
rowType.AddMember(prop)
let wholeFileType = ProvidedTypeDefinition(asm, ns, tyName, Some(typedefof<seq<_>>.MakeGenericType(rowType)))
wholeFileType.AddMember(rowType)
let ctor = ProvidedConstructor(parameters = []) // the *type* is parameterized but the *constructor* gets no args
ctor.InvokeCode <- //given the inputs, what will we get as the outputs? Now we want to read the *data*, skip the header
fun [] -> <@@ System.IO.File.ReadLines(filename) |> Seq.skip 1 |> Seq.map (fun line -> line.Split(',')) @@>
wholeFileType.AddMember(ctor)
wholeFileType
)
do base.AddNamespace(ns, [csvFileProviderType])
[<TypeProviderAssembly>]
do()
Nhờ sự giúp đỡ!
Cảm ơn! Đánh giá cao sự trợ giúp. –