我想从 System.IO.BinaryWriter
派生一个类,并使用自定义 Stream
调用它的构造函数,其实现捕获派生的构造函数参数类型。对于我的生活,我什至无法弄清楚这是否可能。我基本上想做的是,稍微修剪成 MCV,是
type HashingBinaryWriter private
(hasher : System.Security.Cryptography.HashAlgorithm,
stream : System.IO.Stream) =
inherit System.IO.BinaryWriter(stream)
let unsupp() = raise(System.NotSupportedException())
let hash_stream =
{ new System.IO.Stream() with
member __.CanRead = false
member __.CanSeek = false
member __.CanWrite = true
member __.Length = unsupp()
member __.Position with get() = unsupp() and set(_) = unsupp()
member __.Seek(_,_) = unsupp()
member __.SetLength _ = unsupp()
member __.Read(_,_,_) = unsupp()
member __.Flush() = ()
member __.Write(buffer, offset, count) =
hasher.TransformBlock(buffer, offset, count, null, 0) |> ignore
}
new(hasher) = new HashingBinaryWriter(hasher, hash_stream)
// Or, alternatively
new(hasher) as me = new HashingBinaryWriter(hasher, me.hash_stream)
最后一行编译失败,因为 hash_stream
未定义,无论是哪种形式。显然,作为this answer建议,构造函数参数的范围不同于类声明主体的范围,但我需要了解这里发生了什么(如果可能的话,还有 F# 设计决策背后的原因)。
的确,我可以看到一些解决方法(例如,将 hash_stream 转换为私有(private)属性),但我的 F# 习语词汇表中缺少这个。那么,我的第二个问题是,这样做的惯用方式是什么。
最佳答案
有多种方法可以做到这一点 - 我想正确的选择取决于您的完整实现的外观。
如果你想要尽可能接近你问题中的版本的东西,那么你可以在构造函数中移动 unsupp
和 hash_stream
:
type HashingBinaryWriter private
(hasher : System.Security.Cryptography.HashAlgorithm,
stream : System.IO.Stream) =
inherit System.IO.BinaryWriter(stream)
new(hasher : System.Security.Cryptography.HashAlgorithm) =
let unsupp() = raise(System.NotSupportedException())
let hash_stream =
{ new System.IO.Stream() with
member __.CanRead = false
member __.CanSeek = false
member __.CanWrite = true
member __.Length = unsupp()
member __.Position with get() = unsupp() and set(_) = unsupp()
member __.Seek(_,_) = unsupp()
member __.SetLength _ = unsupp()
member __.Read(_,_,_) = unsupp()
member __.Flush() = ()
member __.Write(buffer, offset, count) =
hasher.TransformBlock(buffer, offset, count, null, 0) |> ignore
}
new HashingBinaryWriter(hasher, hash_stream)
我想如果您的 hash_stream
实现变长,这很容易变得丑陋。在这种情况下,按照 John 在评论中的建议将流的实现移到类之外,也许移到辅助模块中会更有意义:
let unsupp() = raise(System.NotSupportedException())
let createHashStream (hasher : System.Security.Cryptography.HashAlgorithm) =
{ new System.IO.Stream() with
member __.CanRead = false
member __.CanSeek = false
member __.CanWrite = true
member __.Length = unsupp()
member __.Position with get() = unsupp() and set(_) = unsupp()
member __.Seek(_,_) = unsupp()
member __.SetLength _ = unsupp()
member __.Read(_,_,_) = unsupp()
member __.Flush() = ()
member __.Write(buffer, offset, count) =
hasher.TransformBlock(buffer, offset, count, null, 0) |> ignore
}
type HashingBinaryWriter private
(hasher : System.Security.Cryptography.HashAlgorithm,
stream : System.IO.Stream) =
inherit System.IO.BinaryWriter(stream)
new(hasher : System.Security.Cryptography.HashAlgorithm) =
new HashingBinaryWriter(hasher, createHashStream hasher)
关于f# - 将捕获构造函数参数的闭包传递给基类构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36524292/