2012-06-14 22 views
3

用户cashfoley在codeplex上发布了一个看起来相当优雅的代码集合,称为PSClass的“模块”。名称查找在Powershell脚本块中如何工作?

当我点源psclass代码到我自己的一些代码,我能写这样的代码:

$Animal = New-PSClass Animal { 

    constructor { 
     param($name, $legs) 

     # ... 
    } 

    method -override ToString { 
     "A $($this.Class.ClassName) named $($this.name) with $($this.Legs) Legs" 
    } 
} 

当我试图然而,创建一个模块出的PSClass代码,我开始出现错误。 constructormethod名称不再被识别。

看看实际的实现,我看到的是constructor,method等实际上是嵌套在New-PSClass函数中的函数。

因此,在我看来,当我点播PSClass.ps1文件时,我的脚本块允许包含对嵌套在其他本地函数中的函数的引用。但是,当PSClass代码成为模块时,导出New-PSClass函数(我尝试使用清单并使用Export-ModuleMember),名称不再可见。

有人可以向我解释脚本块,范围规则和嵌套函数的可见性规则是如何协同工作的?

另外,有一种单独的,是否有一个更好的类纯定义协议纯Powershell脚本? (具体来说,不涉及“只是写在C#中,然后执行此操作......”)

+0

ps> get-help about_scopes |更多 – x0n

回答

0

脚本块中的变量在执行前不会被评估。如果在执行块时脚本块中的变量不存在于当前范围内,则变量将不具有任何值。脚本块不是闭包:它们在实例化时不捕获上下文。

Remove-variable FooBar 

function New-ScriptBlock 
{ 
    $FooBar = 1 

    $scriptBlock = { 
     Write-Host "FooBar: $FooBar" 
    } 

    $FooBar = 2 
    & $scriptBlock # Outputs FooBar: 2 because $FooBar was set to 2 before invocation 
    return $scriptBlock 
} 

function Invoke-ScriptBlock 
{ 
    param(
     $ScriptBlock 
    ) 

    & $ScriptBlock 
} 

$scriptBlock = New-ScriptBlock 

& $scriptBlock # Prints nothing since $FooBar doesn't exist in this scope 

$FooBar = 3 
Invoke-ScriptBlock $scriptBlock # Prints $FooBar: 3 since FooBar set to 3 
+0

如果这是真的,那么为什么将外部函数放在模块中不起作用? –