请看下面的代码:如何确定仅在当前管道步骤中绑定的参数?
function g
{
[CmdletBinding()]
param
(
[parameter(ValueFromPipelineByPropertyName = $true)]$x,
[parameter(ValueFromPipelineByPropertyName = $true)]$y,
[parameter(ValueFromPipelineByPropertyName = $true)]$z
)
process
{
$retval = @{[email protected]{};[email protected]{};x=$x;y=$y;z=$z}
$PSBoundParameters.Keys |
% { $retval.psbp.$_ = $PSBoundParameters.$_ }
$PSCmdlet.MyInvocation.BoundParameters.Keys |
% { $retval.mibp.$_ = $PSCmdlet.MyInvocation.BoundParameters.$_}
return New-Object psobject -Property $retval
}
}
$list = (New-Object psobject -Property @{x=1;z=3}),
(New-Object psobject -Property @{x=$null;y=2})
$list |
g |
Select bp,x,y,z |
ft -AutoSize
下面的输出运行脚本的结果:
psbp mibp x y z
---- ---- - - -
{z, x} {z, x} 1 3
{y, z, x} {y, z, x} 2
这似乎表明,这两个$PSBoundParameters
和$PSCmdlet.MyInvocation.BoundParameters
包含势必使所有参数的累积远。
我相当肯定$x
和$z
被束缚的第一步,和$x
和$y
被绑定在第二个步骤,但我还没有找到一种以编程方式检索细节。
如何确定在当前管道步骤中绑定的参数?
为什么我在乎这件事?某些类型的参数验证比使用诸如参数集ValidateScript()
等语言功能可以实现的要复杂得多。验证必须在函数体内执行。偶尔需要考虑一个未绑定的参数在语义上不同于将$null
传递给相同的参数。通常通过询问$PSBoundParameters
来实现绑定参数的检测。如果您只传递管道上的单个参数对象,这可以正常工作。但是,如果使用管道管道传输参数对象列表,则由于上述脚本显示的问题而导致该检测被阻止。这违反了最少原则的原则,因为当调用者碰巧通过将相同的对象管道到它来调用它时,在foreach
循环内工作正常的函数的行为显着不同。
我可以变通的作法是从foreach
中调用受影响的功能,但我宁愿解决问题的所有调用,而不是完全放弃流水线。
这是一个非常有趣的问题。你的最终目标是什么?也可以尝试使用'Trace-Command'并查看它是否可能揭示绑定过程的任何内容。 – briantist
@briantist我为这个问题添加了一个解释。 – alx9r