2

Write-To-File プロシージャにパラメーターを追加したくありませんStreamWriterが、使い捨ての StreamWriter を使用しようとすると、次のようになります。

An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll

Additional information: Cannot write to a closed TextWriter.

コード:

let fileLogger = {
    new IFlog with
        member i.FLog level format =
            use file = LogFile()
            Printf.kfprintf 
                (fun f -> 
                    fprintfn file "[%s][%A] " 
                            <| level.ToString()
                            <| DateTime.Now
                    ) file (format)

FLog メソッドを 2 回呼び出すと、これが得られます。

私はそれをこのように使用できます:member i.FLog file level formatトップレベルで使い捨てオブジェクトを制御しますが、すべての抽象化を失います.

そのような使い捨てオブジェクトを使用する方法はありますか? または、使い捨てのパラメーターをこの関数に渡さないようにアーキテクチャを変更するにはどうすればよいですか?

ログファイルは次のとおりです。

let mutable LogFileName = "F.log"
let LogFile() =
    match File.Exists(LogFileName) with
    | false -> File.CreateText(LogFileName)
    | true  -> File.AppendText(LogFileName)
4

1 に答える 1

5

Printf.kfprintf渡す関数は、変数への参照をキャプチャするクロージャーとしてコンパイルされるため、例外が発生します。fileつまり、TextWriterインスタンスです。Printf.kfprintf戻ると、範囲file外になります。コンパイラは、それが他の場所では使用されていないことを認識Dispose()し、TextWriter. FLogメソッドによって返されたクロージャーを呼び出すまでに、file既に破棄されているため、例外が発生します。

いくつかのコードで視覚化するのは少し簡単です。これは、F# コンパイラがメソッドをコンパイルするFLog方法です。

member i.FLog level format =
    try
        let file = LogFile()
        Printf.kfprintf 
            (fun f -> 
                fprintfn file "[%s][%A] " 
                        <| level.ToString()
                        <| DateTime.Now
                ) file (format)
    finally
        if file <> null then file.Dispose ()

FLogこれは、 implementの宣言型を持ちIDisposablefile値をメソッド内で宣言する代わりにクラスの一部にすることで修正できます。宣言型のDispose()メソッドが呼び出されるときは、 を呼び出すだけfile.Dispose()です。ただし、インスタンスを破棄した後でも、作成したクロージャーを使用しないように注意する必要があります。そうしないとFLog、現在表示されているのと同じ例外が発生します。

于 2013-04-26T12:52:51.767 に答える