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'")
        ...

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

Comments

No comments yet.