gpt4 book ai didi

Powershell:使用参数集重载 C# 风格的函数?

转载 作者:行者123 更新时间:2023-12-02 08:50:21 25 4
gpt4 key购买 nike

在 C# 中,函数重载历来出现如下所示,其中每个重载都会在更简单的签名之上添加一些参数:

public void Initialize(int version);
public void Initialize(int version, string workspaceName);
public void Initialize(int version, string workspaceName, Path workspaceRoot, bool force);

在 Powershell 中,这样的重载是不可能的;但是,函数重载的一些近似是通过 System.Management.Automation.ParameterAttribute 的 ParameterSetName 属性提供的。这允许我们将参数声明为某些参数集的成员,这允许我们有效地为我们的函数定义单独的签名。最简单的案例 ParameterSetName examples是这样的:

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

获取此函数的帮助会产生以下结果:

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

但是,这种基本类型的示例对于参数集的复杂用法来说并不令人难以置信,因为参数集是完全互斥的。但是如果我们想让一些参数成为所有参数集的成员呢?更有经验的用户可能会建议这是特殊“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>]

显然,当“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>]

现在,$x 参数如我们所料出现在所有函数签名中。

最后是最复杂的情​​况。如果我们希望一个参数出现在一些但不是所有签名中怎么办?原始示例中给出的 workspaceName 参数符合此描述。也许这个解决方案的关键是意识到可以为 param block 中的每个参数声明多个 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

Powershell 声称它无法确定参数集,很可能是因为 WorkspaceName 出现在多个签名中。作为记录,当仅指定 -Version 或除最复杂的签名以外的任何签名时,也会发生这种情况。这可以通过 [CmdletBinding(DefaultParameterSetName="version")] 或其他方式有所缓解,但这不是一个合适的解决方案。

所以在这一切之后,我的问题是:我怎样才能获得我正在寻找的那种签名?我是否需要创建一组过于明确的开关,例如 -VersionMode、-WorkspaceNameMode、-CreateWorkspaceMode 来指定我希望它运行的模式,从根本上否定参数集检测的好处?也许是模式枚举?这可以通过使用 ParameterAttribute 的 Mandatory 和 Position 属性来优雅地完成吗?

谢谢!

最佳答案

如果您尝试模拟 C# 函数重载,最简单的方法是简单地允许“可选”参数,例如:

function Initialize([int]$version, [string]$workspaceName, [string]workspaceRoot, [switch]Force)

调用者未指定的参数将默认为 $null(开关将默认为 $false)。您还可以像这样为参数提供默认值:

function Initialize([int]$version, [string]$workspaceName = $(<script here>), [string]workspaceRoot, [switch]Force)

关于Powershell:使用参数集重载 C# 风格的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8915649/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com