Home > front end >  Instantiate Objects Automatically or with Iteration
Instantiate Objects Automatically or with Iteration

Time:04-04

    class Molecule{
    [Int]$carbon
    [Int]$hydrogen
    [Int]$oxygen
}

$items = [ordered]@{
    water = [ordered]@{carbon = 0; hydrogen = 2; oxygen = 1}
    methane = [ordered]@{carbon = 1; hydrogen = 4; oxygen = 0}
    }
 
$EachKey1 = @() # Just for T-Shooting
$EachObj = @() # Just for T-Shooting
    
foreach ($key in $items.psbase.keys){
     $EachKey1  = $key
    $key = New-Object Molecule
     $EachObj  = $key
    $key.carbon = $items.$key.carbon
    $key.hydrogen = $items.$key.hydrogen
    $key.oxygen = $items.$key.oxygen
}

""
$EachKey1 # Anticipated Values
$EachObj # Not getting values

######################### Output Below #########################

Script Output

Please assist with Instantiating Objects Automatically or via Iteration.

I am unable to instantiate Objects Water & Methane as attempted above.

Thanks!

CodePudding user response:

It's not entirely clear what your expected output would be, however, the clear mistake is in this line:

$key = New-Object Molecule

The item you're iterating over (the hash table Key) is getting replace by a new instance of the Molecule object, the when doing the Property assignment:

$key.carbon   = $items.$key.carbon
$key.hydrogen = $items.$key.hydrogen
$key.oxygen   = $items.$key.oxygen

You're effectively assigning $null to each Property Value, however, since your class properties are constrained to the type [int] PowerShell is converting $null to 0:

[int] $null # => 0

If you want an array of Molecule objects you can simply do it this way:

$EachObj = foreach ($key in $items.PSBase.Keys) {
    [Molecule] $items[$key]
}

PowerShell converts the ordered dictionary into an instance of the class by type casting or type conversion. The result would be the following:

PS /> $EachObj

carbon hydrogen oxygen
------ -------- ------
     0        2      1
     1        4      0

PS /> $EachObj[0] | Get-Member

   TypeName: Molecule

Name        MemberType Definition
----        ---------- ----------
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
ToString    Method     string ToString()
carbon      Property   int carbon {get;set;}
hydrogen    Property   int hydrogen {get;set;}
oxygen      Property   int oxygen {get;set;}

Type casting into an array of Molecule instances would also work:

PS /> $EachObj = [Molecule[]] $items[$items.PSBase.Keys]

PS /> $EachObj.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Molecule[]                               System.Array

Taking a step back, if your intent is to have an ordered dictionary with instances of your class as Values you could do it like this:

$items = [ordered]@{
    water   = [Molecule]@{ carbon = 0; hydrogen = 2; oxygen = 1 }
    methane = [Molecule]@{ carbon = 1; hydrogen = 4; oxygen = 0 }
}
  • Related