FileHelpers BadUsageException仅在编译的F#上,但不在脚本中

时间:2012-01-27 18:01:19

标签: oop f# filehelpers

我写了一个非常好的fsi脚本,想要编译它以便我可以更轻松地移动它。但是,当我编译它时,FileHelpers突然开始出错。

以下代码使用FileHelpers 2.9.9。这是一个简单的工作示例来说明问题,test.fsx

#r "FileHelpers.dll"

open FileHelpers

[<DelimitedRecord(",")>]
type Type = 
    val field1 : string
    val field2 : int
    override x.ToString() = sprintf "%s: %d" x.field1 x.field2

let readFile<'a> file = seq {
    use engine1 = new FileHelperAsyncEngine(typeof<'a>)
    use tmp1 = engine1.BeginReadFile(file)

    engine1.ReadNext() |> ignore

    while engine1.LastRecord <> null do
        yield engine1.LastRecord :?> 'a
        engine1.ReadNext() |> ignore
    }


readFile<Type> "test.csv" |> Seq.iter (printfn "%A")

将文件test.csv设为

test1,1
test2,2
test3,3

如果我将代码作为fsi .\test.fsx运行,它将正常工作。但是,如果我尝试使用fsc .\test.fsx进行编译并运行.\test.exe,则会收到错误Unhandled Exception: FileHelpers.BadUsageException: The record class Type needs a constructor with no args (public or private)。在脚本和编译模式下工作的解决方法是

[<DelimitedRecord(",")>]
type Type () = 
    [<DefaultValue>]
    val mutable field1 : string
    [<DefaultValue>]
    val mutable field2 : int
    override x.ToString() = sprintf "%s: %d" x.field1 x.field2

为什么它可以作为脚本运行但不编译?如果可能的话,我想保持不变。感谢您的任何见解!

1 个答案:

答案 0 :(得分:1)

FSI使用System.Reflection.Emit即时编译您的F#代码。看来,使用System.Reflection.Emit生成的类型总是至少有一个构造函数(默认的公共构造函数或显式定义的构造函数)。因此,FSI发出的代码不可能完全模仿编译代码的结果,编译代码根本没有构造函数(既不公开也不私有)。