あまりPowerShellのパラメータバインディングについての記事を見かけないので頭の整理も兼ねてまとめました。
この続編として、PowerShellのDelay-Bindingについてもまとめる予定です。
※最後にパラメータバインディングのプロセスを辿れるTrace-Commandについても触れました。
###パラメータバインディングとは
コマンド実行時にパラメータと引数を結びつける(バインドする)こと。
必須パラメータは揃っているか、引数の型は適切かなどを判断する。
###パイプラインにおけるパラメータバインディング
パイプを通じて渡されたオブジェクト(パイプラインオブジェクト)は、一定のルールで現在のコマンドのパラメータにバインドされる。
###パラメータバインディングの基本ルール
(1)
パイプラインからの入力を許可するがTrue。これはヘルプで確認可能。Trueには以 下の2種類がある。
- ByValue: パイプラインオブジェクトをバインド
- ByPropertyName: パイプラインオブジェクトのプロパティ名とパラメータ名が一致した場合のプロパティの値をバインド
いずれの場合も、引数となる値の型がパラメータが要求する型が同じかその型に変換可能な場合のみバインドされる
(2)
そのパラメータがコマンド内で使用されていない。
###パイプラインオブジェクトのパラメータバインディング
それでは次の場合、Add-Contentはどのようにパイプラインオブジェクトをバインディングするのでしょうか。
[Regex]::Match("03/01/2019","\d{4}")|Add-Content file.txt
それを確認する前に、まずRegex.Matchメソッドの戻り値(パイプラインの入力オブジェクト)とAdd-Contentのパラメータについて調べます。
###入力オブジェクトとパラメータ
###パラメータバインディングのプロセス
以上を踏まえて、改めて次のコマンドのパラメータバインディングがどのようになされて確認します。
[Regex]::Match("03/01/2019","\d{4}")|Add-Content file.txt
この場合のAdd-Contentのパラメータバインディング
- パラメータがあるかチェック
→なし - パラメータがない引数について、位置指定のパラメータの条件に合うかチェック
→位置0のパラメータは-Path、file.txtは型の条件を満たしているのでOK - 必須パラメータに引数がバインドされているかチェック
→-Valueに空きあり - パイプラインオブジェクトの型と-Valueの要求する型が一致/型変換が可能かチェック
→System.Text.RegularExpressions.Group.MatchとObject[]なので不可 - パイプラインオブジェクトのプロパティ名とパラメータ名が一致するかチェック
→パイプラインオブジェクト内にValueプロパティあり - パラメータ値の型と-Valueの型と-Valueの要求する型が一致/型変換が可能かチェック
→System.StringとObject[]なので可 - パイプラインオブジェクトがByPropertyValueで入力が可能な他のプロパティとバインドできるかチェック
→不可 - 必須パラメータがバインドできているかチェック
→OK
###おわりに
少し雑でしたが、以上になります。
###追記(Trace-Commandについて)
パラメータバインディングの詳細についてはTrace-Commandで知ることができます。
上の例の場合、次のコマンドを実行すると詳細を確認できます。
Trace-Command -PSHost -Name ParameterBinding `
-Expression {[Regex]::Match("03/01/2019","\d{4}")|
Add-Content file.txt}
結果を行単位で見ていくと次のようになります。
BIND NAMED cmd line args [Add-Content]
Add-Contentのパラメータと引数がバインド
→ないので無視
BIND POSITIONAL cmd line args [Add-Content]
BIND arg [file.txt] to parameter [Path]
Add-Contentにパラメータの記載がない場合、位置によって引数がバインド
→file.txtを-Pathにバインド
Binding collection parameter Path: argument type [String], parameter type [System.String[]], collection type Array, element type [System.String], no coerceElementType
Creating array with element type [System.String] and 1 elements
Argument type String is not IList, treating this as scalar
Adding scalar element of type String to array position 0
BIND arg [System.String[]] to param [Path] SUCCESSFUL
BIND arg [System.String[]] to param [Path] SUCCESSFUL
-Pathの引数の型と要求する型を確認
→一致しないが、引数をスカラーとして扱うことで変換が可能と判断してバインド
###中略###
MANDATORY PARAMETER CHECK on cmdlet [Add-Content]
Add-Contentの必須パラメータを確認
→-Valueは必須だが引数がないので先に進む
BIND PIPELINE object to parameters: [Add-Content]
PIPELINE object TYPE = [System.Text.RegularExpressions.Match]
RESTORING pipeline parameter's original values
パイプラインオブジェクトをAdd-Contentの引数にバインドし、オブジェクトの型を確認。そのうえで元の値に復元
Parameter [Value] PIPELINE INPUT ValueFromPipeline NO COERCION
パイプラインオブジェクトを-Valueの引数としてバインド
→型の不一致、返還も負荷のため次に進む
BIND arg [2019] to parameter [Value]
Binding collection parameter Value: argument type [Match],
parameter type [System.Object[]], collection type Array,
element type [System.Object], no coerceElementType
Creating array with element type [System.Object] and 1 elements
Argument type Match is not IList, treating this as scalar
Adding scalar element of type Match to array position 0
BIND arg [System.Object[]] to param [Value] SUCCESSFUL
パイプラインオブジェクトのValueプロパティの型と-Valueが要求する型を確認
→型は一致しないが変換が可能と判断しバインド
少々雑ですが、以上になります