FileHelpers BadUsageException только в скомпилированном F#, но не в скрипте

Я написал 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

Почему он работает как скрипт, но не компилируется? Я хотел бы сохранить его неизменным, если это возможно. Спасибо за любое понимание!


person Taylor Southwick    schedule 27.01.2012    source источник


Ответы (1)


FSI использует System.Reflection.Emit для компиляции кода F# на лету. Похоже, что типы, созданные с помощью System.Reflection.Emit, всегда имеют по крайней мере один конструктор (либо общедоступный конструктор по умолчанию, либо явно определенный конструктор). Таким образом, код, созданный FSI, не может точно имитировать результат скомпилированного кода, который вообще не имеет конструкторов (ни общедоступных, ни частных).

person kvb    schedule 27.01.2012