I followed the link of parse CSV using F# and filehelpers. got compiler error for the following code "The record class oneRow need a constructor with no args (public or private)"
[<DelimitedRecord(",")>]
type oneRow=
class
[<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
val date: DateTime
val value: bool
end
let engine = new FileHelperEngine(typeof<oneRow>)
let tmp = engine.ReadFile("test.csv")
EDIT
The solution looks quite verbose than c# version. I need add ()
, mutable
and [<DefaultValue>]
type oneRow() =
class
[<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
[<DefaultValue>]
val mutable date: Da开发者_高级运维teTime
[<DefaultValue>]
val mutable value: bool
end
But similar code works in C# without specify a constructor. Could anyone help me fix the F# code? thanks.
C# will create you a constructor. F# doesn't (presumably because parameterless constructors imply mutability, and so are not exactly encouraged.)
For example, in your code - how are you going to set those properties, they're still immutable.
Regarding the verbose syntax - It can be made nicer. The sample was written some time ago (2 years), so it is still using a little old syntax. It could be updated to allow writing something like this:
[<DelimitedRecord(",")>]
type OneRow
( [<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
date:DateTime,
value:bool ) =
member x.Date = date
member x.Value = value
I believe this is a lot nicer (and by moving annotations to the constructor, you can also implement your own functionality in the type and e.g. hide some fields). The only change that needs to be done is to modify the parser to find attributes on constructor parameters (and not fields).
Based on the error message, i think it would work if a ctor is added into oneRow.
new () = { date = new DateTime() ; value = false}
yes, it should be type oneRow () =
with parentheses
Most of the posts concerning FileHelpers are rather dated. In some cases though it's nice to use instead of the csv type provider. One can use the CLIMutable
attribute on an F# record to have a default constructor and in this case FileHelpers will happily write and read the csv file:
#if INTERACTIVE
#I @"..\packages\FileHelpers\lib\net45"
#r "FileHelpers.dll"
#endif
open FileHelpers
open System
[<DelimitedRecord(",");CLIMutable>]
type TestFileHelp =
{test1:string
test2:string
[<FieldConverter(ConverterKind.Date, "yyyy/MM/dd")>]
date:DateTime
}
let f1 = [|{test1="a";test2="b";date=DateTime.Now};{test1="c";test2="d";date=DateTime.Now}|]
let fengine = new FileHelperEngine<TestFileHelp>()
fengine.WriteFile(@"c:\tmp\testrec.csv",f1)
精彩评论