2014-11-13 11 views
7

Supponiamo che io ho uno script con molteplici funzioni che assumono gli stessi parametri esatti, nelle stesse posizioni e con gli stessi tipi e vincoli, in questo modo:È possibile riutilizzare un blocco "param" tra più funzioni?

function Verb1-MyValue { 
    [CmdletBinding()] 
    param (
     [parameter(Mandatory = $true)][String]$Param1, 
     [parameter(Mandatory = $true)][String]$Param2, 
     [ValidateSet("Value1","Value2")][String]$Param3 = "Value1" 
    ) 
    # code ... 
} 

function Verb2-MyValue { 
    [CmdletBinding()] 
    param (
     [parameter(Mandatory = $true)][String]$Param1, 
     [parameter(Mandatory = $true)][String]$Param2, 
     [ValidateSet("Value1","Value2")][String]$Param3 = "Value1" 
    ) 
    # code ... 
} 

# and so on ... 

ho voluto condividere il blocco param con tutte le funzioni per evitare potenziali problemi (sono necessario per essere lo stesso per tutti) e per evitare la ridondanza.

C'è un modo in PowerShell per condividere il blocco param su più funzioni nello stesso script? In caso contrario, ci sono alternative ad esso?

+1

Scrive questo come uno script di PowerShell obbligatorio? Che dire di un progetto C# che è stato costruito in un modulo PowerShell? Se questa è un'opzione, è possibile utilizzare una sorta di classe base per tutti i cmdlet con la stessa struttura dei parametri. – Travis

+0

In realtà no, avere questo come script non è obbligatorio. Potresti lavorare il tuo commento come una risposta che mostra come sarebbe possibile? Sono molto interessato. Sai se è impossibile raggiungere questo obiettivo usando solo lo script? – julealgon

+0

Non riesco a pensare al modo di farlo solo nella sceneggiatura – Travis

risposta

3

Se si è in grado, si consiglia di andare con il "progetto C# che costruisce un approccio di modulo PowerShell". A seconda della situazione, ci sono una serie di vantaggi alcuni dei quali includono:

  1. Sicurezza in fase di compilazione. So che alcuni sviluppatori preferirebbero le lingue compilate/fortemente tipizzate a causa della maggiore sicurezza
  2. Test di automazione più facili da scrivere. Questo può essere discutibile, ma nel mio parere , avere librerie come nUnit e altri framework di test sono un vantaggio enorme
  3. Conoscenza della lingua. Ho incontrato molti sviluppatori che hanno familiarità con C#, ma non PowerShell, e quindi sono in lotta .

Per iniziare, ho trovato this article. In sostanza, si dice di aggiungere un riferimento a System.Management.Automation.dll al progetto, e poi un cmdlet molto di base apparirebbe come segue:

using System; 
using System.Collection.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Management.Automation; 

namespace MyModule 
{ 
    [Cmdlet(VerbsCommon.Get, "Saluation")] 
    public class GetSaluation : PSCmdlet 
    { 
     private string[] nameCollection; 

     [Parameter(
      Mandatory = true, 
      ValueFromPipelineByPropertyName = true, 
      ValueFromPipelin = true, 
      Position = 0, 
      HelpMessage = "Name to get salutation for." 
     )] 
     [Alias("Person", "FirstName")] 
     public string[] Name 
     { 
      get { return nameCollection;} 
      set { nameCollection = value;} 
     } 

     protected override void BeginProcessing() 
     { 
      base.BeginProcessing(); 
     } 

     protected override void ProcessRecord() 
     { 
      foreach (string name in nameCollection) 
      { 
       WriteVerbose("Creating salutation for " + name); 
       string salutation = "Hello, " + name; 
       WriteObject(salutation); 
      } 
     } 

     protected override void EndProcessing() 
     { 
      base.EndProcessing(); 
     } 

    } 

Quindi, per usare questo modulo, aprire un PowerShell prompt, passare a dove è stata creata la DLL e utilizzare il cmdlet Import-Module.

E poi per la tua domanda specifica (Come posso riutilizzare blocchi param con diversi cmdlet?) si può avere un cmdlet di base che definisce i parametri, e tutti i cmdlet si desidera scrivere può ereditare che dalla base classe.

2

Suggerirei di utilizzare il suggerimento di Travis e andare al percorso del cmdlet compilato. Hai chiesto in uno dei tuoi commenti se questo fosse possibile solo con uno script, quindi, cercherò di fornire un esempio per farlo. Funzioni avanzate supporta la creazione di parametri dinamici, e si possono combinare questa possibilità con il cmdlet Get-Command per creare versioni dinamica dei parametri di un comando specificato:

function GetDynamicParamDictionary { 
    [CmdletBinding()] 
    param(
     [Parameter(ValueFromPipeline=$true, Mandatory=$true)] 
     [string] $CommandName 
    ) 

    begin { 
     # Get a list of params that should be ignored (they're common to all advanced functions) 
     $CommonParameterNames = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject([type] [System.Management.Automation.Internal.CommonParameters]) | 
      Get-Member -MemberType Properties | 
      Select-Object -ExpandProperty Name 
    } 

    process { 

     # Create the dictionary that this scriptblock will return: 
     $DynParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 

     # Convert to object array and get rid of Common params: 
     (Get-Command $CommandName | select -exp Parameters).GetEnumerator() | 
      Where-Object { $CommonParameterNames -notcontains $_.Key } | 
      ForEach-Object { 
       $DynamicParameter = New-Object System.Management.Automation.RuntimeDefinedParameter (
        $_.Key, 
        $_.Value.ParameterType, 
        $_.Value.Attributes 
       ) 
       $DynParamDictionary.Add($_.Key, $DynamicParameter) 
      } 

     # Return the dynamic parameters 
     $DynParamDictionary 
    } 
} 

function TestFunction { 
    # Create some dummy params 
    param(
     [string] $StringParam, 
     [switch] $Switch1, 
     [switch] $Switch2, 
     [int] $IntParam 
    ) 
} 

function MimicTestFunction { 
    [CmdletBinding()] 
    # Empty param block (you could add extra params here) 
    param() 

    # Mimic TestFunction's parameters 
    dynamicparam { GetDynamicParamDictionary TestFunction } 
    process { $PSBoundParameters } 
} 

function MimicGetChildItem { 
    [CmdletBinding()] 
    param() 

    dynamicparam { GetDynamicParamDictionary Get-ChildItem } 
    process { $PSBoundParameters } 
} 

Questo dovrebbe funzionare, tranne quando un comando di riferimento ha anche parametri dinamici.

Problemi correlati