2013-02-07 53 views
9

我正在写一个负责将记录写入数据库的cmdlet(在PowerShell中)。使用条件命令行,似乎我必须定义四个不同的参数集。是否有更好的方法来声明多个参数集?

是否有这样做的更succient方式?

详情

小命令的参数是:

  • ComputerName(SQL服务器连接到)
  • Path(数据的位置)
  • Xml(该原始数据本身)
  • UserName
  • Password
  • UseIntegratedSecurity(而不是用户名/密码,则使用当前凭证)

PathXml是互斥的,并且UserName/PasswordUseIntegratedSecurity是互斥的。

得到这个正确接线,好像我必须定义四个不同的参数设置,例如:


function Install-WidgetData 
{ 
    [CmdletBinding()] 
    PARAM 
    (
     [Parameter(ParameterSetName="Xml_AutoConnect", Mandatory=$True)] 
     [Parameter(ParameterSetName="Xml_ManualConnect", Mandatory=$True)] 
     [Parameter(ParameterSetName="Path_AutoConnect", Mandatory=$True,)] 
     [Parameter(ParameterSetName="Path_ManualConnect", Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string[]] $ComputerName, 

     [Parameter(ParameterSetName="Path_AutoConnect", Mandatory=$True)] 
     [Parameter(ParameterSetName="Path_ManualConnect", Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string] $Path, 

     [Parameter(ParameterSetName="Xml_AutoConnect", Mandatory=$True)] 
     [Parameter(ParameterSetName="Xml_ManualConnect", Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string[]] $Xml, 

     [Parameter(ParameterSetName="Xml_AutoConnect")] 
     [Parameter(ParameterSetName="Path_AutoConnect")] 
     [switch] $UseIntegratedSecurity, 

     [Parameter(ParameterSetName="Xml_ManualConnect")] 
     [Parameter(ParameterSetName="Path_ManualConnect")] 
     [ValidateNotNullOrEmpty()] 
     [string] $UserName, 

     [Parameter(ParameterSetName="Xml_ManualConnect")] 
     [Parameter(ParameterSetName="Path_ManualConnect")] 
     [ValidateNotNullOrEmpty()] 
     [string] $Password, 
    ) 
+2

'$ ComputerName'提供访问其它来源的连接字符串可以没有'ParametrSetName'。 –

+0

据我所知,你唯一可以最小化的是@ C.B。说过。让我们只是说有一个原因,为什么'#region'存在=) –

回答

0

好了,这是最简洁的方式。如果/然后陷阱来说明所有可能的参数集合,则更简洁,然后是开关/情况的恐怖!

然而,你的另一种选择是写互斥参数集不同commandlest,例如

Install-WidgetDataFromPath 
Install-WidgetDataFromXml 

两个可以叫Install-WidgetData脚本命令行,你可以一直隐藏在模块或者使用范围的修改,以隐藏它里面如果您仅使用脚本文件,则从全局范围启动。内部commandlet可以为两个(或更多)面向用户的包装器实现共享代码。从你的代码判断,我认为你不需要解释如何实现这一点。

7

如果你想在参数集快速完整性检查,你可以使用Show-Command

这将显示包含多个选项卡形式,每个参数集。例如:

Show-Command Get-ChildItem 

将显示此:

enter image description here

+1

这对非技术人员来说非常方便。优秀的东西。 – jasper

+0

'Get-Command Install-WidgetData -Syntax'将同样有用 – Matt

+0

直到现在我还没有关于'Show-Command'的内容。谢谢! –

3

可悲的是,这是做到这一点的唯一方法,根据about_Functions_Advanced_Parameters

下面是摘录:

You can specify only one ParameterSetName value in each argument and only 
    one ParameterSetName argument in each Parameter attribute. To indicate that 
    a parameter appears in more than one parameter set, add additional Parameter   
    attributes. 

    The following example explicitly adds the Summary parameter to the Computer 
    and User parameter sets. The Summary parameter is mandatory in one parameter 
    set and optional in the other. 

    Param 
     (
     [parameter(Mandatory=$true, 
        ParameterSetName="Computer")] 
     [String[]] 
     $ComputerName, 

     [parameter(Mandatory=$true, 
        ParameterSetName="User")] 
     [String[]] 
     $UserName 

     [parameter(Mandatory=$false, ParameterSetName="Computer")] 
     [parameter(Mandatory=$true, ParameterSetName="User")] 
     [Switch] 
     $Summary 
    ) 

有关参数集的详细信息,请参阅MSDN库中的Cmdlet Parameter Sets

1

有一个更好的方法,但它是一个设计解决方案,而不是技术之一。

问题是,你的功能实际上是做了太多事情。有人可能会说这违反了单一责任原则。它执行的每个任务都有两个独立的参数集。任务及其参数集:

  • 建立一个连接字符串
    • 手册(用户名和密码)
    • 汽车(OS帐号认证)
  • 将查询发送到数据库
    • XML数据
    • 点包含路径XML文件中的数据

由于每个任务都有自己不同的参数设置,你的函数结束了需要它们的笛卡尔乘积(手动& XML,汽车& XML,手动&路径,自动&路径)。

任何时候当您发现自己处于这些“笛卡尔乘积”参数情况中的某一个时,几乎总是表示您可以将一项功能移动到单独的功能中,并将新功能的结果作为原始参数。在这种情况下,您可以将它分解为New-ConnectionStringInstall-WidgetData,并且Install-WidgetData可以接受完整的连接字符串作为参数。这将删除从Install-WidgetData构建连接字符串的逻辑,将几个参数合并为一个,并将所需参数集的数量减半。

function New-ConnectionString(
    [Parameter(Mandatory=$True, Position=0)] # Makes it mandatory for all parameter sets 
    [ValidateNotNullOrEmpty()] 
    [string[]]$ComputerName, 

    [Parameter(ParameterSetName="AutoConnect", Mandatory=$True)] 
    [switch]$UseIntegratedSecurity, 

    [Parameter(ParameterSetName="ManualConnect", Mandatory=$True, Position=1)] 
    [ValidateNotNullOrEmpty()] 
    [string]$UserName, 

    [Parameter(ParameterSetName="ManualConnect", Mandatory=$True, Position=2)] 
    [ValidateNotNullOrEmpty()] 
    [string]$Password 
) { 
    # ... Build connection string up 
    return $connString 
} 


function Install-WidgetData(
    [Parameter(Mandatory=$True, Position=0)] 
    [ValidateNotNullOrEmpty()] 
    [string]$ConnectionString, 

    [Parameter(ParameterSetName="Path", Mandatory=$True, Position=1)] 
    [ValidateNotNullOrEmpty()] 
    [string]$Path, 

    [Parameter(ParameterSetName="Xml", Mandatory=$True)] 
    [ValidateNotNullOrEmpty()] 
    [string[]]$Xml 
) { 
    # Do installation 
} 

你可以看到通过在命令调用help这没有你想要的东西:

PS C:\> help New-ConnectionString 

NAME 
    New-ConnectionString 

SYNTAX 
    New-ConnectionString [-ComputerName] <string[]> -UseIntegratedSecurity [<CommonParameters>] 

    New-ConnectionString [-ComputerName] <string[]> [-UserName] <string> [-Password] <string> [<CommonParameters>] 

... 

PS C:\> help Install-WidgetData 

NAME 
    Install-WidgetData 

SYNTAX 
    Install-WidgetData [-ConnectionString] <string> [-Path] <string> [<CommonParameters>] 

    Install-WidgetData [-ConnectionString] <string> -Xml <string[]> [<CommonParameters>] 

... 

然后你叫他们是这样的:

Install-WidgetData (New-ConnectionString 'myserver.example.com' -UseIntegratedSecurity) ` 
    -Path '.\my-widget-data.xml' 

可以存储结果当然,如果你想要的话,New-ConnectionString的变量。您也这样做,重构得到一些额外的功能:

  • New-ConnectionString的返回值可以为任意数量的需要连接字符串函数被重用。
  • 呼叫者可以获取,如果他们愿意
  • 呼叫者可以有利于做自己的放弃你的New-ConnectionString,如果他们需要使用的功能,你并没有
+0

这是正确的解决方案,即使它不是真正的'PowerShell'方式。它使用起来更复杂一点(调用两个函数而不是一个函数)。这需要一些很好的解释/文档/例子。 –

+1

@oɔɯǝɹ我不会说这不是PowerShell的做事方式。这与我在调用'Join-Path'在传入文件路径之前建立一个文件路径似乎没有太大区别。你只是添加一个函数来从几个不同的部分建立一个内聚的参数。 – jpmc26

相关问题