Можете ли вы перегрузить функции в PowerShell?
Я хочу, чтобы моя функция принимала строку, массив или некоторый переключатель.
Пример того, что я хочу:
- Backup-UsersData singleUser
- Backup-UsersData @( "Алиса", "Боб", 'Joe')
- Backup-UsersData-all
Можете ли вы перегрузить функции в PowerShell?
Я хочу, чтобы моя функция принимала строку, массив или некоторый переключатель.
Пример того, что я хочу:
В функциях PowerShell не перегружены. Последнее определение переопределяет предыдущее значение в той же области действия или скрывает предыдущее значение в родительской области. Таким образом, вы должны создать одну функцию и предоставить способ отличить ее режим вызова от аргументов.
В V2 вы можете использовать расширенную функцию, см. help about_Functions_Advanced_Parameters
и избегать некоторого ручного кодирования при разрешении неоднозначностей набора параметров:
# advanced function with 3 parameter sets
function Backup-UsersData
(
[Parameter(Position=0, ParameterSetName="user")]
[string]$user,
[Parameter(Position=0, ParameterSetName="array")]
[object[]]$array,
[Parameter(Position=0, ParameterSetName="all")]
[switch]$all
)
{
# use this to get the parameter set name
$PSCmdlet.ParameterSetName
}
# test
Backup-UsersData -user 'John'
Backup-UsersData 1, 2
Backup-UsersData -all
# OUTPUT:
# user
# array
# all
Обратите внимание, что этот механизм иногда странный. Например, в первом тесте мы должны явно указать имя параметра -user
. В противном случае:
Backup-UsersData : Parameter set cannot be resolved using the specified named parameters.
At C:\TEMP\_101015_110059\try2.ps1:21 char:17
+ Backup-UsersData <<<< 'John'
+ CategoryInfo : InvalidArgument: (:) [Backup-UsersData], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Backup-UsersData
Во многих случаях стандартная, а не продвинутая функция со смешанными параметрами будет делать:
function Backup-UsersData
(
[string]$user,
[object[]]$array,
[switch]$all
)
{
if ($user) {'user'}
elseif ($array) {'array'}
elseif ($all) {'all'}
else {'may be'}
}
Backup-UsersData -user 'John'
Backup-UsersData -array 1, 2
Backup-UsersData -all
Backup-UsersData
Но в этом случае вы должны разрешать (или принимать и игнорировать) двусмысленности, например. решить, что делать, если, скажем:
Backup-UsersData -user 'John' -array 1, 2 -all
Вот вариант римского ответа, который я считаю немного более гибким:
function Backup
{
[CmdletBinding(DefaultParameterSetName='Users')]
Param (
[parameter(mandatory=$true, ParameterSetName='Users', position=0, ValueFromPipeline=$true)][string[]]$User,
[parameter(mandatory=$true, ParameterSetName='AllUsers')][switch]$All
)
Begin
{
if ($All) { $User = @('User1', 'User2', 'User3') }
}
Process
{
foreach ($u in $User)
{
echo "Backup $u"
}
}
}
1) Создайте класс...
class c1 {
[int]f1( [string]$x ){ return 1 }
[int]f1( [int ]$x ){ return 2 }
}
1+) Используйте СТАТИЧЕСКИЕ МЕТОДЫ, если вы предпочитаете вызывать их без инстанцирования...
class c1 {
static [int] f1( [string]$x ){ return 1 }
static [int] f1( [int]$x ){ return 2 }
}
2) Вызовите методы в классе или объекте... перегрузка работает нормально
$o1 = [c1]::new()
o1.f1( "abc" ) ~> returns 1
o1.f1( 123 ) ~> returns 2
-или-
[c1]::f1( "abc" ) ~> returns 1
[c1]::f1( 123 ) ~> returns 2
3)
Если (как я)
вы хотите, чтобы "перегруженные функции" помещались в библиотеки...
так что ваши пользователи могут использовать их прозрачно...
из кода или из интерактивной командной строки (REPL)...
самый близкий, я мог приехать в
"Перегрузка функций в Powershell"
было что-то вроде этого:
function Alert-String() { [c1]::f1( "abc" ) }
function Alert-Strings(){ [c1]::f1( 123 ) }
function Alert-Stringn(){ [c1]::f1( 123 ) }
Может в PS-Core v8??? ;-)
Надеюсь, это поможет...
Если вы используете PSObject вместо Object для определения типа вашего параметра, он должен работать. Например, функция Get-Control знает, как перегрузить на основе типа строки или шаблона и может быть вызвана с использованием позиционного значения:
Get-Control "A-Name-Of-A-Control"
Get-Control $template
Чтобы перегрузка работала, используйте PSObject следующим образом:
Function Get-Control {
Param(
[Parameter(Mandatory=$False,ParameterSetName="ByTemplate",Position=0)]
[PSObject]
$Template,
[Parameter(Mandatory=$False,ParameterSetName="ByName",Position=0)]
[String]
$Name,
[Parameter(Mandatory=$False)]
[Switch]
$List
)
... # remaining code removed for brevity