bwe*_*rks 2 parameters powershell overloading optional-parameters
在C#中,函数重载历史上似乎如下所示,其中每个重载在更简单的签名之上添加了一些参数:
public void Initialize(int version);
public void Initialize(int version, string workspaceName);
public void Initialize(int version, string workspaceName, Path workspaceRoot, bool force);
Run Code Online (Sandbox Code Playgroud)
在Powershell中,诸如此类的过载是不可能的; 但是,通过System.Management.Automation.ParameterAttribute的ParameterSetName属性提供了函数重载的一些近似值.这允许我们将参数声明为某些参数集的成员,这允许我们有效地为我们的函数定义单独的签名.在大多数ParameterSetName示例中找到的简单情况是这样的:
function test-param
{
[CmdletBinding(DefaultParametersetName="p2")]
param(
[Parameter(ParameterSetName="p1",Position=0)]
[String]
$d,
[Parameter(ParameterSetName="p2", Position=0)]
[String]$i
)
switch ($PsCmdlet.ParameterSetName)
{
"p1" { Write-Host ([DateTime]$d); break}
"p2" { Write-Host ([INT]$i); break}
}
}
Run Code Online (Sandbox Code Playgroud)
获取此函数的帮助会产生以下结果:
PS D:\.ws> get-help test-param
test-param [[-i] <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
test-param [[-d] <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Run Code Online (Sandbox Code Playgroud)
然而,这种基本类型的示例对于参数集的复杂用法并不令人难以置信,因为参数集完全是互斥的.但是如果我们想让一些参数成为所有参数集的成员呢?更有经验的用户可能会建议这是特殊"AllParameterSets"参数集的情况,如果未指定参数集,则根据MSDN,该参数集是默认值.但是,请考虑以下事项:
PS D:\.ws> function test-param
{
[CmdletBinding(DefaultParametersetName="p2")]
param
(
[Parameter(ParameterSetName="p1",Position=0)]
[String]
$d,
[Parameter(ParameterSetName="p2", Position=0)]
[String]$i,
[Parameter(ParameterSetName="AllParameterSets")]
[String]$x
)
}
PS D:\.ws> get-help test-param
test-param [[-i] <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
test-param [[-d] <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
test-param [-x <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Run Code Online (Sandbox Code Playgroud)
显然,当"AllParameterSets"被指定为参数集时,它实际上并不像人们所期望的那样包含在所有参数集中.这可以通过省略声明来看出:
PS D:\.ws> function test-param
{
[CmdletBinding(DefaultParametersetName="p2")]
param
(
[Parameter(ParameterSetName="p1",Position=0)]
[String]
$d,
[Parameter(ParameterSetName="p2", Position=0)]
[String]$i,
[String]$x
)
}
PS D:\.ws> get-help test-param
test-param [[-i] <String>] [-x <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
test-param [[-d] <String>] [-x <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Run Code Online (Sandbox Code Playgroud)
现在,$ x参数出现在我们期望的所有函数签名中.
最后,最复杂的情况.如果我们希望一个参数出现在一些但不是所有签名中,该怎么办?原始示例中给出的workspaceName参数符合此描述.也许这个解决方案的关键是要意识到可以为param块中的每个参数声明多个Parameter属性.这允许我们为每个签名建立一个参数集,并使用它所属的每个集合的Parameter属性来装饰每个参数.考虑以下:
PS D:\.ws> function Initialize-Something
{
[CmdletBinding()]
param
(
[Parameter(ParameterSetName="version")]
[Parameter(ParameterSetName="workspaceName")]
[Parameter(ParameterSetName="createWorkspace")]
[int] $Version,
[Parameter(ParameterSetName="workspaceName")]
[Parameter(ParameterSetName="createWorkspace")]
[string] $WorkspaceName,
[Parameter(ParameterSetName="createWorkspace")]
[string] $WorkspaceRoot,
[Parameter(ParameterSetName="createWorkspace")]
[switch] $Force
)
}
PS D:\.ws> get-help initialize-something
Initialize-Something [-Version <Int32>] [-WorkspaceName <String>] [-WorkspaceRoot <String>] [-Force] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Initialize-Something [-Version <Int32>] [-WorkspaceName <String>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Initialize-Something [-Version <Int32>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
PS D:\.ws> initialize-something -workspacename "test"
Initialize-Something : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:21
+ initialize-something <<<< -workspacename "test"
+ CategoryInfo : InvalidArgument: (:) [Initialize-Something], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Initialize-Something
Run Code Online (Sandbox Code Playgroud)
Powershell声称它无法确定参数集,更可能是因为WorkspaceName出现在多个签名中.对于记录,当仅指定-Version时,或者对于除最复杂之外的任何签名时,也会发生这种情况.这可以通过[CmdletBinding(DefaultParameterSetName ="version")]或其他东西来缓解,但它不是一个合适的解决方案.
毕竟,我的问题是:我怎样才能实现我正在寻找的那种签名?我是否需要创建一组过度显式的开关,如-VersionMode,-WorkspaceNameMode,-CreateWorkspaceMode,以指定我希望它运行的模式,从根本上否定参数集检测的优点?也许模式枚举?使用ParameterAttribute的Mandatory和Position属性可以通过一些优雅来完成吗?
谢谢!
如果您试图模拟C#函数重载,最简单的方法是简单地允许"可选"参数,例如:
function Initialize([int]$version, [string]$workspaceName, [string]workspaceRoot, [switch]Force)
Run Code Online (Sandbox Code Playgroud)
调用者未指定的参数将默认为$ null(开关将默认为$ false).您还可以为参数提供默认值,如下所示:
function Initialize([int]$version, [string]$workspaceName = $(<script here>), [string]workspaceRoot, [switch]Force)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4637 次 |
| 最近记录: |