管道对象上的调用方法

时间:2019-04-19 10:29:18

标签: powershell methods pipeline

最好使用PS过滤器来调用诸如

之类的方法

[System.Text.Encoding]::UTF8.GetString

使之成为可能:

filter Invoke-Method { ... ?? ... }

Invoke-WebRequest $url `
    | Select-Object Content `
    | Invoke-Method [System.Text.Encoding]::UTF8.GetString

Here是成员调用的示例,但是我为我的案例构造类似内容的尝试此刻失败了。

2 个答案:

答案 0 :(得分:2)

提供正确输入的输入对象,是的:

filter Invoke-Method {
  param(
    [System.Management.Automation.PSMethod]
    $Method
  )

  return $Method.Invoke($_)
}

(65..74 -as [byte[]]) |Invoke-Method -Method ([System.Text.Encoding]::UTF8.GetString)

答案 1 :(得分:0)

Mathias R. Jessen's helpful answer为您提出的问题提供了一种优雅的解决方案。

但是,方法仅限于将 static 方法传递给手边的管道对象,而 PowerShell确实具有 -in 灵活的按管道输入的处理命令ForEach-Object cmdlet,其内置别名为%,您向其传递了脚本块({{1 }}),其中{ ... }指的是当前的管道输入对象):

$_

请注意,为了将表示UTF8编码文本的字节数组转换回字符串,您必须通过管道将它作为整体发送,这就是一元数组构造运算符{ {1}}在这里实现(它将字节数组包装到一个辅助数组中,该辅助数组在管道中进行枚举时,将字节数组作为一个整体发送)。

如果调用的方法是每个管道输入对象的成员,则在语法上,事情变得更加容易,在这种情况下,您可以使用操作声明 (PSv3 +):

PS> , [byte[]] (0x68, 0xc3, 0xaf) | % { [Text.Encoding]::UTF8.GetString($_) }
hï

有关详细信息,请参见this answer


性能注意事项

自PowerShell Core 6.2.0起编写。

令人惊讶的是,尽管没有涉及脚本块,但操作语句比等效的脚本块语法 ; 例如,# Call the .ToUpper() method on each input string: PS> 'foo', 'bar' | % ToUpper # short for: 'foo', 'bar' | % { $_.ToUpper() } FOO BAR

定义过滤器功能是迄今为止最快的,但如上所述,仅限于静态方法(如果您通过脚本传递了要执行的操作,则速度优势将变得相反。 或按成员 name 通过'foo', 'bar' | % ToUpper使用 reflection 进行屏蔽。

但是,如果性能是最重要的,并且确实需要在每个输入对象上调用一个方法,则可以使用硬编码方法调用来定义过滤器函数:

'foo', 'bar' | % { $_.ToUpper() }