在Piped对象上调用方法

问题描述 投票:1回答:2

最好有一个PS过滤器用于调用方法,如

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

使这样的东西成为可能:

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

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

Here是一个成员电话会议的样本,但我现在试图为我的案例构建这样的东西失败了。

powershell methods pipeline
2个回答
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)

0
投票

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

但是,该方法仅限于传递静态方法以传递管道对象,而PowerShell确实具有内置的灵活的每个管道输入处理命令:ForEach-Object cmdlet,其内置别名为%,你传递一个脚本块({ ... }),其中$_指的是手头的管道输入对象):

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

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

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

# Call the .ToUpper() method on each input string:
PS> 'foo', 'bar' | % ToUpper # short for: 'foo', 'bar' | % { $_.ToUpper() }
FOO
BAR

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


性能考虑:

写自PowerShell Core 6.2.0。

令人惊讶的是,操作语句 - 尽管不涉及脚本块 - 比等效的脚本块语法慢;例如,'foo', 'bar' | % ToUpper'foo', 'bar' | % { $_.ToUpper() }

到目前为止,定义过滤器函数是最快的,但是,如上所述,仅限于静态方法(如果您通过脚本块或使用.psobject.Methods反射的成员名称执行操作,速度优势将变为相反)。

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

filter ToUpper { $_.ToUpper() }
'foo', 'bar' | ToUpper  # much faster than: 'foo', 'bar' | % ToUpper
© www.soinside.com 2019 - 2024. All rights reserved.