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 {
    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 {
                # 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

    function GetContentWriter($path) {
        $psprovider.writeverbose("getcontentwriter '$path'")

Last edited Jul 15, 2010 at 8:41 PM by oisin, version 2


No comments yet.