我正在实施Bart de Smet的解决方案,在此向Powershell添加扩展方法:
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系统集成......
或者我做错了吗?有什么方法可以让你想到这个吗?
答案 0 :(得分: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()
这更像是一个草图而不是实际的实现...我猜真正的代理函数会比一个简单的包装器好得多。