3

ユーザーcashfoleyは、PSClassと呼ばれる「モジュール」のコードプレックスにかなりエレガントなコードセットのように見えるものを投稿しました。

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#で記述してからこれを実行するだけです...」を含まないもの)

4

1 に答える 1

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
于 2012-06-14T14:30:33.967 に答える