是否可以使用属性初始化.NET类型?

时间:2018-08-27 01:05:03

标签: .net powershell constructor initialization hashtable

例如,我要使用此类 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

但是出现错误。

是否有可能?

谢谢。

1 个答案:

答案 0 :(得分:1)

TheIncorrigible1在对该问题的评论中提供了关键指针:

PowerShell的从哈希表构造广播技术仅在目标类型(也)具有构造函数的情况下有效:

  • 公开
  • 无参数

您看到的错误消息暗示[Microsoft.HyperV.PowerShell.HardDiskDrive]确实没有这样的构造函数(有关如何检查构造函数的信息,请参见底部)。

假设具有此类构造函数的类型具有 settable public 个属性,则可以从其条目的哈希表中进行广播匹配这些属性的任何子集 ,其中每个条目的键都必须是此类属性的名称,并且其值必须是类型兼容的(与属性具有相同类型或可转换的) )。
PowerShell首先使用无参数构造函数实例化类型,然后设置哈希表中指定的公共属性。

这是一个(有些人为的)示例:

$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的“属性包”

如果给定类型的所有公共构造函数具有参数,则哈希表技术将不起作用,您必须 调用构造函数以实例化类型-通过静态::new方法(PSv5 +)或New-Object cmdlet ;例如,调用(int year, int month, int day)构造函数的[System.DateTime]重载:

New-Object DateTime -ArgumentList 2018, 12, 1 # '-ArgumentList' is optional
[DateTime]::new(2018, 12, 1)  # PSv5+ equivalent

要调用单个参数构造函数,可以替代使用 cast -请参阅下一节。

不过,an enhancement is coming是PowerShell的 Core 帽子的尖端是TessellatingHeckler  只要具有哈希表项的集合与给定的构造函数重载的参数匹配,就可以在具有参数的构造函数中使用哈希表技术。


通常,除了上面讨论的哈希表情况外, 广播[<target-type>] <operand>)和隐式转换在以下情况下都有效 >,按考虑顺序:

此信息来自PowerShell Core的源代码here

(a)如果目标类型用TypeConverterAttribute属性修饰,该属性指定支持自操作数类型转换的自定义TypeConverterPSTypeConverter类。
另外,这些自定义转换器类可以通过PowerShell的ETS(扩展类型系统),通过Update-TypeData -TypeConverter)与类型关联。

(b)如果目标类型支持从{em> 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)如果目标类型具有带有单个参数的公共构造函数,则该操作数的类型相同或与-兼容:

[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方法,该方法列出所有公共可用构造函数的方法重载(签名);以类型[System.Random]为例:

PS> [Random]::new

OverloadDefinitions
-------------------
System.Random new()
System.Random new(int Seed)

存在{strong> new()重载-没有参数-证明了无参数的公共构造函数

如果根本没有输出,则表示该类型没有任何公共构造函数。