【问题标题】:Powershell GetTypePowershell 获取类型
【发布时间】:2021-02-14 19:55:26
【问题描述】:

我想检查是否存在某种类型。例如:

Add-Type -TypeDefinition '
public class Test{
    public static int aaa(){
        return 1;
    }
}'

[test]::aaa() # 1

[type]::GetType('test') # empty

但 GetType() 不适用于我的“测试”类型。

【问题讨论】:

标签: .net powershell


【解决方案1】:

您可以测试该类型是否已经存在

if (-not ('Test' -as [type])) {
# or 
# if (-not ([System.Management.Automation.PSTypeName]'Test').Type) {
    Add-Type -TypeDefinition '
    public class Test{
        public static int aaa(){
            return 1;
        }
    }'
}

我不知道为什么[type]::GetType('test') 不起作用,但是

("Test" -as [type])

确实有效并返回 $null 或

IsPublic IsSerial Name                                     BaseType                                                                                                               
-------- -------- ----                                     --------                                                                                                               
True     False    Test                                     System.Object

【讨论】:

    【解决方案2】:

    补充Theo's helpful answer,这无疑显示了最佳解决方案(-as [Type]),为什么[Type]::GetType('Test')失败

    • System.Type.GetType() 仅查找从从磁盘加载或保存到磁盘的程序集的类型 - 即从预先存在的程序集加载的类型动态创建程序集的文件或类型还可以选择保存到磁盘

    • 相比之下,当您在 PowerShell 中动态定义类型时,它们是在动态的内存中程序集中创建的,这些程序集持久化到磁盘,所以@ 987654332@ 没有看到它们。请注意,这同样适用于:

      • 使用 Add-Type -TypeDefinition-MemberDefinition 创建的类型

      • 使用 (PSv5+) classenum 关键字创建的类型,即自定义 PowerShell 类和枚举。


    但是,[Type]::GetType() 提供了重载,可以将 自定义程序集解析器功能 挂钩到类型查找过程中,即一种在 additional 中查找程序集类型的方法地方。

    这大概是 PowerShell 在幕后使用来包含其在查找过程中的动态内存中程序集,它在以下上下文中发挥作用(大小写-不敏感,就像 PowerShell 通常那样):

    • 在最明显的形式中,在 type literals ([<typeName>]) 中,例如,您可以将 Test 类型称为 [Test] .

      • 因此,此类类型文字也适用于-istype(-inheritance) / interface test operator,因此您可以测试给定对象是否属于给定类型或从给定类型派生/实现给定接口类型。

      • 警告:如果[...] 中的类型名称未被识别为已加载或动态声明的类型,则会发生异常,并表现为语句终止错误 在 PowerShell 中。

    • -as 的上下文中,conditional type conversion operator,如 Theo 的答案 ('<typeName>' -as [type]) 所示,其中[type] 再次指代System.Type

      • 此方法测试字符串是否包含引用加载类型的类型名称,因此可以将其转换为类型-信息对象。
      • 如果是这样,则返回这样的类型信息对象(在您的示例中相当于[Test]);如果不是,则返回$null
      • 在诸如if 条件的布尔上下文中,返回的类型信息对象隐含为$true,其中$null 隐含为$false - 请参阅this answer 的底部以了解确切信息隐式到布尔转换的规则),因此-as [type] 方法是测试类型是否存在的最方便的方法。
    • 当您将类型名称字符串转换[type][type] 'Test'

      • -as 方法不同,此方法会触发异常,在PowerShell 中显示为语句终止错误
      • if ('Test' -as [type]) ... 的(更冗长但效率更低)等价物是
        if ($(try { [type] 'Test' } catch { $null })) ...

    关于命名空间的说明:

    • classenum 创建的类型有没有 命名空间组件,所以只用它们自己的名字来引用这些类型就足够了,比如@ 987654362@在手头的情况下。

    • 通过Add-Type创建的类型

      • 通过 -TypeDefinition(任意 C# 代码):

        • 是否需要命名空间限定符取决于是否将新类型的声明包含在 namespace <identifier> { ... } 构造中。
      • 通过 -MemberDefinition(用于声明静态方法的 C# 代码,通常用于 P/Invoke 调用):

        • 确实需要一个命名空间限定符来引用结果类型,即您通过-Namespace 参数显式指定的类型或隐式使用的Microsoft.PowerShell.Commands.AddType.AutoGeneratedTypes.WinApi 命名空间。 p>

        • 您可以通过使用-PassThru 开关并将类型定义对象保存在变量中来绕过必须通过命名空间限定名称引用类型,这样您就可以直接通过该变量调用其静态方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多