Functions/ConvertTo-HashString.ps1

#Requires -Version 4.0
function ConvertTo-HashString
{
<#
.SYNOPSIS
    Convert an object to a HashData string

.DESCRIPTION
    Convert an object to a HashData string

.PARAMETER InputObject
    The object that is to be converted

.EXAMPLE
    $hashObject = @{
        Name = "Tore"
        Goal = "Rule the World"
    }
    $hashObject | ConvertTo-HashString

    This will convert the hashtable to the following string
    @{Name = "Tore"; Goal = "Rule the World"}

.INPUTS
    Object

.OUTPUTS
    string
    
.NOTES
    Author: Tore Groneng
    Website: www.firstpoint.no
    Twitter: @ToreGroneng

    Modifications: vike
#>

[cmdletbinding()]
Param (
    [Parameter(ValueFromPipeLine)]
    $InputObject,
    [switch]
    $NoSpaceAroundEqualSign,
    [switch]
    $NoSpaceAfterSemicolon,
    [switch]
    [Alias('ArraySubExpression')]
    [Alias('UseArraySubExpression')]
    $AlwaysUseArraySubExpression
)

Begin
{
    $f = $MyInvocation.InvocationName
    Write-Verbose -Message "$f - START"

    $spaceAfterSemicolon = $NoSpaceAfterSemicolon ? $null : " "
    $spaceAroundEqualSign = $NoSpaceAroundEqualSign ? $null : " "

    function Test-HashStringDictionary
    {
        Param (
            $Object
        )

        $Object -is [hashtable] -or $Object -is [System.Collections.Specialized.OrderedDictionary]
    }

    function Test-HashStringEnumerable
    {
        Param (
            $Object
        )

        $null -ne $Object -and
            $Object -is [System.Collections.IEnumerable] -and
            $Object -isnot [string] -and
            -not (Test-HashStringDictionary -Object $Object)
    }

    function ConvertTo-HashStringValue
    {
        Param (
            $Value,
            [int]
            $Level = 0
        )

        if (Test-HashStringDictionary -Object $Value)
        {
            ConvertTo-HashString -InputObject $Value -Level ($Level+1)
        }
        elseif (Test-HashStringEnumerable -Object $Value)
        {
            $stringValues = foreach ($item in $Value)
            {
                ConvertTo-HashStringValue -Value $item -Level ($Level+1)
            }

            $stringValue = $(
                if ($Value.Count -eq 0)
                {
                    "@()"
                }
                else
                {
                    (
                        $Value.Count -ne 1 ? "" : ","
                    ) + (
                        $Level -gt 0 -or $AlwaysUseArraySubExpression ?
                        "@(" + ($stringValues -join ",") + ")" :
                        ($stringValues -join ",")
                    )
                }
            )

            if (Test-GenericList $Value)
            {
                $typeString = "[" + $Value.GetType().ToString() + "]"

                if ($Value.Count -eq 0 -or $Level -gt 0 -or $AlwaysUseArraySubExpression)
                {
                    $typeString + $stringValue
                }
                else
                {
                    $typeString + "(" + $stringValue + ")"
                }
            }
            else
            {
                $stringValue
            }
        }
        elseif ($null -eq $Value)
        {
            '$null'
        }
        elseif ($Value -is [int] -or $Value -is [double])
        {
            "$Value"
        }
        elseif ($Value -is [bool])
        {
            '$' + "$Value"
        }
        elseif ($Value -is [datetime])
        {
            "New-Date " + ($Value.Ticks)
        }
        elseif ($Value -is [scriptblock])
        {
            "{" + $Value + "}"
        }
        else 
        {
            '"' + $Value + '"'
        }
    }
}

Process
{
    if (Test-HashStringEnumerable -Object $InputObject)
    {
        return ConvertTo-HashStringValue -Value $InputObject
    }

    if (-not (Test-HashStringDictionary -Object $InputObject))
    {
        return ConvertTo-HashStringValue -Value $InputObject
    }

    if (-not $InputObject -or $InputObject.keys.count -eq 0) {return "@{}"}

    $out = foreach ($key in $InputObject.Keys)
    {
        Write-Verbose -Message "$f - Processing key [$key]"

        if ($key.Contains('$'))
        {
            $DisplayKey = "'$key'"
        }

        $value = $InputObject.$key
        $objType = if ($null -eq $value) { "<null>" } else { $value.GetType().Name }
        Write-Verbose -Message "$f - ObjectType = $objType"

        if ($DisplayKey)
        {
            $key = $DisplayKey
            $DisplayKey = $null
        }

        $key = "$key$spaceAroundEqualSign=$spaceAroundEqualSign"
        "$key" + (ConvertTo-HashStringValue -Value $value)
    }

    "@{" + ($out -join ";$spaceAfterSemicolon") + "}"
}

End 
{
    Write-Verbose -Message "$f - End"
}
}

Set-Alias ConvertTo-PSSource ConvertTo-HashString