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 #########################
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 }
}