# encoding: ascii
# api: powershell
# title: Invoke-Switch
# description: A function to invoke a switch statement, in order to allow splatting to be used with switch
# version: 0.9
# type: function
# author: Kyle A Eppler
# license: CC0
# function: Invoke-Switch
# x-poshcode-id: 3873
# x-archived: 2013-01-22T14:51:03
# x-published: 2013-01-10T16:01:00
#
# Dependencies:
# This function, as written in this version, requires the existence of a repr function such as that defined by http://poshcode.org/3872 and its successors.
# I plan to post a new version of this function that does not limit the objects that may be used as either values to match against, or values to return, to only those that support round-trip serialization and deserialization to a string and back, using a repr function for the serialization. Iām first posting this version in case some technique used in it would be useful elsewhere.
#
New-Variable castDictionaryEntries
[System.Func[System.Collections.IEnumerable, System.Collections.Generic.IEnumerable[System.Collections.DictionaryEntry]]] `
$castDictionaryEntries = [System.Delegate]::CreateDelegate(
[System.Func[System.Collections.IEnumerable, System.Collections.Generic.IEnumerable[System.Collections.DictionaryEntry]]],
[System.Linq.Enumerable].GetMethod(
'Cast', @('Public, Static')).MakeGenericMethod(
@([System.Collections.DictionaryEntry])))
Set-Variable castDictionaryEntries -Option ReadOnly
function Invoke-Switch {
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.Collections.IDictionary] $CaseMap,
[Parameter(Position=1, Mandatory=$false)]
[ValidateSet('Regex', 'Wildcard', 'Exact')]
[string] $SwitchMode,
[Parameter(Position=2, Mandatory=$false)]
$DefaultCase,
[Parameter(Position=3, Mandatory=$true, ValueFromPipeline=$true)]
[AllowNull()]
$InputObject,
[Parameter()]
[switch] $CaseSensitive)
begin {
New-Variable mode; [string] $mode = $null
if($PSBoundParameters.ContainsKey('SwitchMode')) {
$mode = " -$SwitchMode"
}
New-Variable caseOption; [string] $caseOption = $null
if($CaseSensitive.IsPresent) {
$caseOption = ' -CaseSensitive'
}
Set-Variable mode, caseOption -Option ReadOnly
New-Variable value
New-Variable cases; [string] $cases =
$castDictionaryEntries.Invoke($CaseMap) `
| % { $value = $_.Value; return $_.Key } `
| repr `
| % { return $_ } `
-End {
if($PSBoundParameters.TryGetValue(
'DefaultCase', [ref] $value))
{
Write-Output default
}
} `
| % { return "$_ { Write-Output (,$(repr $value)) }" } `
| Join-String -Separator ' '
Set-Variable cases -Option ReadOnly
New-Variable switchScript; [scriptblock] `
$switchScript = $PSCmdlet.InvokeCommand.NewScriptBlock(
"switch$mode$caseOption (`$InputObject) { $cases }")
Set-Variable switchScript -Option ReadOnly
$PSCmdlet.WriteDebug($switchScript)
}
process {
. $switchScript | % { $PSCmdlet.WriteObject($_) }
}
}