首页 > 解决方案 > Powershell:强制或强制转换为字符串变量中命名的类型

问题描述

我正在尝试使用此处概述的方法来创建许多自定义数据类型,而不是为每个类型设置一行,我想定义一个名称和类型的哈希表,如下所示

$pxAccelerators = @{
   pxListObject = '[System.Collections.Generic.List[Object]]'
   pxListString = '[System.Collections.Generic.List[String]]'
   pxOrderedDictionary = '[System.Collections.Specialized.OrderedDictionary]'
}

然后我可以使用这样的东西

$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($key in $pxAccelerators.Keys) {
    $name = $key
    $type = $pxAccelerators.$key
    $typeAccelerators::Add($key,$type)
}

循环遍历哈希表并添加每一个。然而,问题当然是它$type不是一个实际的类型,它是一个字符串。并且$typeAccelerators::Add($key,$type)需要一个字符串和一个实际类型。所以基本上我需要将一个字符串强制为'[System.Collections.Specialized.OrderedDictionary]'实际类型。我发现了大量关于从一种数据类型转换或强制转换为另一种数据类型的参考,但我似乎找不到任何关于如何将字符串转换为由字符串定义的类型的参考。我在黑暗中尝试过所有这些刺

([System.Type]'[System.Collections.ArrayList]')::new()
[System.Type]'[System.Collections.ArrayList]'
[System.Type]'[System.Collections.ArrayList]' -as [System.Type]
'[System.Collections.ArrayList]' -as ([PowerShell].Assembly.GetType('[System.Collections.ArrayList]')

无济于事。 $type = ([PowerShell].Assembly.GetType('[System.Collections.ArrayList]'))似乎有效,因为它不会引发异常。但$type.GetType()确实抛出You cannot call a method on a null-valued expression.。有趣的是,自动完成[PowerShell].Assembly.GetType('[System.Collections.ArrayList]').显示属性如BaseTypeFullName可用,这表明我实际上已经生成了一个类型,但是.GetType()在结果上使用会引发异常。我试过了

$pxAccelerators = @{
   pxListObject = 'System.Collections.Generic.List[Object]'
   pxListString = 'System.Collections.Generic.List[String]'
   pxOrderedDictionary = 'System.Collections.Specialized.OrderedDictionary'
}
$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($key in $pxAccelerators.Keys) {
    $name = $key
    $type = [PowerShell].Assembly.GetType($pxAccelerators.$key)
    $typeAccelerators::Add($key,$type)
}

[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get

并且正在添加加速器,但要加速的类型不存在,这表明该GetType()行实际上并未产生类型。

最后,我发现似乎越来越近了。但是我似乎无法在没有从某种类型开始的情况下如何访问该方法,并且[System.Type].GetType('System.Int32')正在抛出,所以这似乎是一个死胡同。

我在尝试做一些不可能的事情吗?还是只是缺少适当的机制?

标签: powershelltypescastingtype-coercion

解决方案


-as [type]会做

运算符很乐意将-as类型名称作为右侧操作数。

将字典的值更改为只包含一个有效的类型名称,它变得很简单:

$pxAccelerators = @{
   pxListObject = 'System.Collections.Generic.List[Object]'
   pxListString = 'System.Collections.Generic.List[String]'
   pxOrderedDictionary = 'System.Collections.Specialized.OrderedDictionary'
}

$typeAccelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
foreach ($acc in $pxAccelerators.GetEnumerator()) {
    $name = $acc.Key
    $type = $acc.Value -as [type]
    $typeAccelerators::Add($name,$type)
}

结果:

PS ~> [pxOrderedDictionary] -is [type]
True
PS ~> [pxOrderedDictionary].FullName
System.Collections.Specialized.OrderedDictionary

推荐阅读