如何断言参数绑定会成功而没有副作用?

时间:2017-09-15 16:19:39

标签: powershell dependency-injection assert parameterbinding

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

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,但在这种情况下这样做会产生副作用,直到首先完成其他一些长时间运行的事情才能发生这种副作用。

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

1 个答案:

答案 0 :(得分: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属性和动态参数可能会产生副作用。