我想检查是否存在某种类型。例如:
Add-Type -TypeDefinition '
public class Test{
public static int aaa(){
return 1;
}
}'
[test]::aaa() # 1
[type]::GetType('test') # empty
但是GetType()不适用于我的“测试”类型。
为了补充Theo有用的答案,它无疑显示了最佳解决方案(-as[Type]
),以及为什么[Type]::GetType('Test')
失败:
>
System.Type.GetType()
仅从从磁盘加载或保存到磁盘的程序集中查找类型-也就是说,从预先存在的程序集文件加载的类型或动态创建的程序集中的类型也可以选择持久化到磁盘。
相比之下,当您在PowerShell中动态定义类型时,它们是在动态的、内存中的程序集中创建的,不会保存到磁盘上,因此< code>[Type]::GetType()看不到它们。请注意,这同样适用于:
>
使用Add-Type
-Type定义
或-Member定义
创建的类型
使用(PSv5)<代码>类
但是,[Type]::GetType()
提供了重载,这些重载允许将自定义程序集解析程序功能挂钩到类型查找过程中,即一种在其他位置查找程序集中的类型的方法。
这大概是PowerShell在后台使用的方法,用于在查找过程中包含其动态的仅在内存中的程序集,它在以下上下文中发挥作用(不区分大小写,因为PowerShell通常是这样的):
> 在最明显的形式中,在文字类型(< code>[
>
因此,此类类型文字也可以与<code>-is</code>,即类型(-继承)/接口测试运算符一起使用,因此您可以测试给定对象是否属于给定类型或从给定类型派生/实现给定接口类型。
警告:如果< code>[...]未被识别为加载或动态声明的类型,则会发生异常,这在PowerShell中表现为语句终止错误。
在-as
的上下文中,条件类型转换运算符,如Theo的回答()所示
此方法测试字符串是否包含引用已加载类型的类型名称,因此可以将其转换为类型信息对象。
- 如果是这样,则返回这样的类型信息对象(在您的示例中相当于
[Test]
),否则,将返回$null
- 在布尔上下文(如
if
conditional)中,返回的类型信息对象是隐式$true
,其中$null
隐式$false
- 有关隐式到布尔转换的确切规则,请参阅此答案的底部部分),因此 -as [type]
方法是测试类型是否存在的最便捷方法。
将类型名称字符串转换为
[类型]
:[类型] “测试”
与-as
方法不同,此方法会触发异常,该异常在PowerShell中显示为语句终止错误。
if('Test'-as[type])的等价物(更详细且效率更低)…
是
if($(try{[type]'Test'}catch{$null}))…
关于名称空间注意事项:
> < li>
使用< code>class
和< code>enum创建的类型没有命名空间组件,因此只通过它们自己的名称来引用类型就足够了,例如本例中的< code>[Test]。
通过添加类型创建的类型
:
>
通过 -类型定义
(任意 C# 代码):
命名空间中
通过
-MemberDefinition
(用于声明静态方法的C#代码,通常用于P/Invoke调用):
>
你确实需要一个命名空间限定符来引用生成的类型,即你通过
-Namespace
参数显式指定的类型,或者隐式使用的 Microsoft.PowerShell.命令.AddType.自动生成类型.WinApi
命名空间。
通过使用< code>-PassThru
开关并将类型定义对象保存在一个变量中,您可以绕过必须通过命名空间限定的名称来引用类型,这允许您通过该变量直接调用其静态方法。
您可以使用测试该类型是否已经存在
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