1

ここで、Powershell に拡張メソッドを追加するための Bart de Smet のソリューションを実装しています。

http://bartdesmet.net/blogs/bart/archive/2007/09/06/extension-methods-in-windows-powershell.aspx

それはうまくいきます!ほとんど!彼はジェネリックを除外していますが、それは暗黒時代 (2007 年) にさかのぼります。そのため、今日の Powershell 3.0 でそれが可能かどうかを調べようとしています。これが私がやろうとしていることの簡単な例です:

$ls = new-object collections.generic.list[string]

'generic'
update-typedata -force -typename collections.generic.list`1 `
    -membertype scriptmethod -membername test -value {'test!'}

$ls.test() # fail

'string'
update-typedata -force -typename collections.generic.list[string] `
    -membertype scriptmethod -membername test -value {'test!'}

$ls.test() # works!

これは以下を出力します:

generic
Method invocation failed because [System.Collections.Generic.List`1[[System.String, mscorlib, 
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]] doesn't contain a method 
named 'test'.
At C:\Temp\blah5.ps1:12 char:1
+ $ls.test()
+ ~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

string
test!

これで、Powershell はジェネリック型定義を操作できるようになりました。typedataシステムと統合されていないようです...

それとも私はそれを間違っていますか?これを機能させるために考えられる方法はありますか?

4

1 に答える 1

2

カスタム型拡張は依存し$object.PSTypeNamesます-そこに表示されるものはすべて、特定の拡張が型に適用されるかどうかを決定するときに PowerShell によって使用されます。

最初の例では、メソッドを「フック」して、おそらくどのオブジェクトの PSTypeNames にも表示されないタイプにします。

$ls.PSTypeNames
System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
System.Object 

明らかに、System.Object へのジェネリックで使用する必要があるメソッドをリンクすることは、やり過ぎです (控えめに言っても)。New-Object をラップし、PSTypeNames に何かを追加する特殊な関数を使用してジェネリックを作成することで、これを回避できます。

Update-TypeData -Force -TypeName System.Collections.Generic.List -Value {
    'Works!'
} -MemberName Test -MemberType ScriptMethod

function New-GenericObject {
param (
    [Parameter(Mandatory)]
    $TypeName
)
    $out = New-Object @PSBoundParameters
    $out.PSTypeNames.Insert(
        0,
        ($out.GetType().FullName -split '`')[0]
    )
    , $out
}

$ls = New-GenericObject -TypeName Collections.Generic.List[string]
$ls.Test()

これは、実際の実装というよりもスケッチです...実際のプロキシ関数は、単純なラッパーよりもはるかに優れていると思います。

于 2013-02-15T15:23:15.400 に答える