[原文作者]:Jared Parsons
[原文链接]:Simulating Closures in PowerShell
在之前的博文中我曾经提到过Power Shell缺少在脚本块中对闭包的支持.这对我正在研究的开发针对PowerShell的LINQ, 比如DSL, 是个很大的障碍。想象下下面的语句:
$a = from it in $source where {$it -gt 5 }
它大致相当于以下的C#代码
var a = from it in source where it > 5;
在C#中这段代码是能正常运行的,因为追根究底其中的WHERE语句“it > 5”被转化成了Lambda表达式。它要获取的变量在Lambda表达式中是通过闭包来实现的。为了在PowerShell中实现相似的功能,值$it在“where”句块执行的时候必须被转换。
所幸PowerShell的灵活性出乎意料的好。当一个脚本块执行的时候,它会通过遍历各个不同的域并尝试转换所有的变量。第一被搜索的域是脚本块,然后是脚本块执行所在的本地代码块。使用new-variable,我们能生成和脚本块所寻求的变量名相同的变量。
PS) $sb = { write-host $it }PS) & $sb
PS) new-variable "it" 42 -scope local
PS) & $sb
42
成功了!现在我们唯一要做的就是通过生成一个函数Run-Scriptblock来概括这种行为。这个函数涉及到以下两点:
1.需要执行的脚本块;
2.一系列名字/值对。每一对都代表执行脚本块所必需的一个变量。
代码:
#============================================================================
# Runs a script block. The $list parameter must be a list of string, value
# combinations. The script block will be executed with variables of the
# specified name and value in scope
#============================================================================
function Run-Scriptblock() {param ( [scriptblock] $sb = $(throw "Need a script block"),
[object[]]$list= $(throw "Please specify the list of names and values") )
for ( $i = 0; $i -lt $list.Length; $i = $i+2 ) {$name = [string]($list[$i])
$value = $list[$i+1]
new-variable -name $name -value $value -scope "local"
}
& $sb
}
Example Usage:
PS) $sb = { write-host $it }PS) run-scriptblock $sb "it",42
42
PS) $it
现在我们已经有执行一个“where”语句的方法了。下次我们将讨论如何在PowerShell中定一个LINQ DSL的实际操作。
打印 | 张贴于 2009-02-20 14:26:04 | Tag:暂无标签
留言反馈