sobota, 30 sierpnia 2014

Dynamiczne parametry funkcji w PS ( dynamicParam )

ValidateSet jest fantastycznym atrybutem do parametrów funkcji. Umożliwia podpowiadanie argumentów oraz nie dopuszcza zmienianie wartości. Ma jednak jedną wadę. dozwolone wartości musza być stałymi przedefiniowanymi. Jeżeli chcielibyśmy zwalidować dane wejściowe, które ilość oraz wartości są zmienne to nie mamy takiej możliwości. Z pomocą przychodzi nam dynamiczny parametr. Całkowicie zmienia składnie funkcji. Przykład wywołania dynamicznego parametru jest poniżej. Przypuśćmy, że mamy hashtable z dozwolonymi nazwami oraz ich wartościami

$dparamColl = @{
param1 = 'test';
param2 = 'abc';
param3 = 'xyz'
}

function function_name
{
    param(
     $param
   )

    dynamicParam {

       $attributes = new-object System.Management.Automation.ParameterAttribute
       $attributes.ParameterSetName = "__AllParameterSets" 
       $attributes.Mandatory = $true
       $attributeCollection =      new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
       $attributeCollection.Add($attributes)
       $_Values  = $dparamColl.Keys
       $ValidateSet =      new-object System.Management.Automation.ValidateSetAttribute($_Values)
       $attributeCollection.Add($ValidateSet)
       $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter( "dparam", [string], $attributeCollection)
       $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
       $paramDictionary.Add("dparam", $dynParam1)
       return $paramDictionary
    }

    begin{}
    process{
      return $dparam
    }
    end{}
}

Można stworzyć osobną funkcję, która będzie zwracała RuntimeDefinedParameterDictionary z dynamicznymi parametrami:
function Get-DynamicParam
{
    param(
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [array]$paramSet, 
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$paramName)

        $attributes = new-object System.Management.Automation.ParameterAttribute
        $attributes.ParameterSetName = "__AllParameterSets" 
        $attributes.Mandatory = $true
        $attributeCollection =      new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
        $attributeCollection.Add($attributes)
        $_Values  = $paramSet
        $ValidateSet =      new-object System.Management.Automation.ValidateSetAttribute($_Values)
        $attributeCollection.Add($ValidateSet)
        $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter( $paramName, [string], $attributeCollection)
        $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
        $paramDictionary.Add($paramName, $dynParam1)
        return $paramDictionary
}

Dynamiczny parametr pierwszy raz zastosowałem jak pisałem moduł do Oracla. W jednej zmiennej przetrzymuje zapytania sql, a funkcja z parametrem dynamicznym wywołuje to zapytanie sql:
$sqlHelpQueryCollection = @{
DatabaseName = @'
select ora_database_name from dual
'@;

Instance = @'
select * from v$instance
'@;
#and many more
}


function Invoke-OracleSqlHelpQuery
{
    [CmdletBinding()]
    param(
    $conn
    )
    dynamicParam {
        return Get-DynamicParam -paramSet $sqlHelpQueryCollection.Keys -paramName 'sqlHelpQuery'
    }

    begin{}
    process{
    $sql = $sqlHelpQueryCollection[$sqlHelpQuery]
    return Get-OracleDataTable -conn $conn -sql $sql
    }
    end{}
}

Efekt dynamicznego parametru jest przedstawiony poniżej:
Cały kod modułu jest na githubie.


Brak komentarzy:

Prześlij komentarz