У меня есть код, похожий на

if ($condition) {
  do-it1 -param1 "cookies" -param2 "eat"
  do-it1 -param1 "bananas" -param2 "peal"
  do-it1 -param1 "apples" -param2 "core"
  do-it1 -param1 "parachuting" -param2 "dont"
} else {
  do-it2 -param1 "cookies" -param2 "eat"
  do-it2 -param1 "bananas" -param2 "peal"
  do-it2 -param1 "apples" -param2 "core"
  do-it2 -param1 "parachuting" -param2 "dont"
}

То, что я хочу сделать, это что-то вроде


if ($condition) {
  $doWhat = do-it1
} else {
  $doWhat = do-it2
}

$doWhat -param1 "cookies" -param2 "eat"
$doWhat -param1 "bananas" -param2 "peal"
$doWhat -param1 "apples" -param2 "core"
$doWhat -param1 "parachuting" -param2 "dont"

В C $ я бы просто использовал делегата или что-то еще OO.

Action<string,string> doWhat = condition? doIt1:doIt2;
doWhat("cookies","eat");
doWhat("bananas","peal");
doWhat("apples","core");
doWhat("parachuting","dont");

В моем реальном коде я не использую константы в качестве параметров для doWhat.

Как я могу изменить командлет, который вызывает мой скрипт, не дублируя код с кучей похожих веток if?

Спасибо в Andcation!

0
DrFloyd5 19 Окт 2020 в 16:34

1 ответ

Лучший ответ

Первые три примера здесь касаются того, как я лично подхожу к рефакторингу кода, как в примере, который вы показали, ответ на ваш конкретный вопрос находится в самом низу :)

PowerShell поддерживает сплаттинг, то есть несколько аргументов именованных параметров могут быть переданы как один словарь:

$paramArgs = @{
 "param1" = "cookies"
 "param2" = "eat"
}

if ($condition) {
  do-it1 @paramArgs
}
else {
  do-it2 @paramArgs
}

Итак, создайте массив словарей, по одному на вызов, и мы можем сократить код до:

$paramArgTables = @(
  @{ param1="cookies"; param2="eat"}
  @{ param1="bananas"; param2="peal" }
  @{ param1="apples"; param2="core" }
  @{ param1="parachuting"; param2="dont" }
)

if ($condition) {
  $paramArgTables |ForEach-Object {
    do-it1 @_
  }
}
else {
  $paramArgTables |ForEach-Object {
    do-it2 @_
  }
}

Вы также можете сделать еще один шаг вперед, вызвав целевую команду по имени с помощью оператора вызова & (который также поддерживает сплаттинг):

$paramArgTables = @(
  @{ param1="cookies"; param2="eat"}
  @{ param1="bananas"; param2="peal" }
  @{ param1="apples"; param2="core" }
  @{ param1="parachuting"; param2="dont" }
)

$cmdName = if($condition){
  'do-it1'
}
else{
  'do-it2'
}

$paramArgTables |ForEach-Object {
  & $cmdName @_
}

Это означает, что вы также можете делать именно то, что хотите:

$cmdName = if($condition){
  'do-it1'
}
else{
  'do-it2'
}

& $cmdName -param1 "cookies" -param2 "eat"
& $cmdName -param1 "bananas" -param2 "peal"
& $cmdName -param1 "apples" -param2 "core"
& $cmdName -param1 "parachuting" -param2 "dont"

Я просто предпочитаю сплаттинг :)

2
Mathias R. Jessen 19 Окт 2020 в 13:49