问题
I don't want to add StreamWriter
parameter to Write-To-File procedure but when I'm trying to work with disposable StreamWriter there I'm getting:
An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll
Additional information: Cannot write to a closed TextWriter.
code:
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)
so when I call FLog method twice I get this.
I can use it alike this : member i.FLog file level format
and control disposable object on top level but then I lose all the abstraction.
Is there some way to use disposable objects like that? Or how can I change architecture to avoid passing disposable parameter into this function?
LogFile is :
let mutable LogFileName = "F.log"
let LogFile() =
match File.Exists(LogFileName) with
| false -> File.CreateText(LogFileName)
| true -> File.AppendText(LogFileName)
回答1:
You're getting the exception because the function you pass to Printf.kfprintf
is compiled as a closure which captures a reference to your file
variable -- i.e., your TextWriter
instance. Once Printf.kfprintf
returns, file
goes out of scope; the compiler sees that it is not used anywhere else and thus inserts some code to call the Dispose()
method on the TextWriter
. By the time you call the closure returned by the FLog
method, file
has already been disposed so the exception is raised.
It's a little easier to visualize with some code. This is how the F# compiler compiles the FLog
method:
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 ()
You could fix this by having the declaring type of FLog
implement IDisposable
, and making the file
value part of the class instead of declaring it within the method. When the declaring type's Dispose()
method is called, it should just call file.Dispose()
. You'll still need to take care not to use any closures you've created with FLog
after you've disposed the instance though, or you'll end up with the same exception you're seeing now.
来源:https://stackoverflow.com/questions/16234364/why-i-can-not-use-disposable-objects-in-object-members