New-ContentReader and New-ContentWriter return objects implementing
IContentReader and
IContentWriter respectively, bound to the supplied ScriptBlocks via OnRead/OnWrite, OnSeek and OnClose delegate accepting parameters. PowerShell will automatically bind a supplied ScriptBlock to a parameter of Delegate type. The ScriptBlocks run in the bound module's scope.
Here's an example implementation of
IContentCmdletProvider.GetContentReader:
New-PSDrive data ContainerScriptProvider -Root / -ModuleInfo $(New-Module -Name test -Args @{
a = "this is node a."
b = "this is node b."
c = "this is node c."
d = "this is node d."
} -ScriptBlock {
param($data)
function GetContentReader($path) {
$psprovider.writeverbose("getcontentreader '$path'")
# initialize for read operation
$item = $data[$path]
$content = [char[]]$item
$position = 0
# should close around our locals, esp. $position
# to support concurrent content readers.
& {
# create a new content reader and return it
New-ContentReader -OnRead {
param([long]$count)
# this implementation returns a string where $count represents number of char to return
# at a time; you may choose to return whatever you like, and treat $count in any way you feel
# is appropriate. All that matters is that you return an array. Return an empty array to signify
# the end of the stream.
# yes, i could use stringbuilder here but i figure the algorithm is more general purpose for a sample
# as this could be easily adopted for byte arrays.
$remaining = $content.length - $position
if ($remaining -gt 0) {
if ($count -gt $remaining) {
$len = $remaining
} else {
$len = $count
}
$output = new-object char[] $len
[array]::Copy($content, $position, $output, 0, $len)
$position += $len
@($output -join "")
} else {
# end stream, return empty array
write-verbose "read: EOF" -verbose
@()
}
} -OnSeek {
param([long]$offset, [io.seekorigin]$origin)
write-verbose "seek: $offset origin: $origin" -verbose
} -OnClose {
# perform any cleanup you like here.
write-verbose "read: close!" -verbose
}
}.getnewclosure()
}
function GetContentWriter($path) {
$psprovider.writeverbose("getcontentwriter '$path'")
...