我不想将StreamWriter
参数添加到Write-To-File过程中,但是当我尝试使用一次性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方法时,我得到了这个。
我可以使用它:member i.FLog file level format
并在顶层控制一次性对象,但后来我失去了所有的抽象。
有没有办法像这样使用一次性物品?或者我如何更改架构以避免将一次性参数传递给此函数?
LogFile是:
let mutable LogFileName = "F.log"
let LogFile() =
match File.Exists(LogFileName) with
| false -> File.CreateText(LogFileName)
| true -> File.AppendText(LogFileName)
答案 0 :(得分: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
实现IDisposable
并使file
值成为类的一部分而不是在方法中声明它来解决此问题。当调用声明类型的Dispose()
方法时,它应该只调用file.Dispose()
。在处理完实例后,您仍然需要注意不要使用FLog
创建的任何闭包,否则您最终会遇到与现在相同的异常。