modules/Helper/ObjectHelper.psm1

class ObjectHelper{
    # TODO review and remove
    static [PSCustomObject] ConvertToObject([hashtable] $ht) {
        # $object = New-Object PSCustomObject

        # if ($ht){
        # $ht.GetEnumerator() | ForEach-Object { Add-Member -inputObject $object `
        # -memberType NoteProperty -name $_.Name -value $_.Value }
        # }

        return ([PSCustomObject]$ht)
    }

    static [PSCustomObject] ConvertToString([hashtable] $ht){
        $isFirst = $true
        $retValue = "@{";

        foreach ($key in $ht.Keys) {
            $val = $ht[$key]
            if (-not $isFirst) { $retValue += ';' }

            if ($key -match "\s") {
                $retValue += '''{0}''=''{1}''' -f @($key, $val)
            }
            else {
                $retValue += '{0}=''{1}''' -f @($key, $val)
            }
            $isFirst = $false
        }
        $retValue += "}"

        return $retValue
    }

    static [hashtable] ConvertToHashTable([PSCustomObject] $obj){
        $ht = @{}

        if ($obj){
            $obj.psobject.properties | ForEach-Object { $ht[$_.Name] = $_.Value }
        }

        return $ht
    }

    static [object] CombineObject([object]$current, [object]$previous){
        if ($null -eq $current) { return $null }
        [object] $result = $current

        foreach ($item in $previous.PSObject.Properties.Name) {
            if (-not $current.$item) { $current.$item = $previous.$item }
        }

        return $result
    }

    static [object] MergeObject([object]$current, [object]$override){
        if ($null -eq $current) { return $override }
        [object] $result = $current

        foreach ($item in $override.PSObject.Properties.Name) {
            switch ($override.$item.GetType().Name) {
                'PSCustomObject' {
                    if ($current.$item) { $current.$item = [ObjectHelper]::MergeObject($current.$item, $override.$item)}
                    else { $current | Add-Member $item ([ObjectHelper]::MergeObject($current.$item, $override.$item)) }

                    break
                }
                'System.Object[]' {
                    foreach ($arrayItem in $item) {
                        $current.arrayItem = [ObjectHelper]::MergeObject($current.$item.arrayItem, $override.$item.arrayItem)
                    }
                    break
                }
                'System.Collections.Hashtable' {
                    foreach ($hashKey in $item.Keys) {
                        if ($current.$item.ContainsKey($hashKey)){
                            $current.$item.$hashKey = [ObjectHelper]::MergeObject($current.$item.$hashKey, $override.$item.$hashKey)
                        }
                        else{
                            $current.$item.Add($hashKey, $override.$item.$hashKey)
                        }
                    }
                    break
                }
                default {
                    if ($current.$item) { $current.$item = $override.$item }
                    else { $current | Add-Member $item $override.$item }
                }
            }
        }

        return $result
    }

    static [hashtable] MergeHashtables([hashtable]$current, [hashtable]$previous){
        [hashtable] $result = $current

        foreach ($item in $previous.GetEnumerator()) {
            if (-not $result.ContainsKey($item.Key)){
                $result.Add($item.Key, $item.Value)
            }
        }

        return $result
    }

    static [object[]] MergeObjectArray([object[]]$current, [object[]]$previous, [string]$idPropertyName){
        [object[]] $result = $current

        foreach ($obj in $previous) {
            if (-not (($current | Select-Object -ExpandProperty $idPropertyName) -contains ($obj.$idPropertyName))) {
                $result += $obj
            }
        }

        return $result
    }

    static [bool] isEqualHashTable([hashtable] $a, [hashtable] $b){
        $result = $false

        if ($a.Count -eq $b.Count){
            $result = $true
            foreach ($key in $a.Keys) {
                if ($a[$key] -ne $b[$key]) {
                    $result = $false
                    break
                }
            }
        }

        return $result
    }

    static [object] DeepCopyCli([object] $object){

        return ($object | Export-CliXML -Depth 100 | Import-CliXml)
    }

    static [object] DeepCopy([object] $object){
        # Serialize and Deserialize data using BinaryFormatter
        $ms = New-Object System.IO.MemoryStream
        $bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

        $bf.Serialize($ms, $object)
        $ms.Position = 0

        $newObject = $bf.Deserialize($ms)
        $ms.Close()

        # Use deep copied data
        return $newObject
    }
}