PSA: существует известная проблема, связанная с сохранением старых копий классов в памяти. Это действительно сбивает с толку работу с классами, если вы об этом не знаете. Вы можете прочитать об этом здесь.
using
подвержен ловушкам
Ключевое слово using
подвержено различным ошибкам, а именно:
- Оператор
using
не работает для модулей, не входящих в PSModulePath
, если вы не укажете полный путь к модулю в операторе using
. Это довольно удивительно, потому что, хотя модуль доступен через Get-Module
, оператор using
может не работать в зависимости от того, как модуль был загружен.
- Оператор
using
может использоваться только в самом начале «сценария». Никакая комбинация [scriptblock]::Create()
или New-Module
, похоже, не преодолеет это. Строка, переданная в Invoke-Expression
, похоже, действует как своего рода автономный скрипт; using
оператор в начале такого рода строк работает. То есть Invoke-Expression "using module $path"
может быть успешным, но объем, в котором становится доступным содержимое модуля, кажется довольно непостижимым. Например, если Invoke-Expression "using module $path"
используется внутри блока сценария Pester, классы внутри модуля недоступны из одного и того же блока сценария Pester.
Приведенные выше утверждения основаны на . Насколько я могу судить, использование ScriptsToProcess
похоже на определение класса вне модуля следующим образом:
# this is like defining c in class.ps1 and referring to it in ScriptsToProcess
class c {
[string] priv () { return priv }
[string] pub () { return pub }
}
# this is like defining priv and pub in module.psm1 and referring to it in RootModule
New-Module {
function priv { 'private function' }
function pub { 'public function' }
Export-ModuleMember 'pub'
} | Import-Module
[c]::new().pub() # succeeds
[c]::new().priv() # fails
Вызов этого приводит к
public function
priv : The term 'priv' is not recognized ...
+ [string] priv () { return priv } ...
Функция модуля priv
недоступна из класса, хотя priv
вызывается из класса, который был определен при импорте этого модуля. Это может быть то, что вы хотите, но я не нашел ему применения, потому что обнаружил, что методы класса обычно нуждаются в доступе к некоторой функции в модуле, которую я хочу сохранить конфиденциальной.
.NewBoundScriptBlock()
Кажется, работает надежно
Вызов блока сценария, привязанного к модулю, содержащему класс, кажется, надежно работает для экспорта экземпляров класса и не страдает от тех ошибок, которые есть у using
. Рассмотрим этот модуль, который содержит класс и был импортирован:
New-Module 'ModuleName' { class c {$p = 'some value'} } |
Import-Module
Вызов [c]::new()
внутри блока сценария, привязанного к модулю, создает объект типа [c]
:
PS C:\> $c = & (Get-Module 'ModuleName').NewBoundScriptBlock({[c]::new()})
PS C:\> $c.p
some value
Идиоматическая альтернатива .NewBoundScriptBlock()
Похоже, есть более короткая идиоматическая альтернатива .NewBoundScriptBlock()
. Каждая из следующих двух строк вызывает блок сценария в состоянии сеанса модуля, выводимого Get-Module
:
& (Get-Module 'ModuleName').NewBoundScriptBlock({[c]::new()})
& (Get-Module 'ModuleName') {[c]::new()}}
Последний имеет то преимущество, что он передает поток управления среднему блоку сценария конвейера, когда объект записывается в конвейер. .NewBoundScriptBlock()
, с другой стороны, собирает все объекты, записанные в конвейер, и возвращает только после завершения выполнения всего блока сценария.
person
alx9r
schedule
05.11.2016
Import-Module holidays -verbose
перечисляет вашиdata_block
? - person Vesper   schedule 25.06.2015PS ~> import-module holidays -verbose VERBOSE: Importing function 'get-holidays'.
- person jason   schedule 25.06.2015Export-Module
действительно существует (вопрос не риторический)? ЭтоExport-ModuleMember
? - person Peter Mortensen   schedule 18.06.2021