pf-object.ps1

function Set-Member { 
    Param (
        [Parameter(ValueFromPipeline=$true)]
        $InputObject,
        $Name,
        $value,
        [Switch]$force,
        [Switch]$PassThru
    )
    Process {
        if (!$InputObject) { return }

        $doAssignValue = (-not $InputObject.$Name) -or $force.IsPresent

        $member = Get-Member -InputObject $InputObject -Name $Name
        if (!$member) {
            $doAssignValue = $true
            $member = Add-Member -InputObject $InputObject -Name $Name -Value $null `
                -MemberType NoteProperty -PassThru
        }

        if ($doAssignValue) {
            $valueResult = if ($Value -is [ScriptBlock]) {
                $Value.InvokeReturnAsIs($InputObject)
            }
            else {
                $Value
            }
            $InputObject.$Name = $valueResult
        }
        if ($PassThru) {
            return $InputObject
        }
    }
}

function Set-Member:::Example {
    $obj = ConvertFrom-Json "{ A : 1, B : 2}"
    $obj | Set-Member -Name D -Value { 4 }
    $obj | Set-Member -Name D -Value { 5 }
    $obj | Set-Member -Name D -Value { 6 } -force
    $obj | Set-Member -Name E -Value 7
    $obj | Set-Member -Name F -Value { $_.D }
}

function Add-Object_PropertyMember { 
    Param (
        [Parameter(ValueFromPipeline=$true)]
        $InputObject,
        $Name,
        $Value
    )
    Process {
        if ($InputObject) {
            $member = Get-Member -InputObject $InputObject -Name $Name
            if ($member) {
                $UserInfo.$Name = $value
            }
            else {
                Add-Member -InputObject $InputObject -MemberType NoteProperty -Name $Name -Value $value
            }
            return $InputObject
        }
    }
}
function Add-Object_PropertyMember:::Test {
    [PSCustomObject]@{ A = 1} | Add-Object_PropertyMember -Name B -Value 2 | assert (@{ A = 1; B = 2})
    [PSCustomObject]@{ A = 1; B = 3 } | Add-Object_PropertyMember -Name B -Value 2 | assert (@{ A = 1; B = 2})
}