2014-11-13 2 views
7

Предположим, у меня есть сценарий с множеством функций, принимающих те же параметры, в одних и тех же позициях и с теми же типами и ограничений, например:Можно ли повторно использовать блок «param» для нескольких функций?

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 ... 

Я хотел разделить param блок со всеми функциями, чтобы избежать потенциальные проблемы (они нуждаются в, чтобы они были одинаковыми для всех) и чтобы избежать избыточности.

Есть ли способ в PowerShell разделить блок param на несколько функций в том же скрипте? Если нет, есть ли альтернативы этому?

+1

Является ли это сценарий powershell обязательным? Как насчет проекта C#, который был встроен в модуль powershell? Если это опция, вы можете использовать какой-то базовый класс для всех ваших командлетов с той же структурой параметров. – Travis

+0

На самом деле нет, наличие этого как скрипта не является обязательным вообще. Не могли бы вы написать свой комментарий в качестве ответа, показывающего, как это возможно? Я очень заинтересован. Знаете ли вы, что невозможно достичь этого, используя скрипт? – julealgon

+0

Я не могу придумать способ сделать это только в скрипте – Travis

ответ

3

Если вы в состоянии, я бы порекомендовал идти с проектом «C#, который строит модуль« PowerShell ». В зависимости от вашей ситуации существуют различные преимущества, в том числе:

  1. Безопасность во время компиляции. Я знаю, что некоторые разработчики предпочли бы скомпилированных/сильно типизированных языков из-за дополнительной безопасности
  2. Легче писать автоматизированные тесты. Это может быть спорным, но в моем мнении, что библиотеки, такие как nUnit и другие тестовые рамки , являются огромным плюсом
  3. Знание языков. Я столкнулся с множеством разработчиков, знакомых с C#, но не powershell, и поэтому они борьба.

Чтобы начать работу, я нашел this article. В основном, это говорит, чтобы добавить ссылку на System.Management.Automation.dll к вашему проекту, а затем очень простой командлет будет выглядеть следующим образом:

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(); 
     } 

    } 

Затем, чтобы использовать этот модуль, откройте PowerShell приглашение, перейдите туда, где построена ваша dll, и используйте командлет Import-Module.

А затем для вашего конкретного вопроса (Как я повторно Param блоков с различными командлетами?) вы можете иметь базовый командлет, который определяет параметры, и все командлетов вы хотите писать могут наследовать, что от основания класс.

2

Я бы рекомендовал использовать предложение Тревиса и перейти к скомпилированному командлету. Вы спросили в одном из своих комментариев, если это было возможно только с помощью сценария, поэтому я попытаюсь привести пример этого. Расширенные функции поддерживают создание динамических параметров, и вы можете комбинировать, что возможность с помощью командлета Get-Command для создания динамических версий параметров указанной команды в:

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 } 
} 

Это должно работать, за исключением, когда ссылка команда также имеет динамические параметры.

Смежные вопросы