Function overloading in PowerShell

前端 未结 4 1666
温柔的废话
温柔的废话 2020-12-15 16:11

Can you overload functions in PowerShell?

I want to my function to accept a string, array or some switch.

An example of what I want:

  • Backup-Use
相关标签:
4条回答
  • 2020-12-15 16:24

    If you use PSObject instead of Object to define your parameter type, it should work. For example, The function Get-Control, know's how to overload based on type string or template and can be called using the positional value:

        Get-Control "A-Name-Of-A-Control"
        Get-Control $template
    

    To make the overload work, use PSObject as follows:

    Function Get-Control {
        Param(
            [Parameter(Mandatory=$False,ParameterSetName="ByTemplate",Position=0)]
            [PSObject]
            $Template,
    
            [Parameter(Mandatory=$False,ParameterSetName="ByName",Position=0)]        
            [String]
            $Name,
    
            [Parameter(Mandatory=$False)] 
            [Switch]
            $List
          ) 
       ... # remaining code removed for brevity
    
    0 讨论(0)
  • 2020-12-15 16:28

    In PowerShell functions are not overloaded. The last definition overrides the previous in the same scope or hides the previous in a parent scope. Thus, you should create a single function and provide a way to distinguish its call mode by arguments.

    In V2 you may use an advanced function, see help about_Functions_Advanced_Parameters and avoid some manual coding on resolving parameter set ambiguities:

    # advanced function with 3 parameter sets
    function Backup-UsersData
    (
        [Parameter(Position=0, ParameterSetName="user")]
        [string]$user,
        [Parameter(Position=0, ParameterSetName="array")]
        [object[]]$array,
        [Parameter(Position=0, ParameterSetName="all")]
        [switch]$all
    )
    {
        # use this to get the parameter set name
        $PSCmdlet.ParameterSetName
    }
    
    # test
    Backup-UsersData -user 'John'
    Backup-UsersData 1, 2
    Backup-UsersData -all
    
    # OUTPUT:
    # user
    # array
    # all
    

    Note that this mechanism is sometimes strange. For example in the first test we have to specify parameter name -user explicitly. Otherwise:

    Backup-UsersData : Parameter set cannot be resolved using the specified named parameters.
    At C:\TEMP\_101015_110059\try2.ps1:21 char:17
    + Backup-UsersData <<<<  'John'
        + CategoryInfo          : InvalidArgument: (:) [Backup-UsersData], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : AmbiguousParameterSet,Backup-UsersData
    

    In many cases standard, not advanced, function with mixed parameters will do:

    function Backup-UsersData
    (
        [string]$user,
        [object[]]$array,
        [switch]$all
    )
    {
        if ($user) {'user'}
        elseif ($array) {'array'}
        elseif ($all) {'all'}
        else {'may be'}
    }
    
    Backup-UsersData -user 'John'
    Backup-UsersData -array 1, 2
    Backup-UsersData -all
    Backup-UsersData
    

    But in this case you should resolve (or accept and ignore) ambiguities, e.g. to decide what to do if, say:

    Backup-UsersData -user 'John' -array 1, 2 -all
    
    0 讨论(0)
  • 2020-12-15 16:37

    1) Build a class...

    class c1 { 
        [int]f1( [string]$x ){ return 1 } 
        [int]f1( [int ]$x ){ return 2 }
        }
    

    1+) Use STATIC METHODS if you prefer to call them without instantiation...

    class c1 { 
        static [int] f1( [string]$x ){ return 1 } 
        static [int] f1( [int]$x ){ return 2 } 
        }
    

    2) Call the methods in class or object... overload works OK

    $o1 = [c1]::new()
    o1.f1( "abc" ) ~> returns 1
    o1.f1( 123 )   ~> returns 2
    

    -OR-


    [c1]::f1( "abc" ) ~> returns 1
    [c1]::f1( 123 )   ~> returns 2
    

    3) If (like me)
    you want to have "Overloaded Functions" placed in a libraries...
    so your users can use them transparently...
    from code or from Interactive Command Line (REPL)...

    the closest I could came to
    "Overloading functions in Powershell"
    was something like this:

    function Alert-String() { [c1]::f1( "abc" ) }
    function Alert-Strings(){ [c1]::f1( 123 ) }
    function Alert-Stringn(){ [c1]::f1( 123 ) }
    

    Maybe in PS-Core v8??? ;-)

    Hope it helps...

    0 讨论(0)
  • 2020-12-15 16:38

    Here is a variant of Roman's answer that I think is a little more flexible:

    function Backup
    {
        [CmdletBinding(DefaultParameterSetName='Users')]
        Param (
            [parameter(mandatory=$true, ParameterSetName='Users', position=0, ValueFromPipeline=$true)][string[]]$User,
            [parameter(mandatory=$true, ParameterSetName='AllUsers')][switch]$All
        )
    
        Begin
        {
            if ($All) { $User = @('User1', 'User2', 'User3') }
        }
    
        Process
        {
            foreach ($u in $User)
            {
                echo "Backup $u"
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题