Search code examples
powershelldelegatespipelinescriptblock

Is there a way to create a Cmdlet "delegate" that supports pipeline parameter binding?


In .NET if you have a subroutine whose implementation might change from one call to another, you can pass a delegate to the method that uses the subroutine. You can also do this in Powershell. You can also use scriptblocks which have been described as Powershell's equivalent of anonymous functions. Idiomatic powershell, however, makes use of powershell's pipeline parameter bindings. But neither delegates nor scriptblocks seem to make use of Powershell's pipeline parameter bindings.

Is there a (idiomatic) way to pass a powershell commandlet to another commandlet in a way that preserves support for pipeline parameter bindings?

Here is a code snippet of what I'd like to be able to do:

Function Get-Square{
    [CmdletBinding()] 
    Param([Parameter(ValueFromPipeline=$true)]$x)
    PROCESS{$x*$x}
}
Function Get-Cube{
    [CmdletBinding()] 
    Param([Parameter(ValueFromPipeline=$true)]$x)
    PROCESS{$x*$x*$x}
}
Function Get-Result{
    [CmdletBinding()]
    Param([Parameter(ValueFromPipeline=$true)]$x,$Cmdlet)
    PROCESS{$x | $Cmdlet}
}

10 | Get-Result -Cmdlet {Get-Square}
10 | Get-Result -Cmdlet {Get-Cube}

Solution

  • That'll work. You've just got some syntax issues with your function definitions and how you're passing the parameters:

    Function Get-Square{
        [CmdletBinding()] 
        Param([Parameter(ValueFromPipeline=$true)]$x)
        $x*$x
    }
    Function Get-Cube{
        [CmdletBinding()] 
        Param([Parameter(ValueFromPipeline=$true)]$x)
        $x*$x*$x
    }
    Function Get-Result{
        [CmdletBinding()]
        Param([Parameter(ValueFromPipeline=$true)]$x,$Cmdlet)
        $x | . $cmdlet
    }
    
    10 | Get-Result -Cmdlet Get-Square
    10 | Get-Result -Cmdlet Get-Cube
    
    100
    1000