繁体   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