1

假设我有一个函数,其中注入了依赖项和一些参数,如下所示:

function Invoke-ACommandLaterOn
{
    param
    (
        # ...
        [string]   $CommandName,
        [object]   $PipelineParams,
        [object[]] $PositionalParams,
        [hashtable]$NamedParams
        # ...
    )

    Assert-ParameterBinding @PSBoundParameters
    # ...
    # Some complicated long-running call tree that eventually invokes 
    # something like
    # $PipelineParams | & $CommandName @PositionalParams @NamedParams
    # ...
}

我想立即断言参数绑定$CommandName成功。这就是Assert-ParameterBinding要做的事情。但是,我不确定如何实施Assert-ParameterBinding

当然,我可以尝试$CommandName立即调用,但在这种情况下,这样做会产生副作用,直到首先完成一堆其他长时间运行的事情才会发生。

如何在不调用函数的情况下断言与函数的参数绑定将成功?

4

1 回答 1

1

如果你做了这样的事情(在Assert-函数内部)怎么办:

$cmd = Get-Command $CommandName
$meta = [System.Management.Automation.CommandMetadata]::new($cmd)
$proxy = [System.Management.Automation.ProxyCommand]::Create($meta)

$code = $proxy -ireplace '(?sm)(?:begin|process|end)\s*\{.*','begin{}process{}end{}'

$sb = [scriptblock]::Create($code)

$PipeLineParams | & $sb @PositionalParams @NamedParams

我实际上不确定它是否适用于位置参数或从我的头顶喷出两个不同的集合(我没有做太多测试)。

解释

我有几个想法。一方面,参数绑定可能非常复杂。在管道调用的情况下,绑定会随着不同的块被命中而不同。

因此,让 PowerShell 处理这个问题可能是一个好主意,方法是基本上重新创建相同的函数,但使用一个什么都不做的主体。

所以我使用内置的方式来生成一个代理函数,因为它会处理所有这些杂乱的工作,然后粗暴地替换了主体,这样它实际上就不会调用原始函数。

理想情况下,您将在所有常规参数绑定过程之后进行调用,但最终什么也没做。

将其包装在try/catch或其他错误测试中应该是对这是否是成功调用的一个很好的测试。

这甚至可以处理动态参数。

可能在某些极端情况下这不起作用,但我认为它们很少见。

此外,ValidateScript属性和动态参数可能会产生副作用。

于 2017-09-15T20:45:35.113 回答