簡體   English   中英

PowerShell管道參數綁定順序

[英]PowerShell pipeline parameter binding order

我有一個高級函數,可以接受兩種管道數據:

  • PSTypeName為“MyType”的自定義對象
  • 任何具有ID屬性的對象

這是我的功能:

function Test-PowerShell {
    [CmdletBinding(DefaultParameterSetName = "ID")]
    param (
        [Parameter(
            Mandatory = $true,
            ParameterSetName = "InputObject",
            ValueFromPipeline = $true
        )]
        [PSTypeName('MyType')]
        $InputObject,

        [Parameter(
            Mandatory = $true,
            ParameterSetName = 'ID',
            ValueFromPipelineByPropertyName = $true
            )]
        [int]
        $ID
    )

    process {
        if ($InputObject) {
            $objects = $InputObject
            Write-Verbose 'InputObject binding'
        }
        else {
            $objects = Get-MyType -ID $ID
            Write-Verbose 'ID binding'
        }

        # Do something with $objects
    }
}

我可以像這樣使用這個函數:

$obj = [PSCustomObject]@{
    PSTypeName = 'MyType'
    ID = 5
    Name = 'Bob'
}
$obj | Test-PowerShell -Verbose

請注意,此對象滿足上述兩個條件:它是MyType,並且具有ID屬性。 在這種情況下,PowerShell始終綁定到ID屬性。 這在性能方面並不理想,因為管道對象被丟棄,我不得不使用ID重新查詢它。 我的問題是:

如果可能,如何強制PowerShell將管道綁定到$ InputObject?

如果我將默認參數設置更改為InputObject,PowerShell將綁定$ InputObject。 但是,我不希望這樣,因為在沒有參數的情況下運行時,我希望PowerShell提示輸入ID,而不是InputObject。

簡單的答案:刪除$InputObject上的Parameter屬性的Mandatory參數以獲得所需的功能。 我沒有關於如何參數綁定作品解釋為什么這個作品足夠的知識。

function Test-PowerShell {
    [CmdletBinding(DefaultParameterSetName = 'ID')]
    param(
        [Parameter(ParameterSetName = 'InputObject', ValueFromPipeline)]
        [PSTypeName('MyType')]
        $InputObject,

        [Parameter(ParameterSetName = 'ID', Mandatory, ValueFromPipelineByPropertyName)]
        [int]
        $ID
    )

    process {
        $PSBoundParameters
    }
}

$o = [pscustomobject]@{
    PSTypeName = 'MyType'
    ID         = 6
    Name       = 'Bob'
}


PS> $o | Test-PowerShell

Key         Value
---         -----
InputObject MyType


PS> [pscustomobject]@{ID = 6} | Test-PowerShell

Key Value
--- -----
ID      6

下面的想法和實驗。

解決您的問題方法(定義您自己的類型):

Add-Type -TypeDefinition @'
public class MyType
{
    public int ID { get; set; }
    public string Name { get; set; }
}
'@

然后你將你的參數標記為[MyType] ,創建像[pscustomobject]那樣的對象:

[MyType]@{ ID = 6; Name = 'Bob' }

事后看來,這種方法不起作用。 您遇到的是DefaultParameterSet的行為。 我建議你改變你的管道輸入。 是否存在將ID作為管道輸入而不是僅使用Test-PowerShell -ID 5Test-PowerShell並被提示輸入ID的用戶的用例?

這是一個可能與我的測試有關的建議:

function Test-PowerShell {
    [CmdletBinding(DefaultParameterSetName = 'ID')]
    param(
        [Parameter(ParameterSetName = 'InputObject', Mandatory = $true, ValueFromPipeline = $true)]
        [PSTypeName('MyType')]
        $InputObject,

        [Parameter(ParameterSetName = 'ID', Mandatory = $true, ValueFromPipeline = $true)]
        [int]
        $ID
    )

    process {
        $PSBoundParameters
    }
}

要從現有的內置cmdlet中獲取示例,它們不會在對象上使用相同的名稱或屬性來表示多個參數。 Get-ChildItemLiteralPathPath接受管道輸入,但LiteralPath只接受PropertyName LiteralPathPSPath (別名)。 Path是ByValue和PropertyName,但僅作為Path

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM