Может ли функция Powershell обрабатывать несколько типов ввода?
Я работаю над функцией, которая сравнивает два объекта, чтобы определить их идентичность. Однако я хотел бы, чтобы он также работал с другими типами, такими как строки или целые числа.
C++ позволяет объявлять разные функции с одним и тем же именем, чтобы по-разному обрабатывать вызовы функций с разными типами ввода. Мне известно о существовании наборов параметров, однако, насколько мне известно, именно пользователь должен указать, какой набор параметров он использует.
Я пытаюсь сделать что-то подобное
function Compare-Objects{
Param(
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName = "Hashtables")]
[ValidateNotNullOrEmpty()]
[Hashtable]$Item1Hash,
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName = "Integers")]
[ValidateNotNullOrEmpty()]
[int]$Item1int,
[Parameter(Mandatory=$true,
Position=1,
ParameterSetName = "Hashtables")]
[ValidateNotNullOrEmpty()]
[Hashtable]$Item2Hash,
[Parameter(Mandatory=$true,
Position=1,
ParameterSetName = "Integers")]
[ValidateNotNullOrEmpty()]
[Hashtable]$Item2Int
)
if($PSCmdlet.ParameterSetNamePositionv -match "Integers"){ Return ($Item1Int -eq $Item2Int)}
else{
#do some other stuff with $Item1Hash and $Item2Hash
}
}
Дополнительные баллы, если я могу назвать переменные одинаковыми (так $Item1Hash
а также $Item1Int
стать обоими $Item1
с присвоением соответствующего типа)
1 ответ
Как утверждает Jeff Zeitlin в своем комментарии:
Пользователям не нужно указывать набор параметров в явном виде - PowerShell выводит соответствующий набор параметров из определенной комбинации аргументов (или их отсутствии), передаваемых при вызове.
Вывод основан на типах данных аргументов, на том, передаются ли аргументы позиционно (без имени параметра) и какие параметры помечены как обязательные, а имя вступившего в силу набора параметров отражается в$PSCmdlet.ParameterSetName
внутри вызываемого (расширенного) скрипта / функции.
Эта способность определять применимый набор параметров аналогична автоматическому разрешению перегрузки в C-подобных языках.
Хотя любой заданный параметр может участвовать в нескольких наборах параметров - и действительно по умолчанию является частью всех из них - вы принципиально не можете объявлять параметры с одним и тем же именем, но с разными типами данных.
Если вам нужны такие "полиморфные" параметры, вам придется реализовать свою собственную логику, которая не полагается на наборы параметров:
function Compare-Objects {
[CmdletBinding(PositionalBinding=$false)]
Param(
[Parameter(Mandatory, Position=0)]
[ValidateNotNullOrEmpty()]
# Define as [object] to initially accept any value; specific types
# are later enforced inside the function body.
[object] $Item1
,
[Parameter(Mandatory, Position=1)]
[ValidateNotNullOrEmpty()]
[object] $Item2
)
# Ensure that a supported type was passed.
if ($Item1.GetType() -notin [int], [hashtable]) { Throw "Unsupported argument type." }
# Ensure that both arguments have the same type.
if ($Item1.GetType() -ne $Item2.GetType()) { Throw "Inconsistent argument types." }
if ($Item1 -is [int]) {
"[int] arguments given."
}
else {
"[hashtable] arguments given."
}
}
Однако, если использование одних и тех же имен параметров не является обязательным, и вы довольны позиционным вызовом с использованием разных типов данных, наборы параметров могут помочь, как показывает следующий упрощенный пример:
function Foo {
[CmdletBinding()]
param(
[Parameter(ParameterSetName='int', Position=0)]
[int] $ItemInt
,
[Parameter(ParameterSetName='hash', Position=0)]
[hashtable] $ItemHash
)
"Parameter set chosen: $($PSCmdlet.ParameterSetName)"
}
# Call the function first with an [int], then with a [hashtable], positionally.
10, @{ foo = 1 } | ForEach-Object { Foo $_ }
Приведенное выше дает следующее, показывающее, что тип данных аргумента автоматически выбрал соответствующий набор параметров:
Parameter set chosen: int
Parameter set chosen: hash