powershell - 在内部从一个功能流水线到另一个功能
问题描述
我有一个模块,它具有以下两个功能,它们几乎相同:
<#
.SYNOPSIS
Retrieves a VApp from VCloud.
#>
Function Get-VApp
{
[CmdletBinding()]
[OutputType([System.Xml.XmlElement])]
Param(
[Parameter(Mandatory = $true)]
[System.Xml.XmlElement] $Session,
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string[]] $VAppName
)
Begin {
[System.Xml.XmlElement] $queryList = $Session.GetQueryList();
[System.Xml.XmlElement[]] $vAppRecords = $queryList.GetVAppsByRecords().VAppRecord;
}
Process {
ForEach ($VAN in $VAppName)
{
$vAppRecords |
Where-Object { $_.name -eq $VAN } |
ForEach-Object { $_.Get(); }
}
}
End
{
#
}
}
和
<#
.SYNOPSIS
Retrieves a VAppRecord from VCloud.
#>
Function Get-VAppRecord
{
[CmdletBinding()]
[OutputType([System.Xml.XmlElement])]
Param(
[Parameter(Mandatory = $true)]
[System.Xml.XmlElement] $Session,
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string[]] $VAppName
)
Begin {
[System.Xml.XmlElement] $queryList = $Session.GetQueryList();
[System.Xml.XmlElement[]] $vAppRecords = $queryList.GetVAppsByRecords().VAppRecord;
}
Process {
ForEach ($VAN in $VAppName)
{
$vAppRecords |
Where-Object { $_.name -eq $VAN } |
ForEach-Object { $_; }
}
}
End
{
#
}
}
本质上,Get-VApp 类似于 Get-VAppRecord,只是前者在返回的对象上调用 Get() 方法。这似乎很浪费。如果我不打扰管道,那将很容易:
Function Get-VApp
{
[CmdletBinding()]
[OutputType([System.Xml.XmlElement])]
Param(
[Parameter(Mandatory = $true)]
[System.Xml.XmlElement] $Session,
[Parameter(Mandatory = $true)]
[string[]] $VAppName
)
Get-VAppRecord $Session $VAppName |
ForEach-Object {
$_.Get();
}
}
但显然管道把事情搞砸了。为了提高效率,我不会多次调用 Begin 块中的代码,并且我想找到一种方法来“玩好”管道,而无需批量记录。
解决方案
该类SteppablePipeline
旨在包装启用管道的命令,而不会破坏它们的管道支持。
您甚至不需要知道如何设置它,ProxyCommand.Create()
将为它生成脚手架!
因此,让我们从创建一个代理函数开始Get-VAppRecord
:
$GetVAppRecordCommand = Get-Command Get-VAppRecord
$GetVAppRecordCommandMetadata = [System.Management.Automation.CommandMetadata]::new($GetVAppRecordCommand)
# returns the body of the new proxy functions
[System.Management.Automation.ProxyCommand]::Create($GetVAppRecordCommandMetadata)
...然后我们只需要在它的块中添加Get()
调用:process
function Get-VApp {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, Position=0)]
[System.Xml.XmlElement]
${Session},
[Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true)]
[string[]]
${VAppName})
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-VAppRecord', [System.Management.Automation.CommandTypes]::Function)
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline()
$steppablePipeline.Begin($MyInvocation.ExpectingInput) # Many examples use $PSCmdlet; however setting this ensures that $steppablePipeline.Process() returns the output of the inner function.
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_) |ForEach-Object {
# call Get() on the record
$_.Get()
}
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
}
推荐阅读
- google-cloud-sql - 100 万个并发数据库连接
- sql - 查询在一列中找到三个相同的实例,但在另一列中必须有三个不同的结果
- python - 如何使用 python 请求发布带有 base64 文件的 Json?
- swiftui - 允许 DragGesture 从 SwiftUI 中的按钮开始?
- nginx - 带有 pre_read SSL proxy_pass 和非 pre_read SLL proxy_pass 配置的 Nginx
- javascript - 使用 Neovis 库时,如何将 Vis.js 的方法传递给控制台?
- python - 获取 NER 结果后如何获取索引?
- javascript - ReactJS:React-Select 调用 api 并过滤结果
- javascript - 使用三元运算符有条件地渲染数组方法
- python - 从带有水平线的 .txt 文件中提取相交值