【问题标题】:Resolving class name to type accelerator name将类名解析为类型加速器名称
【发布时间】:2020-11-20 03:00:08
【问题描述】:

我偶然发现了如何通过使用"$(...)" 始终如一地获取类的类型加速器名称(即短名称),例如:

PS H:\> "$([System.DirectoryServices.DirectorySearcher])"
adsisearcher
PS H:\> "$([adsisearcher])"
adsisearcher
PS H:\> "$([type]'System.DirectoryServices.DirectorySearcher')"
adsisearcher
PS H:\> "$([type]'adsisearcher')"
adsisearcher

或者如果你有一个类的实例:

PS H:\> "$(([System.DirectoryServices.DirectorySearcher]'').GetType())"
adsisearcher
PS H:\> "$(([adsisearcher]'').GetType())"
adsisearcher

但是查看该类的属性(例如[System.DirectoryServices.DirectorySearcher] | fl),我实际上在其中的任何地方都看不到“adsisearcher”。调用 ToString() 也无济于事,因为您获得了完整的类名:

PS H:\> [System.DirectoryServices.DirectorySearcher].ToString()
System.DirectoryServices.DirectorySearcher
PS H:\> [adsisearcher].ToString()
System.DirectoryServices.DirectorySearcher

谁能解释这个"$(...)"实际上是如何解析短名称的? “返回值”从何而来?

SO 上有许多其他答案解释了如何获取类型加速器的完整列表,但我找不到任何解释这种"$(...)" 行为的答案。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    这不是$() 操作,而是从[type][string] 的转换:

    PS H:\> [System.Int32] -as [string]
    int
    

    对于代码生成用例,类型名称转换也通过 LanguagePrimitives.ConvertTypeNameToPSTypeName() 静态方法公开,该方法根据可解析类型的名称生成有效的类型文字标记:

    PS H:\> [System.Management.Automation.LanguagePrimitives]::ConvertTypeNameToPSTypeName('System.Int32')
    [int]
    PS H:\> [System.Management.Automation.LanguagePrimitives]::ConvertTypeNameToPSTypeName('System.DirectoryServices.DirectorySearcher')
    [adsisearcher]
    

    但是查看该类的属性(例如[System.DirectoryServices.DirectorySearcher] | fl),我实际上在其中的任何地方都看不到“adsisearcher”。

    这是因为类型加速器是 PowerShell底层 (.NET) 类型系统之上施加的类型名称别名 - 目标类型本身对“类型加速器”是什么一无所知。

    内置类型加速器名称的真正“起源”是hardcoded lists of type mappings in PowerShell's language engine

    【讨论】:

    • 好的,这很有帮助,谢谢!一个后续,如果可以的话:为什么[System.Int32] -as [string](似乎产生与[string][System.Int32] 相同的结果)和[System.Int32].ToString() 之间存在差异? iow,调用什么方法来执行转换?
    • @fission [System.Management.Automation.LanguagePrimitives]::ConvertTo([System.Int32], [string])。换句话说,PowerShell 有自己的类型转换层,可以使参数绑定期间的类型强制和隐式格式化等工作顺利进行,而在转换为[string] 期间调用ToString() 只是一个回退跨度>
    • 啊,谢谢。这也是集合/数组(例如来自Get-ChildItem C:\,)在转换为字符串时被表示为名称的串联列表的原因。它似乎使用[System.Management.Automation.LanguagePrimitives]::ConvertTo($fsItems,[string])
    • 它更像$fsItems.ForEach({[LanguagePrimitives]::ConvertTo($_,[string])}) -join $(if($null -ne $OFS){$OFS}else{' '}),但是是的:)
    • 知道了……很好的解释,谢谢!我也会阅读TypeResolver.csLanguagePrimitives.cs 文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 2021-11-11
    • 2018-02-06
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    相关资源
    最近更新 更多