是否可以使用属性初始化 .NET 类型?
Is it possible to initialize a .NET type with properties?
例如我想使用这个 class Microsoft.HyperV.PowerShell.HardDiskDrive
我试过这样初始化的:
$obbb = [Microsoft.HyperV.PowerShell.HardDiskDrive]@{
Path = 'D:\TEST\test\Virtual Hard Disks\test.vhdx'
DiskNumber = $null
MaximumIOPS = '1000'
MinimumIOPS = '0'
QoSPolicyID = '00000000-0000-0000-0000-000000000000'
SupportPersistentReservations = $false
WriteHardeningMethod = '0'
ControllerLocation = '0'
ControllerNumber = '0'
ControllerType = '0'
Name = 'Hard Drive on IDE controller number 0 at location 0'
PoolName = 'Primordial'
Id = 'Microsoft:480244F9-44D4-4BFC-B34B-EC3C425D52F7\83F8638B-8DCA-4152-9EDA-2CA8B33039B4\0\0\D'
VMId = '480244f9-44d4-4bfc-b34b-ec3c425d52f7'
VMName = 'test'
VMSnapshotId = '00000000-0000-0000-0000-000000000000'
VMSnapshotName = ''
CimSession = $null
ComputerName = 'NodeTest'
IsDeleted = $false
VMCheckpointId = '00000000-0000-0000-0000-000000000000'
VMCheckpointName = ''
}
但是出现这个错误:
Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type "Microsoft.HyperV.PowerShell.HardDiskDrive".
At line:1 char:1
+ $obbb = [Microsoft.HyperV.PowerShell.HardDiskDrive]@{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException
我也尝试过不同的 New-Object 变体 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-object?view=powershell-6
但是有错误。
有没有可能?
谢谢。
Maximilian Burszley 在对问题的评论中提供了关键指针:
PowerShell 的从哈希表中强制转换的构造技术 仅在目标类型(也)具有 构造函数 时才有效:
- public
- 和 无参数
您看到的错误消息暗示 [Microsoft.HyperV.PowerShell.HardDiskDrive]
没有 有这样的构造函数(请参阅底部部分了解如何检查构造函数)。
假设具有此类构造函数的类型具有 public 属性 可设置,您可以从其条目匹配这些属性的任何子集的哈希表进行转换,其中每个条目的键必须是此类属性的名称属性 及其值类型兼容(已经与 属性 类型相同或可转换为它)。
PowerShell 首先使用无参数构造函数实例化类型,然后设置哈希表中指定的 public 属性。
这是一个(有点做作的)例子:
$obj = [System.Exception] @{ # just [Exception] works too, because 'System.' is implied
HResult = 0x8000400
Source = 'SomeModule'
}
以上相当于:
$obj = New-Object System.Exception; $obj.HResult = 0x8000400; $obj.Source = 'SomeModule'
由于需要无参数构造函数,散列表技术目前主要用于 DTO-like“属性 包”。
If all public 给定类型的构造函数 do 有参数 ,哈希表技术将不起作用,您必须 调用构造函数 以实例化类型 - 通过静态 ::new
方法 (PSv5+)或通过 New-Object
cmdlet;例如,调用 [System.DateTime]
构造函数的 (int year, int month, int day)
重载:
New-Object DateTime -ArgumentList 2018, 12, 1 # '-ArgumentList' is optional
[DateTime]::new(2018, 12, 1) # PSv5+ equivalent
为了调用单参数构造函数,可以使用cast替代——见下一节。
然而,an enhancement is coming to PowerShell Core Tip of the hat to TessellatingHeckler.
这将允许使用哈希表技术,即使是带有参数的构造函数,只要哈希表条目集与给定的构造函数重载的参数匹配。
通常,除了上面讨论的哈希表情况,casts ([<target-type>] <operand>
) 以及 隐式转换 在以下场景中工作,按考虑顺序排列:
此信息是从 PowerShell Core 的源代码中收集的 here。
(a) 如果目标类型装饰有 TypeConverterAttribute
attribute that specifies a custom TypeConverter
or PSTypeConverter
class 支持从操作数类型转换。
或者,这些自定义转换器 classes 可以通过 PowerShell 的 ETS(扩展类型系统)与类型相关联,通过 Update-TypeData -TypeConverter
)
(b) 如果目标类型支持从 string 构造实例的静态 ::Parse()
方法:
[DateTime] '2018-12-01'
# The above matches `::Parse()` overload `static datetime Parse(string s)`
# However, given that there's also an overload that accepts a
# System.IFormatProvider argument, PowerShell uses that in order
# to use *culture-invariant* parsing.
# Thus, the above is the equivalent of:
[DateTime]::Parse('2018-12-01', [cultureinfo]::InvariantCulture)
有关 PowerShell 使用 不变区域性 的更多信息,请参见 this answer。
(c) 如果目标类型有一个 public 构造函数,其操作数与以下参数类型相同或兼容:
[Exception] 'Something failed'
# The above matches constructor `Exception(string message)` and is the
# equivalent of:
New-Object Exception -ArgumentList 'Something failed'
[Exception]::new('Something failed')
(d) 如果目标类型为操作数类型定义隐式或显式 conversion operator。
(e) 如果操作数类型实现了 IConvertible
接口,用于构造目标类型的等效实例(仅限于 CLR 运行时类型(内置类型))。
在PSv5+中,很容易检查给定(加载)类型的构造函数:调用静态::new
方法,不带括号,它列出了所有 public 可用构造函数的方法重载(签名);使用类型 [System.Random]
:
的示例
PS> [Random]::new
OverloadDefinitions
-------------------
System.Random new()
System.Random new(int Seed)
存在 a new()
重载 - 无参数 - 是无参数 public 构造函数 .
的证据
如果根本没有输出,则意味着该类型没有任何 public 构造函数。
例如我想使用这个 class Microsoft.HyperV.PowerShell.HardDiskDrive
我试过这样初始化的:
$obbb = [Microsoft.HyperV.PowerShell.HardDiskDrive]@{
Path = 'D:\TEST\test\Virtual Hard Disks\test.vhdx'
DiskNumber = $null
MaximumIOPS = '1000'
MinimumIOPS = '0'
QoSPolicyID = '00000000-0000-0000-0000-000000000000'
SupportPersistentReservations = $false
WriteHardeningMethod = '0'
ControllerLocation = '0'
ControllerNumber = '0'
ControllerType = '0'
Name = 'Hard Drive on IDE controller number 0 at location 0'
PoolName = 'Primordial'
Id = 'Microsoft:480244F9-44D4-4BFC-B34B-EC3C425D52F7\83F8638B-8DCA-4152-9EDA-2CA8B33039B4\0\0\D'
VMId = '480244f9-44d4-4bfc-b34b-ec3c425d52f7'
VMName = 'test'
VMSnapshotId = '00000000-0000-0000-0000-000000000000'
VMSnapshotName = ''
CimSession = $null
ComputerName = 'NodeTest'
IsDeleted = $false
VMCheckpointId = '00000000-0000-0000-0000-000000000000'
VMCheckpointName = ''
}
但是出现这个错误:
Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type "Microsoft.HyperV.PowerShell.HardDiskDrive".
At line:1 char:1
+ $obbb = [Microsoft.HyperV.PowerShell.HardDiskDrive]@{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException
我也尝试过不同的 New-Object 变体 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-object?view=powershell-6
但是有错误。
有没有可能?
谢谢。
Maximilian Burszley 在对问题的评论中提供了关键指针:
PowerShell 的从哈希表中强制转换的构造技术 仅在目标类型(也)具有 构造函数 时才有效:
- public
- 和 无参数
您看到的错误消息暗示 [Microsoft.HyperV.PowerShell.HardDiskDrive]
没有 有这样的构造函数(请参阅底部部分了解如何检查构造函数)。
假设具有此类构造函数的类型具有 public 属性 可设置,您可以从其条目匹配这些属性的任何子集的哈希表进行转换,其中每个条目的键必须是此类属性的名称属性 及其值类型兼容(已经与 属性 类型相同或可转换为它)。
PowerShell 首先使用无参数构造函数实例化类型,然后设置哈希表中指定的 public 属性。
这是一个(有点做作的)例子:
$obj = [System.Exception] @{ # just [Exception] works too, because 'System.' is implied
HResult = 0x8000400
Source = 'SomeModule'
}
以上相当于:
$obj = New-Object System.Exception; $obj.HResult = 0x8000400; $obj.Source = 'SomeModule'
由于需要无参数构造函数,散列表技术目前主要用于 DTO-like“属性 包”。
If all public 给定类型的构造函数 do 有参数 ,哈希表技术将不起作用,您必须 调用构造函数 以实例化类型 - 通过静态 ::new
方法 (PSv5+)或通过 New-Object
cmdlet;例如,调用 [System.DateTime]
构造函数的 (int year, int month, int day)
重载:
New-Object DateTime -ArgumentList 2018, 12, 1 # '-ArgumentList' is optional
[DateTime]::new(2018, 12, 1) # PSv5+ equivalent
为了调用单参数构造函数,可以使用cast替代——见下一节。
然而,an enhancement is coming to PowerShell Core Tip of the hat to TessellatingHeckler. 这将允许使用哈希表技术,即使是带有参数的构造函数,只要哈希表条目集与给定的构造函数重载的参数匹配。
通常,除了上面讨论的哈希表情况,casts ([<target-type>] <operand>
) 以及 隐式转换 在以下场景中工作,按考虑顺序排列:
此信息是从 PowerShell Core 的源代码中收集的 here。
(a) 如果目标类型装饰有 TypeConverterAttribute
attribute that specifies a custom TypeConverter
or PSTypeConverter
class 支持从操作数类型转换。
或者,这些自定义转换器 classes 可以通过 PowerShell 的 ETS(扩展类型系统)与类型相关联,通过 Update-TypeData -TypeConverter
)
(b) 如果目标类型支持从 string 构造实例的静态 ::Parse()
方法:
[DateTime] '2018-12-01'
# The above matches `::Parse()` overload `static datetime Parse(string s)`
# However, given that there's also an overload that accepts a
# System.IFormatProvider argument, PowerShell uses that in order
# to use *culture-invariant* parsing.
# Thus, the above is the equivalent of:
[DateTime]::Parse('2018-12-01', [cultureinfo]::InvariantCulture)
有关 PowerShell 使用 不变区域性 的更多信息,请参见 this answer。
(c) 如果目标类型有一个 public 构造函数,其操作数与以下参数类型相同或兼容:
[Exception] 'Something failed'
# The above matches constructor `Exception(string message)` and is the
# equivalent of:
New-Object Exception -ArgumentList 'Something failed'
[Exception]::new('Something failed')
(d) 如果目标类型为操作数类型定义隐式或显式 conversion operator。
(e) 如果操作数类型实现了 IConvertible
接口,用于构造目标类型的等效实例(仅限于 CLR 运行时类型(内置类型))。
在PSv5+中,很容易检查给定(加载)类型的构造函数:调用静态::new
方法,不带括号,它列出了所有 public 可用构造函数的方法重载(签名);使用类型 [System.Random]
:
PS> [Random]::new
OverloadDefinitions
-------------------
System.Random new()
System.Random new(int Seed)
存在 a new()
重载 - 无参数 - 是无参数 public 构造函数 .
如果根本没有输出,则意味着该类型没有任何 public 构造函数。