programing

PowerShell에서 함수 오버로드

closeapi 2023. 7. 25. 20:58
반응형

PowerShell에서 함수 오버로드

PowerShell의 기능을 오버로드할 수 있습니까?

문자열, 배열 또는 일부 스위치를 허용하는 기능을 사용합니다.

내가 원하는 것의 예:

  • 백업 사용자 데이터 단일 사용자
  • 백업-사용자 데이터 @('Alice', 'Bob', 'Joe')
  • 백업 - 사용자 데이터 - 모두

PowerShell에서는 기능이 오버로드되지 않습니다.마지막 정의는 동일한 범위의 이전 정의를 재정의하거나 상위 범위의 이전 정의를 숨깁니다.따라서 단일 함수를 만들고 변수로 호출 모드를 구분할 수 있는 방법을 제공해야 합니다.

V2에서는 고급 기능을 사용할 수 있습니다( 참조).help about_Functions_Advanced_Parameters매개 변수 집합의 모호성을 해결하기 위한 일부 수동 코딩을 피합니다.

# 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

이 메커니즘은 때때로 이상합니다.예를 들어 첫 번째 테스트에서는 매개 변수 이름을 지정해야 합니다.-user노골적으로그렇지 않은 경우:

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

대부분의 경우 혼합 파라미터를 사용하는 표준 기능은 다음과 같습니다.

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

그러나 이 경우 모호성을 해결(또는 수락 및 무시)해야 합니다. 예를 들어 다음과 같은 경우에 수행할 작업을 결정해야 합니다.

Backup-UsersData -user 'John' -array 1, 2 -all

제가 생각하기에 조금 더 유연하다고 생각하는 로만의 답변의 변형은 다음과 같습니다.

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"
        }
    }
}

클래스 만들기...

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

1+) 인스턴스화 없이 호출하려는 경우 정적 메서드 사용...

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

클래스 또는 개체의 메서드를 호출합니다...오버로드가 정상적으로 작동합니다.

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

-또는-


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

만약 (나처럼)
라이브러리에 "Overloaded Functions"를 배치하려는 경우...
사용자가 투명하게 사용할 수 있도록...
코드 또는 REPL(Interactive Command Line)에서...

내가 가장 가까이에 가장 가까운
"Powershell에서 함수를 오버로드하는 중"
다음과 같은 것이었습니다.

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

아마도 PS-Core v8에서?---)

도움이 되길...

Object 대신 PSObject를 사용하여 매개 변수 유형을 정의하면 작동합니다.예를 들어 Get-Control 함수는 형식 문자열 또는 템플릿을 기반으로 오버로드하는 방법을 알고 있으며 위치 값을 사용하여 호출할 수 있습니다.

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

오버로드가 작동하도록 하려면 다음과 같이 PSObject를 사용합니다.

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

언급URL : https://stackoverflow.com/questions/3940722/function-overloading-in-powershell

반응형