【问题标题】:Is it possible to use update-typedata with a generic type definition in Powershell?是否可以在 Powershell 中将 update-typedata 与泛型类型定义一起使用?
【发布时间】:2013-02-15 23:23:15
【问题描述】:

我在这里实现了 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 系统集成......

还是我做错了?您有什么办法可以让这项工作发挥作用吗?

【问题讨论】:

    标签: powershell powershell-3.0


    【解决方案1】:

    自定义类型扩展取决于$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()
    

    这更像是一个草图而不是实际实现......我想真正的代理函数会比一个简单的包装器要好得多。

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 2013-03-01
      相关资源
      最近更新 更多