about_Enum
简短说明
语句 enum
声明枚举。 枚举是一种非重复类型,它由一组名为枚举器列表的命名标签组成。
长说明
语句 enum
允许创建一组强类型标签。 可以在代码中使用该枚举,而无需分析或检查拼写错误。
枚举在内部表示为整数值类型,起始值为零。 默认情况下,PowerShell 枚举使用 System.Int32 ([int]
) 作为基础类型。 默认情况下,PowerShell 为列表中的第一个标签分配值零。 默认情况下,PowerShell 使用连续整数分配剩余的标签。
在定义中,可以为标签提供任何整数值。 未分配值的标签采用下一个整数值。
语法
枚举使用以下语法:
整数枚举定义语法
[[<attribute>]...] enum <enum-name> {
<label> [= <int-value>]
...
}
特定基础类型枚举定义语法
[[<attribute>]...] enum <enum-name> : <underlying-type-name> {
<label> [= <int-value>]
...
}
标志枚举定义语法
[[<attribute>]...] [Flag()] enum <enum-name>[ : <underlying-type-name>] {
<label 0> [= 1]
<label 1> [= 2]
<label 2> [= 4]
<label 3> [= 8]
...
...
}
枚举访问语法
[<enum-name>]::<label>
示例
示例 1 - 最小枚举
以下代码块定义了带有三个标签的 MarkdownUnorderedListCharacter 枚举。 它不会向任何标签分配显式值。
enum MarkdownUnorderedListCharacter {
Asterisk
Dash
Plus
}
下一个代码块显示当强制转换为枚举类型时整数值和字符串值的行为方式。
$ValuesToConvert = @(0, 'Asterisk', 1, 'Dash', 2, 'Plus')
foreach ($Value in $ValuesToConvert) {
[MarkdownUnorderedListCharacter]$EnumValue = $Value
[pscustomobject]@{
AssignedValue = $Value
Enumeration = $EnumValue
AreEqual = $Value -eq $EnumValue
}
}
AssignedValue Enumeration AreEqual
------------- ----------- --------
0 Asterisk True
Asterisk Asterisk True
1 Dash True
Dash Dash True
2 Plus True
Plus Plus True
强制转换等于枚举值的整数将返回该枚举。 与枚举的标签相同的强制转换字符串将返回该枚举。
示例 2 - 显式和同义词枚举值
下面的示例演示与媒体文件关联的 对象的枚举。 定义将显式值分配给 、、 picture
video
的基础值music
。 紧跟在显式赋值之后的标签将获取下一个整数值。 可以通过将相同的值分配给另一个标签来创建同义词;请参阅的构造值:ogg
、oga
、mogg
、 或 jpg
、jpeg
、 或 mpg
。 mpeg
enum MediaTypes {
unknown
music = 10
mp3
aac
ogg = 15
oga = 15
mogg = 15
picture = 20
jpg
jpeg = 21
png
video = 40
mpg
mpeg = 41
avi
m4v
}
方法 GetEnumNames()
返回 枚举的标签列表。
[MediaTypes].GetEnumNames()
unknown
music
mp3
aac
ogg
oga
mogg
picture
jpg
jpeg
png
video
mpg
mpeg
avi
m4v
方法 GetEnumValues()
返回 枚举的值列表。
[MediaTypes].GetEnumValues()
unknown
music
mp3
aac
ogg
ogg
ogg
picture
jpg
jpg
png
video
mpg
mpg
avi
m4v
注意
GetEnumNames()
和 GetEnumValues()
似乎返回相同的结果;命名值的列表。 但是,在内部枚举 GetEnumValues()
值,然后将值映射到名称中。 仔细阅读列表,你会注意到 ogg
、 oga
和 mogg
显示在 的 GetEnumNames()
输出中,但 的 GetEnumValues()
输出仅显示 ogg
。 、jpeg
、 和 mpg
会发生mpeg
同样的情况jpg
。 PowerShell 为同义词值返回的名称不是确定性的。
可以使用 GetEnumName()
方法获取与特定值关联的名称。 如果有多个与值关联的名称,该方法将返回第一个定义的名称。
[MediaTypes].GetEnumName(15)
ogg
以下示例演示如何将每个名称映射到其值。
[MediaTypes].GetEnumNames() | ForEach-Object {
[pscustomobject]@{
Name = $_
Value = [int]([MediaTypes]::$_)
}
}
Name Value
---- -----
unknown 0
music 10
mp3 11
aac 12
ogg 15
oga 15
mogg 15
picture 20
jpg 21
jpeg 21
png 22
video 40
mpg 41
mpeg 41
avi 42
m4v 43
可以使用语法 [<enum-name>]::<label>
指定单个枚举值的标签。
[MediaTypes]::png
[MediaTypes]::png -eq 22
png
True
示例 3 - 枚举作为标志
以下代码块将 FileAttributes 枚举创建为一组位标志。 每个标签的值是前一个标签值的两倍。
[Flags()] enum FileAttributes {
Archive = 1
Compressed = 2
Device = 4
Directory = 8
Encrypted = 16
Hidden = 32
}
[FileAttributes]$file1 = [FileAttributes]::Archive
[FileAttributes]$file1 += [FileAttributes]::Compressed
[FileAttributes]$file1 += [FileAttributes]::Device
"file1 attributes are: $file1"
[FileAttributes]$file2 = [FileAttributes]28 ## => 16 + 8 + 4
"file2 attributes are: $file2"
file1 attributes are: Archive, Compressed, Device
file2 attributes are: Device, Directory, Encrypted
若要测试是否设置了特定标志,可以使用二进制比较运算符 -band
。 此示例测试 值$file2
中的 Device 和 Archive 属性。
PS > ($file2 -band [FileAttributes]::Device) -eq [FileAttributes]::Device
True
PS > ($file2 -band [FileAttributes]::Archive) -eq [FileAttributes]::Archive
False
还可以使用 HasFlag()
方法测试是否设置了特定标志。
此示例测试 的值$file1
中的 Device 和 Hidden 属性。
PS > $file1.HasFlag([FileAttributes]::Device)
True
PS > $file1.HasFlag([FileAttributes]::Hidden)
False
示例 4 - 作为参数的枚举
在以下示例中, 函数ConvertTo-LineEndingRegex
定义了类型为 EndOfLine 的 InputObject 参数。
enum EndOfLine {
CR = 1
LF = 2
CRLF = 3
}
function ConvertTo-LineEndingRegex {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline)]
[EndOfLine[]]$InputObject
)
process {
switch ($InputObject) {
CR { '\r' }
LF { '\n' }
CRLF { '\r\n' }
}
}
}
[EndOfLine]::CR | ConvertTo-LineEndingRegex
'CRLF' | ConvertTo-LineEndingRegex
ConvertTo-LineEndingRegex 2
\r
\r\n
\n
在此示例中,调用 ConvertTo-LineEndingRegex
的第一个语句传递 的 CR
枚举值。 第二个语句传递字符串 ,该字符串 'CRLF'
将强制转换为 LineEnding。 第三个语句指定参数的值 2
,该值映射到 LF
标签。
可以通过在 PowerShell 提示符中键入以下文本来查看参数完成选项:
ConvertTo-LineEndingRegex -InputObject <Tab>
为参数指定无效的标签名称或数值时,函数将引发错误。
ConvertTo-LineEndingRegex -InputObject 0
ConvertTo-LineEndingRegex: Cannot process argument transformation on
parameter 'InputObject'. Cannot convert value "0" to type "EndOfLine" due
to enumeration values that are not valid. Specify one of the following
enumeration values and try again. The possible enumeration values are
"CR,LF,CRLF".
示例 5 - 具有特定基础类型的枚举
从 PowerShell 6.2 开始,可以使用特定的基础类型定义枚举。 此示例显示枚举的有效基础类型。
第一个代码块将两个变量初始化为数组。 $EnumTypes
是一个空数组,用于保存动态创建的类型。 $IntegralTypes
是包含枚举的有效基础类型的数组。
$EnumTypes = @()
$IntegralTypes = @(
'byte', 'sbyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong'
)
下一个代码块定义用于动态创建枚举定义的模板。 将 {0}
格式占位符替换为整型类型名称时,模板将创建一个脚本块,该脚本块可:
定义名为 的
<type>Enum
枚举,如byteEnum
。 定义的枚举使用指定的整型类型作为基础值类型。枚举的定义是将
Min
值设置为整型类型的最小值。 它定义Max
设置为整型类型的最大值的值。返回新定义的类型。
$DefinitionTemplate = @"
enum {0}Enum : {0} {{
Min = [{0}]::MinValue
Max = [{0}]::MaxValue
}}
[{0}Enum]
"@
下一个代码块使用模板在当前范围内创建和调用 scriptblock。 它将返回的类型定义添加到 数组中 $EnumTypes
。
foreach ($IntegralType in $IntegralTypes) {
$Definition = $DefinitionTemplate -f $IntegralType
$ScriptBlock = [scriptblock]::Create($Definition)
$EnumTypes += . $ScriptBlock
}
最后一个代码块循环访问枚举类型,使用 GetEnumValuesAsUnderlyingType()
方法将值列为基础类型。 循环为每个值创建一个新的 对象,显示枚举类型、值类型、标签和实际值。
foreach ($EnumType in $EnumTypes) {
$EnumType.GetEnumValuesAsUnderlyingType() | ForEach-Object {
[pscustomobject]@{
EnumType = $EnumType.FullName
ValueType = $_.GetType().FullName
Label = $EnumType.GetEnumName($_)
Value = $_
}
}
}
EnumType ValueType Label Value
-------- --------- ----- -----
byteEnum System.Byte Min 0
byteEnum System.Byte Max 255
sbyteEnum System.SByte Max 127
sbyteEnum System.SByte Min -128
shortEnum System.Int16 Max 32767
shortEnum System.Int16 Min -32768
ushortEnum System.UInt16 Min 0
ushortEnum System.UInt16 Max 65535
intEnum System.Int32 Max 2147483647
intEnum System.Int32 Min -2147483648
uintEnum System.UInt32 Min 0
uintEnum System.UInt32 Max 4294967295
longEnum System.Int64 Max 9223372036854775807
longEnum System.Int64 Min -9223372036854775808
ulongEnum System.UInt64 Min 0
ulongEnum System.UInt64 Max 18446744073709551615
枚举方法
以下列表包括可用于 PowerShell 中的枚举的有用方法以及如何使用它们。
格式
静态 Format()
方法返回给定枚举类型、枚举值和格式字符串的格式化字符串输出。 输出与对具有指定格式字符串的值调用 ToString 方法相同。
可以对 System.Enum 基类类型或特定枚举类型使用静态方法。
[System.Enum]::format([<enum-name>], <value>, <format-string>)
[<enum-name>]::format([<enum-name>], <value>, <format-string>)
有效的格式字符串是 G
或 g
、 X
d
x
D
和 F
或 。f
有关详细信息,请参阅 枚举格式字符串。
以下示例使用每个受支持的枚举格式字符串将 TaskState 枚举的每个值转换为其字符串表示形式。
enum TaskState {
ToDo
Doing
Done
}
# String format template for the statements
$Statement = "[System.Enum]::Format([TaskState], {0}, '{1}')"
foreach ($Format in @('G', 'D', 'X', 'F')) {
$StatementToDo = $Statement -f 0, $Format
$StatementDoing = $Statement -f "([TaskState]'Doing')", $Format
$StatementDone = $Statement -f '[TaskState]::Done', $Format
$FormattedToDo = [System.Enum]::Format(
[TaskState], 0, $Format
)
$FormattedDoing = [System.Enum]::Format(
[TaskState], ([TaskState]'Doing'), $Format
)
$FormattedDone = [System.Enum]::Format(
[TaskState], [TaskState]::Done, $Format
)
"{0,-62} => {1}" -f $StatementToDo, $FormattedToDo
"{0,-62} => {1}" -f $StatementDoing, $FormattedDoing
"{0,-62} => {1}" -f $StatementDone, $FormattedDone
}
[System.Enum]::Format([TaskState], 0, 'G') => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'G') => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'G') => Done
[System.Enum]::Format([TaskState], 0, 'D') => 0
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'D') => 1
[System.Enum]::Format([TaskState], [TaskState]::Done, 'D') => 2
[System.Enum]::Format([TaskState], 0, 'X') => 00000000
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'X') => 00000001
[System.Enum]::Format([TaskState], [TaskState]::Done, 'X') => 00000002
[System.Enum]::Format([TaskState], 0, 'F') => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'F') => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'F') => Done
GetEnumName
反射 GetEnumName()
方法返回特定枚举值的名称。 输入值必须是枚举的有效基础类型,如整数或枚举值。 如果有多个与值关联的名称,该方法将返回第一个定义的名称。
[<enum-name>].GetEnumName(<value>)
enum GateState {
Unknown
Open
Opening
Closing
Closed
}
foreach ($Value in 0..4) {
[pscustomobject]@{
IntegerValue = $Value
EnumName = [GateState].GetEnumName($Value)
}
}
IntegerValue EnumName
------------ --------
0 Unknown
1 Open
2 Opening
3 Closing
4 Closed
GetEnumNames
反射 GetEnumNames()
方法将每个枚举值的名称作为字符串返回。 输出包含同义词。
[<enum-name>].GetEnumNames()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumNames()
Unknown
Spring
Summer
Fall
Autumn
Winter
GetEnumUnderlyingType
反射 GetEnumUnderlyingType()
方法返回枚举值的基础类型。
[<enum-name>].GetEnumUnderlyingType()
enum IntBasedEnum {
Zero
One
Two
}
enum ShortBasedEnum : short {
Zero
One
Two
}
foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
[pscustomobject]@{
EnumType = $EnumType
ValueType = $EnumType.GetEnumUnderlyingType()
}
}
EnumType ValueType
-------- ---------
IntBasedEnum System.Int32
ShortBasedEnum System.Int16
GetEnumValues
反射 GetEnumValues()
方法返回枚举的每个已定义值。
[<enum-name>].GetEnumValues()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumValues()
Unknown
Spring
Summer
Fall
Fall
Winter
GetEnumValuesAsUnderlyingType
反射 GetEnumValuesAsUnderlyingType()
方法将枚举的每个定义值作为基础类型返回。
[<enum-name>].GetEnumValuesAsUnderlyingType()
enum IntBasedEnum {
Zero
One
Two
}
enum ShortBasedEnum : short {
Zero
One
Two
}
foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
[pscustomobject]@{
EnumType = $EnumType
ValueType = $EnumType.GetEnumValuesAsUnderlyingType()[0].GetType()
}
}
EnumType ValueType
-------- ---------
IntBasedEnum System.Int32
ShortBasedEnum System.Int16
HasFlag
实例 HasFlag
方法确定是否为标志枚举值设置位标志。 与执行二进制比较和等效性检查相比,使用此方法更短且更易于阅读。
<enum-value>.HasFlag(<enum-flag-value>)
以下示例定义 ModuleFeatures 标志枚举,并显示值 39
具有哪些标志。
[Flags()] enum ModuleFeatures {
Commands = 1
Classes = 2
Enums = 4
Types = 8
Formats = 16
Variables = 32
}
$Features = [ModuleFeatures]39
foreach ($Feature in [ModuleFeatures].GetEnumValues()) {
"Has flag {0,-12}: {1}" -f "'$Feature'", ($Features.HasFlag($Feature))
}
Has flag 'Commands' : True
Has flag 'Classes' : True
Has flag 'Enums' : True
Has flag 'Types' : False
Has flag 'Formats' : False
Has flag 'Variables' : True
IsDefined
如果为 枚举定义了输入值,则 IsDefined()
静态方法返回 $true
;否则 $false
返回 。 使用此方法可检查值是否对枚举有效,而无需处理无效参数错误。
可以对 System.Enum 基类类型或特定枚举类型使用静态方法。
[System.Enum]::IsDefined([<enum-name>], <value>)
[<enum-name>]::IsDefined([<enum-name>], <value>)
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
foreach ($Value in 0..5) {
$IsValid = [Season]::IsDefined([Season], $Value)
$EnumValue = if ($IsValid) { [Season]$Value }
[pscustomobject] @{
InputValue = $Value
IsValid = $IsValid
EnumValue = $EnumValue
}
}
InputValue IsValid EnumValue
---------- ------- ---------
0 True Unknown
1 True Spring
2 True Summer
3 True Fall
4 True Winter
5 False
ToString
实例 ToString()
方法返回枚举值的标签。
此方法也是枚举值如何显示为输出的默认视图。 (可选)可以指定格式字符串来控制值显示方式。 有关格式设置的详细信息,请参阅 设置枚举值的格式。
注意
对于为特定值定义同义词的枚举,不要编写依赖于 输出的代码 ToString()
。 方法可以返回值的任何有效名称。
<enum-value>.ToString([<format-string>])
以下示例将 Shade 枚举 Gray
定义为 的 Grey
同义词。 然后,它输出对象,这些对象显示实际枚举值,枚举显示为字符串,枚举显示为整数。
enum Shade {
White
Grey
Gray = 1
Black
}
[Shade].GetEnumValues() | Foreach-Object -Process {
[pscustomobject]@{
EnumValue = $_
StringValue = $_.ToString()
IntegerValue = [int]$_
}
}
numValue StringValue IntegerValue
--------- ----------- ------------
White White 0
Grey Grey 1
Grey Grey 1
Black Black 2
枚举值同义词
可以定义为同一整数值提供不同名称的枚举。 执行此操作时,指向相同基础值的名称称为 同义词。 具有同义词的枚举使用户能够为同一值指定不同的名称。
使用同义词定义枚举时,不要编写依赖于转换为特定名称的同义词值的代码。 可以可靠地编写将同义词字符串转换为枚举值的代码。 使用枚举值本身时,始终将其作为枚举值或其基础类型而不是字符串进行比较。
以下代码块使用 Grey
和 Gray
作为同义词定义 Shade 枚举。
enum Shade {
White
Grey
Gray = 1
Black
}
[Shade]'Grey' -eq [Shade]::Gray
[Shade]::Grey -eq 1
[Shade]'Gray' -eq 1
True
True
True
枚举作为标志
枚举的一个常见用途是表示一组互斥值。 例如, ArrivalStatus 实例的值可以是 Early、OnTime 或 Late。 一个 ArrivalStatus 实例的值反映多个枚举常量是没有意义的。
但是,在其他情况下,枚举对象的值可以包含多个枚举成员,并且每个成员表示枚举值中的一个位字段。 可以使用 FlagsAttribute 指示枚举由位字段组成,作为用户可以组合的标志。
要使作为标志的枚举正常工作,必须将每个标签的整数值设置为 2 的幂。 如果未为标签指定值,PowerShell 会将该值设置为比上一个标签高一个值。
可以定义常用标志组合的值,使用户能够更轻松地同时指定一组标志。 值的名称应为标志的组合名称。 整数值应为标志值之和。
若要确定是否为值设置了特定标志,请对值使用 HasFlag()
方法或使用二进制比较运算符 -band
。
有关演示如何使用标志枚举和检查是否设置标志的示例,请参阅示例 3。
枚举作为参数
可以定义使用枚举作为其类型的 cmdlet 参数。 将枚举指定为参数的类型时,用户会自动完成该参数的值并验证该参数的值。 参数完成建议枚举的有效标签列表。
当参数具有枚举作为其类型时,可以指定以下任一项:
- 枚举,例如
[<EnumType>]::<Label>
- 字符串格式的枚举标签
- 枚举的数值
有关显示枚举类型参数行为的示例,请参阅 示例 4。
具有特定基础类型的枚举
从 PowerShell 6.2 开始,可以使用特定的基础类型定义枚举。 定义不带特定基础类型的枚举时,PowerShell 会创建 (System.Int32) 作为基础类型的枚举[int]
。
枚举的基础类型必须是 整型数值类型。 以下列表包含具有短名称和完整类型名称的有效类型:
byte
- System.Bytesbyte
- System.SByteshort
- System.Int16ushort
- System.UInt16int
- System.Int32uint
- System.UInt32long
- System.Int64ulong
- System.UInt64
可以将枚举的特定基础类型定义为短名称或完整类型名称。 以下定义在功能上是相同的。 只有用于基础类型的名称不同。
enum LongValueEnum : long {
Zero
One
Two
}
enum LongValueEnum : System.Int64 {
Zero
One
Two
}
设置枚举值的格式
可以通过调用静态 Format 方法以及实例 ToString 方法的重载,将枚举值转换为其字符串表示形式。 可以使用格式字符串来控制枚举值以字符串形式表示的精确方式。 有关详细信息,请参阅 枚举格式字符串。
以下示例使用每个受支持的枚举格式字符串 (G
、 X
g
d
D
或 F
x
f
) 将 TaskState 枚举的每个成员转换为其字符串表示形式。
enum TaskState {
ToDo
Doing
Done
}
[TaskState].GetEnumValues() | ForEach-Object {
[pscustomobject]@{
"ToString('G')" = $_.ToString('G')
"ToString('D')" = $_.ToString('D')
"ToString('X')" = $_.ToString('X')
"ToString('F')" = $_.ToString('F')
}
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
ToDo 0 00000000 ToDo
Doing 1 00000001 Doing
Done 2 00000002 Done
以下示例将格式字符串用于标志枚举的值。
[Flags()] enum FlagEnum {
A = 1
B = 2
C = 4
}
$FlagValues = @(
[FlagEnum]::A # 1
[FlagEnum]::B # 2
[FlagEnum]::A + [FlagEnum]::B # 3
[FlagEnum]::C # 4
[FlagEnum]::C + [FlagEnum]::A # 5
[FlagEnum]::C + [FlagEnum]::B # 6
[FlagEnum]::C + [FlagEnum]::A + [FlagEnum]::B # 7
[FlagEnum]::C + [FlagEnum]::C # 8
)
foreach ($Value in $FlagValues) {
[pscustomobject]@{
"ToString('G')" = $Value.ToString('G')
"ToString('D')" = $Value.ToString('D')
"ToString('X')" = $Value.ToString('X')
"ToString('F')" = $Value.ToString('F')
}
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
A 1 00000001 A
B 2 00000002 B
A, B 3 00000003 A, B
C 4 00000004 C
A, C 5 00000005 A, C
B, C 6 00000006 B, C
A, B, C 7 00000007 A, B, C
8 8 00000008 8
请注意,对于标志枚举, G
和 F
格式字符串显示用逗号分隔的值的集标志列表。 最后一个值 8
不会列出任何标志,因为它实际上不是有效的标志集。 如果不复制至少一个标志,则不能组合枚举标志来获取 的总 8
和。
使用 Update-TypeData 定义扩展方法
不能在声明中为枚举定义方法。 若要扩展枚举的功能,可以使用 Update-TypeData cmdlet 定义 ScriptMethod
枚举的成员。
以下示例使用 Update-TypeData
cmdlet 将方法添加到 GetFlags()
FileAttributes 标志枚举。 它返回为值设置的标志的数组。
[Flags()] enum FileAttributes {
Archive = 1
Compressed = 2
Device = 4
Directory = 8
Encrypted = 16
Hidden = 32
}
$MemberDefinition = @{
TypeName = 'FileAttributes'
MemberName = 'GetFlags'
MemberType = 'ScriptMethod'
Value = {
foreach ($Flag in $this.GetType().GetEnumValues()) {
if ($this.HasFlag($Flag)) { $Flag }
}
}
}
Update-TypeData @MemberDefinition
$File = [FileAttributes]28
$File.GetFlags()
Device
Directory
Encrypted
使用类型加速器导出枚举
默认情况下,PowerShell 模块不会自动导出 PowerShell 中定义的类和枚举。 如果不调用 using module
语句,自定义类型在模块外部不可用。
但是,如果模块添加了类型加速器,则用户导入模块后,这些类型加速器将立即在会话中可用。
注意
将类型加速器添加到会话使用内部 (而不是公共) API。 使用此 API 可能会导致冲突。 如果导入模块时已存在同名的类型加速器,则下面所述的模式将引发错误。 从会话中删除模块时,它还会删除类型加速器。
此模式可确保这些类型在会话中可用。 在 VS Code 中创作脚本文件时,它不会影响 IntelliSense 或完成。
若要获取 VS Code 中自定义类型的 IntelliSense 和完成建议,需要在脚本顶部添加 语句 using module
。
以下模式演示如何在模块中将 PowerShell 类和枚举注册为类型加速器。 将代码片段添加到根脚本模块的任何类型定义之后。 请确保变量 $ExportableTypes
包含要在用户导入模块时提供给用户的每个类型。 其他代码不需要任何编辑。
# Define the types to export with type accelerators.
$ExportableTypes =@(
[DefinedTypeName]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
$Message = @(
"Unable to register type accelerator '$($Type.FullName)'"
'Accelerator already exists.'
) -join ' - '
throw [System.Management.Automation.ErrorRecord]::new(
[System.InvalidOperationException]::new($Message),
'TypeAcceleratorAlreadyExists',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Type.FullName
)
}
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
foreach($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Remove($Type.FullName)
}
}.GetNewClosure()
当用户导入模块时,添加到会话的类型加速器的任何类型都立即可用于 IntelliSense 和完成。 删除模块时,类型加速器也是如此。
从 PowerShell 模块手动导入枚举
Import-Module
#requires
和 语句仅导入模块定义的模块函数、别名和变量。 不导入枚举。
如果模块定义类和枚举,但未为这些类型添加类型加速器,请使用 using module
语句导入它们。
语句 using module
从根模块导入类和枚举, (ModuleToProcess
脚本模块或二进制模块的) 。 它不会一致地将嵌套模块中定义的类或脚本中定义的点源类导入根模块。 定义希望直接在根模块中供模块外部用户使用的类。
有关 语句 using
的详细信息,请参阅 about_Using。
在开发期间加载新更改的代码
在脚本模块开发期间,通常会更改代码,然后使用 Force 参数加载新版本的模块Import-Module
。 这仅适用于对根模块中函数的更改。 Import-Module
不会重新加载任何嵌套模块。 此外,无法加载任何更新的类。
若要确保运行最新版本,必须启动新会话。
无法在 PowerShell 中定义并使用 语句导入 using
的类和枚举进行卸载。
另一种常见的开发做法是将代码分成不同的文件。 如果一个文件中的函数使用在另一个模块中定义的枚举,则应使用 using module
语句来确保函数具有所需的枚举定义。
限制
不能使用属性修饰 PowerShell 中定义的枚举值。 只能修饰枚举声明本身,如用于将枚举定义为一组位标志的 FlagsAttribute 一样。
解决方法:无
不能在枚举定义中定义方法,并且 PowerShell 不支持定义 [扩展方法] (如 C#)。
解决方法:使用 Update-TypeData cmdlet 定义
ScriptMethod
枚举的成员。