【问题标题】:Hashtable key with point带点的哈希表键
【发布时间】:2020-05-31 00:25:10
【问题描述】:

如何发出带有点字符的哈希表键,例如FlatAppearance.BorderSize,以便正确?

$Button = [System.Windows.Forms.Button] @{

    # This is not a valid entry
    FlatAppearance.BorderSize = 0
}
$Button = [System.Windows.Forms.Button] @{

    # This is not a valid entry too
    "FlatAppearance.BorderSize" = 0
}
$Button = [System.Windows.Forms.Button] @{

    # This is not a valid entry too too
    FlatAppearance = @{ BorderSize = 0 }
}

当然可以这样写

$Button = [System.Windows.Forms.Button] @{}
$Button.FlatAppearance.BorderSize = 0

不过,写在哈希表里面更方便。但是怎么做?谢谢

【问题讨论】:

    标签: powershell constructor hashtable object-initializers


    【解决方案1】:

    由于Button 类型的.FlatAppearance 属性属于FlatButtonAppearance 类型,因此在这种情况下没有好的解决方案,因为FlatButtonAppearance 类型有没有公共的、无参数的构造函数

    如果是这样,您将能够编写:

    using namespace System.Windows.Forms
    
    $Button = [Button] @{
    
        # !! This is how you would generally do it, but
        # !! IN THIS CASE IT DOESN'T WORK, due to lack of an appropriate constructor.
        FlatAppearance = [FlatButtonAppearance] @{ BorderSize = 0 }
    }
    

    上述语法类似于 C# 的 object initializer 语法,将在下一节中解释。


    PowerShell 中的对象初始化语法:

    对于从哈希表 (@{ ... }) 或预先存在的 [pscustomobject] 实例[1]转换为类型文字 ([...]) /sup> 执行隐式构造(隐式创建实例)然后多属性初始化才能工作,必须满足以下先决条件

    • 目标类型必须有一个构造函数(可能还有其他[2]),即:

      • 公开
      • and 无参数[3]
    • 类型的公共属性的名称必须与哈希表条目的键匹配,并且条目的值必须与目标属性具有相同或兼容的类型。

    这使得 PowerShell 可以通过调用 new SomeType()(PowerShell 语法中的 [SomeType]::new())在后台创建实例,然后从同名的哈希表条目中分配公共属性的值。

    注意:PowerShell v3+ 中提供的此类转换实际上是语法糖,用于使用-Property 参数调用
    New-Object cmdlet;只有后者在 v2 中有效。


    除了查阅类型的文档之外,您还可以通过调用 PowerShell 提供的静态 ::new 方法轻松在 PowerShell 中检查类型的构造函数不带括号 (() ):

    PS> [System.Windows.Forms.FlatButtonAppearance]::new
    # NO OUTPUT, which means the type has no public constructors at all.
    
    # [ProcessStartInfo] has several public constructors, among them
    # a public parameterless one, so you *can* initialize it by hashtable.
    PS> [System.Diagnostics.ProcessStartInfo]::new
    
    OverloadDefinitions
    -------------------
    System.Diagnostics.ProcessStartInfo new()
    System.Diagnostics.ProcessStartInfo new(string fileName)
    System.Diagnostics.ProcessStartInfo new(string fileName, string arguments)
    
    

    确定类型的公共、可写实例属性

    PS> [System.Windows.Forms.FlatButtonAppearance].GetProperties('Public, Instance') | 
           ? CanWrite | Select-Object Name, PropertyType
    
    Name               PropertyType        
    ----               ------------        
    BorderSize         System.Int32        
    BorderColor        System.Drawing.Color
    CheckedBackColor   System.Drawing.Color
    MouseDownBackColor System.Drawing.Color
    MouseOverBackColor System.Drawing.Color
    

    [1] 例如,这对于从 JSON 反序列化的对象很有用,这些对象变为 [pscustomobject] 实例;例如:$obj = '{ "Text": "Submit" }' | ConvertFrom-Json; $button = [Button] $obj

    [2] 边缘情况:不能也有具有以下参数类型之一的 single 参数公共构造函数,因为它会按原样绑定强制转换操作数:

    • [object]
    • 从哈希表 (@{ ... }) 投射时:[hashtable][System.Collections.IDictionary]
    • [pscustomobject] 实例投射时:[psobject][pscustomobject]

    [3] 方便的是,如果你定义一个类型(类)而不声明任何构造函数,你会得到一个公共无参数的默认;例如,在以下 PowerShell 示例类中,Foo隐式提供了这样一个构造函数:
    class Foo { [string] $Bar }; $foo = [Foo] @{ Bar = 'None' }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-10
      • 2010-11-26
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 2014-05-30
      • 2019-09-22
      • 2011-04-17
      相关资源
      最近更新 更多