title: PowerShell ArrayList converting to PSCustomObject when added as Property of another PSCustomObject inside another ArrayList
body: <p>I am trying to create a PSCustomObject that has multiple properties that are ArrayLists  containing PSCustomObjects. I Am adding the parent object to an ArrayList as well. The idea is to create a relationship that I can easily parse out to yml or another format.
  For example,</p>
  <pre class="lang-yml prettyprint-override"><code>Hosts:                            # Parent ArrayList
    - HostName: myhost              # Start of Parent Object
      FQDN: myhost.my.domain.com
      IPs:                          # ArrayList of Objects, Property of Parent Object
        - IP: 192.168.1.2           # Start of Child Object
          MAC: 00:00:00:00:00:00
        - IP: 10.10.1.1             # Start of Child Object
      Records:                      # ArrayList of Objects, Property of Parent Object
        - Zone: 192.168.1           # Start of Child Object
          RRType: PTR
          Source: 2
          Target: myhost.my.domain.com
          TTL: 2H
        - Zone: my.domain.com       # Start of Child Object
          RRType: A
          Source: myhost.my.domain.com
          Target: 192.168.1.2
          TTL: 2H
  </code></pre>
  <p>The problem I'm having is when I try to add a new object to one of the ArrayList properties of the Parent object, I'm receiving the following error:</p>
  <pre class="lang-ps prettyprint-override"><code>Method invocation failed because [System.Management.Automation.PSCustomObject] does not contain a method named 'add'.
  At C:\merge.ps1:96 char:13
  +             ,$_.DNSRecords.Add($RecordObj)
  +             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo          : InvalidOperation: (add:String) [], RuntimeException
      + FullyQualifiedErrorId : MethodNotFound
  </code></pre>
  <p>I am using this function to create hosts:</p>
  <pre class="lang-ps prettyprint-override"><code>function New-HostEntry {
      param (
          [Parameter(ValueFromPipeline=$true,position=0)]$HostName,
          [Parameter(ValueFromPipeline=$true,position=1)]$FQDN,
          [Parameter(ValueFromPipeline=$true,position=2)]$IP,
          [Parameter(ValueFromPipeline=$true,position=3)]$MAC,
          [Parameter(ValueFromPipeline=$true,position=4)]$RecordObj
      )
  
      $IPS = New-Object System.Collections.ArrayList
      if ($IP){
          $IPEntry = [PSCustomObject]@{
              IP = $IP
              MAC = $MAC
          }
          $IPS.Add($IPEntry)
      }
  
      $DNSRecords = New-Object System.Collections.ArrayList
      if ($RecordObj){
          $DNSRecords.Add($RecordObj)
      }
  
      [PSCustomObject]@{
          HostName = $HostName
          FQDN = $FQDN
          IPs = $IPS
          DNSRecords = $DNSRecords
      }
  }
  </code></pre>
  <p>In the main part of the script, I am creating the parent collection &amp; adding hosts to it with the following:</p>
  <pre class="lang-ps prettyprint-override"><code>[System.Collections.ArrayList]$hosts= @()
  $hosts.add((New-HostEntry -HostName $hostname -FQDN $fqdn -IP $ip -MAC $mac -RecordObj $RecordObj))
  </code></pre>
  <p>Sometimes The values for IP, MAC, or RecordObj may be $null or missing. That does not seem to matter when initially creating the new Host object &amp; adding it to the collection.</p>
  <p>Later, an existing Host object (Inside the $Hosts ArrayList) may need to have a $RecordObj added to it:</p>
  <pre class="lang-ps prettyprint-override"><code>Add-DNSRecordToHost $_.HostName $RecordObj
  </code></pre>
  <p>This is an example of a RecordObj:</p>
  <pre class="lang-ps prettyprint-override"><code>$RecordObj = [PSCustomObject]@{
      Zone = $zonename 
      Source = $Source
      TTL = $TTL
      RRType = $RRType
      Preference = $Preference
      Target = $Target
      Comment = $Comment
  }
  </code></pre>
  <p>Finally, this is the function that is failing:</p>
  <pre class="lang-ps prettyprint-override"><code>function Add-DNSRecordToHost{
      param (
          [Parameter(ValueFromPipeline=$true,position=0)]$HostName,
          [Parameter(ValueFromPipeline=$true,position=1)]$RecordObj
      )
      $found = $false
      #Get the host with matching HostName
      $hosts | Where-Object {$_.HostName -eq $HostName} | ForEach-Object {
          #Compare each record already on the host to the new record
          Write-host &quot;Checking&quot; $_.HostName &quot;for&quot; $RecordObj.Zone $RecordObj.RRType &quot;record ...&quot;
          foreach ($DNSRecord in $_.DNSRecords){
              if ( -not (Compare-Object $DNSRecord.PSObject.Properties $RecordObj.PSObject.Properties) ) {
                  #objects match
                  Write-Host &quot;ERROR: Zone Record&quot; $RecordObj.Zone &quot;already exists on &quot; $HostObj.Host -ForegroundColor Yellow
                  $found = $true
              }
          }
          #If none of the records match add the new record to the host
          if (!$found){
              Write-Host &quot;ACTION: Adding Zone Record&quot; $RecordObj.Zone &quot;to&quot; $_.HostName -ForegroundColor Cyan
              #Write-Host $DNSRecords.toString()
              $_.DNSRecords.Add($RecordObj)
              #,$_.DNSRecords.Add($RecordObj)
              #$DNSRecords = $_.DNSRecords; $DNSRecords.add($RecordObj); $_.DNSRecords = $DNSRecords
              #$_.DNSRecords | %{ Write-Host $_.Zone $_.Source $_.TTL $_.RRType $_.Preference $_.Target $_.Comment -ForegroundColor Yellow }
          }
      }
  }
  </code></pre>
  <p>I have left in (but commented out) my attempts at debugging.</p>
  <p>Note: I had also tried passing the function a $host object, but it failed also:</p>
  <pre class="lang-ps prettyprint-override"><code>function Add-DNSRecordToHost{
      param (
          [Parameter(ValueFromPipeline=$true,position=0)]$Host,
          [Parameter(ValueFromPipeline=$true,position=1)]$RecordObj
      )
      $found = $false
      foreach ($DNSRecord in $Host.DNSRecords){
          if ( -not (Compare-Object $DNSRecord.PSObject.Properties $RecordObj.PSObject.Properties) ) {
              $found = $true
          }
      }
      if (!$found){
          $Host.DNSRecords.Add($RecordObj)
      }
  }
  
  $hosts | % {Add-DNSRecordToHost $_ $RecordObj}
  </code></pre>
  <p>It errors out when I try to add a $RecordObj to the DNSRecords property of a Host object.
  I Expect the DNSRecords property to be an ArrayList, but the according to the above error message, it has converted to a PSCustomObject. Why is it being changed, and how can I correctly add to it?</p>