[英]PowerShell pipeline parameter binding order
我有一个高级函数,可以接受两种管道数据:
这是我的功能:
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 5
或Test-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-ChildItem
, LiteralPath
和Path
接受管道输入,但LiteralPath
只接受PropertyName LiteralPath
或PSPath
(别名)。 Path
是ByValue和PropertyName,但仅作为Path
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.