Search code examples
winformspowershellhashtable

WinForm inside hashtable


I can set form elements inside hashtable:

$Hash = @{}

$Hash.Main = New-Object System.Windows.Forms.Form
$Hash.Main.Left = 0
$Hash.Main.Top = 0
...
$Hash.Label = New-Object System.Windows.Forms.Label
$Hash.Label.Left = 0
$Hash.Label.Top = 0
...
$Hash.Panel = New-Object System.Windows.Forms.Panel
$Hash.Panel.Left = 0
$Hash.Panel.Top = 0
...

How can I write the same thing inside hashtable? I tried to make it as if it could be. And it works. But is this syntax correct?

$Hash = @{

   Main = [System.Windows.Forms.Form] @{

      Left = 0
      Top = 0
      ...
   }

   Label = [System.Windows.Forms.Label] @{

      Left = 0
      Top = 0
      ...
   }

   Panel = [System.Windows.Forms.Panel] @{

      Left = 0
      Top = 0
      ...
   }
}

Thank you


Solution

  • Yes, this syntax is correct:

    Creating Objects from Hash Tables

    Beginning in PowerShell 3.0, you can create an object from a hash table of properties and property values.

    The syntax is as follows:

    [<class-name>]@{
      <property-name>=<property-value>
      <property-name>=<property-value>
      …
    }
    

    This method works only for classes that have a null constructor, that is, a constructor that has no parameters. The object properties must be public and settable.

    For more information, see about_Object_Creation.

    Check the first condition (a constructor that has no parameters):

    [System.Drawing.Font],        ### does not have empty constructor 
    [System.Windows.Forms.Form],
    [System.Windows.Forms.Label],
    [System.Windows.Forms.Panel] |
        Where-Object { 
            'new' -in ( $_ | 
                Get-Member -MemberType Methods -Static | 
                    Select-Object -ExpandProperty Name ) -and
            $_::new.OverloadDefinitions -match ([regex]::Escape('new()'))
        } | Select-Object -ExpandProperty FullName
    
    System.Windows.Forms.Form
    System.Windows.Forms.Label
    System.Windows.Forms.Panel
    

    Check the latter condition (object properties must be public and settable):

    [System.Windows.Forms.Form],
    [System.Windows.Forms.Label],
    [System.Windows.Forms.Panel] | 
        ForEach-Object {
            @{ $_.FullName = ( 
                $_.GetProperties('Instance,Public') | Where-Object CanWrite |
                    Select-Object -ExpandProperty Name | Sort-Object
               )
            }
        }
    
    Name                           Value
    ----                           -----
    System.Windows.Forms.Form      {AcceptButton, AccessibleDefaultActionDescription, Acc...
    System.Windows.Forms.Label     {AccessibleDefaultActionDescription, AccessibleDescrip...
    System.Windows.Forms.Panel     {AccessibleDefaultActionDescription, AccessibleDescrip...
    

    Getting both above code snippets together is a trivial task…