Author Posts

July 28, 2016 at 8:17 pm

Hi!

Recently I ran into the problem with validate set and strings containing spaces.
Found this great post by Rohn Edwards with a solution using a C# class.

I'm wondering if it would be possible to use a native approach instead?
Tried the following code, but the overloaded ToString() from a PSCustomObject does not seem to be called when the ValidateSet is enumerated.

Does it have something to do with ToString() being overloaded by a ScriptMethod?

Function _New-CustomObjForQuotedString {
    [CmdletBinding()]
    Param(
        [string]$InputString,
        [string]$QuoteCharacter="'"
    )
    
    $obj = [PSCustomObject]@{
                        Value = $InputString
                        QuoteCharacter = $QuoteCharacter
                    }

    $obj | Add-Member -MemberType ScriptMethod -Name ToString -Value {
        if ( ($this.Value).contains(' ') ) {
            return $($this.QuoteCharacter)+$($this.Value)+$($this.QuoteCharacter)
        } else {
            return $this.Value
        }
    } -Force


    return $obj
}


function TestDynamicSetWithSpace_PSNative {
    [CmdletBinding()]
    param(
    )

    dynamicparam {
		# from https://powershell.org/forums/topic/dynamic-parameter-question/#post-22381
        $ParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
 
        $Attributes = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
        $Attributes.Add( (New-Object System.Management.Automation.ParameterAttribute) )

        # Convert each object into a DynParamQuotedString:
        $Attributes.Add( (New-Object System.Management.Automation.ValidateSetAttribute($__DynamicParamValidateSet | % { _New-CustomObjForQuotedString -InputString $_ })) )

        $ParamDictionary.$__DynamicParamName = New-Object System.Management.Automation.RuntimeDefinedParameter (
            $__DynamicParamName,
            [PSCustomObject],    # Notice the type here
            $Attributes
        )       

        return $ParamDictionary
    } 

    process {
        
        $ParamValue = $null
        if ($PSBoundParameters.ContainsKey($__DynamicParamName)) {
            # Get the original string back:
            $ParamValue = $PSBoundParameters.$__DynamicParamName
        }

        "$__DynamicParamName = $ParamValue"
    }
}

August 8, 2016 at 8:54 pm

_Overridden_, not overloaded, actually. An overload is when you have multiple copies of a method, each with a different signature (parameters). And in this case, it's possible, yes, that the ScriptMethod is not being called. I'm not sure what happens under the hood, but if it happens "outside" PowerShell proper, then it'd be calling the base class ToString(), not the tacked-on ToString() from the ETS. I think a custom class might be the only way to do that.