问题描述
这个自我回答的问题解决了以下情况:
-
可以使用参数级 {{3} } 属性还是
[ArgumentCompleter()]
cmdlet? -
如果是这样,这种方法的局限性是什么?
示例场景:
假设的 Get-Property
命令有一个 -Object
参数,它接受任何类型的对象,还有一个 -Property
参数,它接受要从对象中提取其值的属性的名称。
现在,在键入 Get-Property
调用的过程中,如果已经为 -Object
指定了值,则制表符补全 -Property
应循环遍历指定对象的名称(公共) 属性。
$obj = [pscustomobject] @{ foo = 1; bar = 2; baz = 3 }
Get-Property -Object $obj -Property # <- pressing <tab> here should cycle
# through 'foo','bar','baz'
解决方法
以下解决方案使用特定于参数的 [ArgumentCompleter()]
属性作为 Get-Property
函数本身定义的一部分,但该解决方案类似地适用于通过 {{1} } cmdlet。
限制:
-
PowerShell 调用的自定义完成脚本块 (
Register-CommandCompleter
) 从根本上只能看到通过参数指定的值,而不是通过管道。- 也就是说,如果您键入
{ ... }
,脚本块可以确定Get-Property -Object $obj -Property <tab>
的值将绑定到$obj
参数,但这不适用于-Object
(即使$obj | Get-Property -Property <tab>
被声明为管道绑定)。
- 也就是说,如果您键入
-
即使在通过参数指定的那些值中,也只有那些没有副作用可以被评估的值在脚本中实际上是可访问的堵塞;具体来说,这意味着:
-
文字值(例如,
-Object
-
简单变量引用(例如,
-Object ([pscustomobject] @{ foo = 1; bar = 2; baz = 3 })
)或property-access 或index-access 表达式(例如,{{ 1}} 或-Object $obj
) - 值得注意的是,以下值是不可访问的:
-
方法-调用结果(例如,
-Object $obj.Foo
) -
Command 输出(通过
-Object $obj[0]
、-Object $object.Foo()
或(...)
,例如$(...)
) - 此限制的原因是,在实际提交命令之前评估这些值可能会产生不良副作用和/或可能需要很长时间才能完成。
-
方法-调用结果(例如,
-
文字值(例如,
@(...)