如何为添加的 ScriptMethod 成员获取参数强制?
How do I get parameter enforcement to work with for added ScriptMethod members?
我有 $object 我想要内置函数。我似乎无法弄清楚如何对添加的函数的参数强制执行强制规则。
强制规则适用于与对象无关的标准函数,但是当我测试对象和 运行 函数时,我可以在没有所需的强制参数的情况下执行。
$object | Add-Member -Name ProcessFiles -MemberType ScriptMethod -Value {
param(
[Parameter(Mandatory=$true)]
[String[]]$FILES
)
这不会引发错误,它应该抱怨缺少参数。
$object.ProcessFiles()
有什么魔力?有没有人有自定义对象ScriptMethod参数验证的示例代码?
这很有趣。我可以确认您看到的行为(使用 PowerShell 5.0,但我想它在整个过程中都是一样的)。
我不能确切地说出发生这种情况的原因,但这一定与调用代码的方式有关。
通过执行 $object.ProcessFiles.Script.Ast.ParamBlock.Parameters.Attributes
你可以看到 Mandatory
参数被保留了,它只是看似被忽略了。
解决方法
一个简单的测试
如果您不需要强制参数的所有功能(也就是说,您不关心它是否提示输入值),您可以简单地测试 throw
:
$object | Add-Member -MemberType ScriptMethod -Name test -Value {
param(
[String[]]
$Files
)
if (!$Files) {
throw [System.ArgumentException]'-Files is required.'
}
}
更通用的东西
在对此进行调查时,我注意到 [ScriptBlock]
确实强制执行了属性,所以我想出了这个 hack:
$object | Add-Member -MemberType ScriptMethod -Name ProcessFiles -Value {
param(
[String[]]
$Files
)
& {
param(
[Parameter(Mandatory=$true)]
[String[]]
$Files
)
$Files
} @PSBoundParameters
}
这是在您的 ScriptMethod 中创建一个接受相同参数的脚本块,然后在调用它时将所有绑定参数作为参数传递给脚本块。
我还没有使用更复杂的参数声明对其进行测试,但它应该可以解决问题。
我认为这样做的主要缺点是您需要编写两次参数块。如果您在 Add-Member
调用之外创建脚本块,则有一种方法可以避免这种情况;您可以创建一个将脚本块作为参数的函数,然后使用 AST 解析它并以编程方式创建一个嵌入并执行原始脚本块的新脚本块。这可能有点矫枉过正;也许我会写一篇关于它的博客 post。
我有 $object 我想要内置函数。我似乎无法弄清楚如何对添加的函数的参数强制执行强制规则。
强制规则适用于与对象无关的标准函数,但是当我测试对象和 运行 函数时,我可以在没有所需的强制参数的情况下执行。
$object | Add-Member -Name ProcessFiles -MemberType ScriptMethod -Value {
param(
[Parameter(Mandatory=$true)]
[String[]]$FILES
)
这不会引发错误,它应该抱怨缺少参数。
$object.ProcessFiles()
有什么魔力?有没有人有自定义对象ScriptMethod参数验证的示例代码?
这很有趣。我可以确认您看到的行为(使用 PowerShell 5.0,但我想它在整个过程中都是一样的)。
我不能确切地说出发生这种情况的原因,但这一定与调用代码的方式有关。
通过执行 $object.ProcessFiles.Script.Ast.ParamBlock.Parameters.Attributes
你可以看到 Mandatory
参数被保留了,它只是看似被忽略了。
解决方法
一个简单的测试
如果您不需要强制参数的所有功能(也就是说,您不关心它是否提示输入值),您可以简单地测试 throw
:
$object | Add-Member -MemberType ScriptMethod -Name test -Value {
param(
[String[]]
$Files
)
if (!$Files) {
throw [System.ArgumentException]'-Files is required.'
}
}
更通用的东西
在对此进行调查时,我注意到 [ScriptBlock]
确实强制执行了属性,所以我想出了这个 hack:
$object | Add-Member -MemberType ScriptMethod -Name ProcessFiles -Value {
param(
[String[]]
$Files
)
& {
param(
[Parameter(Mandatory=$true)]
[String[]]
$Files
)
$Files
} @PSBoundParameters
}
这是在您的 ScriptMethod 中创建一个接受相同参数的脚本块,然后在调用它时将所有绑定参数作为参数传递给脚本块。
我还没有使用更复杂的参数声明对其进行测试,但它应该可以解决问题。
我认为这样做的主要缺点是您需要编写两次参数块。如果您在 Add-Member
调用之外创建脚本块,则有一种方法可以避免这种情况;您可以创建一个将脚本块作为参数的函数,然后使用 AST 解析它并以编程方式创建一个嵌入并执行原始脚本块的新脚本块。这可能有点矫枉过正;也许我会写一篇关于它的博客 post。