型を検索する PowerShell 関数(親クラス→子クラス)
はじめに
ネット環境無しで PowerShell を弄っているとたまに起こるのが、「引数に何を渡せば良いのかわからない」問題です。
Get-Member
コマンドレットなどで各種メンバーの定義は確認できますが、引数の型が抽象的な型になっていて、具体的な型がわからない、という問題です。
例:System.DateTime
の ToString
メソッド
PS >[datetime]::Now.ToString.OverloadDefinitions
string ToString()
string ToString(string format)
string ToString(System.IFormatProvider provider)
string ToString(string format, System.IFormatProvider provider)
string IFormattable.ToString(string format, System.IFormatProvider formatProvider)
string IConvertible.ToString(System.IFormatProvider provider)
「System.IFormatProvider
って具体的に何……?」という問題です。
型名の先頭にI
が付いていることからインターフェイスということはわかりますが、これだけではその先に繋がりません。
Microsoft Docs を見られれば、派生が書いてあるのでそれでOKなのですが……。 IFormatProvider Interface (System) | Microsoft Docs
対策の方針
今使えるすべての型の中から、該当する型の子クラス(やや不正確な表現)を探索する。
System.AppDomain
を使えばロード済みアセンブリを取得できるので、さらにそのアセンブリ内の型を列挙すれば、使えるすべての型を取得できる。
Type.IsAssignableFrom(Type) Method (System) | Microsoft Docs を使えば、該当する型の子クラスかどうかも判定できる。
作成した関数
<# .SYNOPSIS Search type from loaded assemblies. ロード済みアセンブリー内から型を検索します。 .DESCRIPTION Search type by root type from Loaded assemblies. ロード済みアセンブリー内から、指定した型及びサブクラスを検索します。 .EXAMPLE [System.IFormatProvider] | Search-Type IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False IFormatProvider True True CultureInfo System.Object True True DateTimeFormatInfo System.Object True True NumberFormatInfo System.Object .INPUTS System.Type .OUTPUTS System.Type By default, return all public type in loaded assemblies. #> function Search-Type { [CmdletBinding()] [OutputType([type])] param ( [Parameter(ValueFromPipeline=$true)] [type]$RootType = [System.Object] , [SupportsWildcards()] [string]$Name , [SupportsWildcards()] [string]$Namespace , [SupportsWildcards()] [string]$FullName ) begin { # Declare foreach variables for IntelliSense. [System.Reflection.Assembly]$asm = [type]$t = $null } process { foreach ($asm in [System.AppDomain]::CurrentDomain.GetAssemblies()) { foreach ($t in $asm.GetTypes()) { # Public only. if (-not $t.IsPublic) { continue } if (-not $RootType.IsAssignableFrom($t)) { continue } # Name check. if (-not [string]::IsNullOrEmpty($Name) -and ($t.Name -notlike $Name) ) { continue } if (-not [string]::IsNullOrEmpty($Namespace) -and ($t.Namespace -notlike $Namespace) ) { continue } if (-not [string]::IsNullOrEmpty($FullName) -and ($t.FullName -notlike $FullName) ) { continue } Write-Output -InputObject $t } } } }
使用例1
前述のSystem.IFormatProvider
を探したい場合は以下のようにする。
PS> [System.IFormatProvider] | Search-Type IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False IFormatProvider True True CultureInfo System.Object True True DateTimeFormatInfo System.Object True True NumberFormatInfo System.Object
さらに以下のようにすれば、FullNameも分かるのであとはある程度何とかなる。
PS> [System.IFormatProvider] | Search-Type | Select-Object -ExpandProperty FullName System.IFormatProvider System.Globalization.CultureInfo System.Globalization.DateTimeFormatInfo System.Globalization.NumberFormatInfo
使用例2
どんなコレクションがあるんだっけ…?と発作的に調べてくなったら以下のようにする(ワイルドカード指定のサンプル)。
PS> [System.Collections.IEnumerable] | Search-Type -Namespace System.Collections* IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True CollectionBase System.Object True True DictionaryBase System.Object True True ReadOnlyCollectionBase System.Object True True Queue System.Object True True ArrayList System.Object True True BitArray System.Object True True Stack System.Object True True Hashtable System.Object True False ICollection True False IDictionary True False IEnumerable True False IList ...