我一直在使用PowerShell AST为PSScriptAnalyzer创建一些自定义规则。
在AST的很多示例代码中,有一行我不明白。这是一个例子。
首先解析一个文件,在本例中是ISE中当前打开的文件。
$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::
ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$null)
到目前为止这是有道理的。假设我们想要查找所有ParameterAst对象。我见过这样做的代码如下。
$params = $AbstractSyntaxTree.FindAll({$args[0] -is [System.Management.Automation.Language.ParameterAst]}, $true)
这行代码调用FindAll
并传入一个脚本块,它似乎充当过滤器,因此只返回ParameterAst对象。
我在这里不明白的是$args[0]
如何适应这个电话。在调用FindAll
方法时,如何将任何参数实际传递到scriptblock中?
答案 0 :(得分:2)
FindAll
方法具有以下签名(来自msdn):
public IEnumerable<Ast> FindAll (
Func<Ast,bool> predicate,
bool searchNestedScriptBlocks
)
因此,第一个参数是一个以Ast作为输入的委托,并返回bool。 在Powershell中,您可以创建这样的委托:
$delegate = { param($ast) $ast -is [System.Management.Automation.Language.ParameterAst] }
或者没有声明参数:
$delegate = { $args[0] -is [System.Management.Automation.Language.ParameterAst] }
FindAll
方法将执行类似的操作(伪代码):
foreach ($node in $allNodes) {
$shouldAdd = & $delegate $node <-- this is how $node gets passed to your delegate
if ($shouldAdd) {
<add the node to the output list>
}
}
答案 1 :(得分:1)
将scriptblock视为匿名回调函数。
使用Where-Object { $someCondition }
时会发生同样的事情。
.FindAll
找到所有(事物),并为每个人调用你提供的功能。它显然期望得到[bool]
结果,并返回满足回调中存在条件的对象。
在powershell中的函数或脚本或脚本块中,您可以使用明确定义的命名参数,也可以reference parameters without declaring them using the $args
array,这是这里发生的事情。
使用scriptblock作为回调类似于将其用于事件:
$参数数量
Contains an array of the undeclared parameters and/or parameter values that are passed to a function, script, or script block. When you create a function, you can declare the parameters by using the param keyword or by adding a comma-separated list of parameters in parentheses after the function name. In an event action, the $Args variable contains objects that represent the event arguments of the event that is being processed.