点源文件中的 PowerShell 点源 - 导入 类

PowerShell dot source within a dot sourced file - import classes

我的项目结构如下:

MyScript.ps1
classes\
    Car.ps1
    Tesla.ps1

汽车。ps1是特斯拉的基地class。ps1。我试图在特斯拉中这样定义特斯拉。ps1:

. "$PSScriptRoot\Car.ps1"

class Tesla : Car
{
}

MyScript.ps1 需要使用 Tesla class,但不需要知道它继承自 Car.

. "$PSScriptRoot\classes\Tesla.ps1"

$tesla = [Tesla]::new()

点源到 classes\Tesla.ps1 工作正常,但这个错误是从 Tesla 文件中抛出的:

Unable to find type [Car]

如果我在 MyScript 中以正确的顺序导入所有文件。ps1,它工作正常。示例:

. "$PSScriptRoot\classes\Car.ps1"
. "$PSScriptRoot\classes\Tesla.ps1"

$tesla = [Tesla]::new()

这很麻烦,尤其是随着复杂性的增加。我点采购不正确吗?有没有更好的方法来使用不在 PSModulePath 中的相对路径导入自定义 PowerShell class?

PetSerAl,像以前无数次一样,在对这个问题的简短评论中提供了关键指针:

由于您使用 classes,您必须使用 modules 并将它们导入using module 个语句 以便使用它们。

不幸的是,在撰写本文时,using module 仍未在 Get-Help about_Modules 中提及。

具体来说,为了在 class 定义中引用类型 (class),PowerShell 在解析时必须知道该类型.

在您的示例中,为了从 class Car 派生 Tesla,当脚本为 时,PowerShell 必须知道类型 Car parsed, before 执行开始 - 这就是为什么尝试导入Car太迟 ] 通过点源其包含的脚本 (. "$PSScriptRoot\Car.ps1")

PowerShell 通过以下两种方式之一在解析时了解引用类型:

  • 如果类型已经加载到当前 PowerShell 会话

  • 通过 using module 语句引用定义了类型 (class) 的模块(请注意,还有一个 using assembly 语句用于加载类型来自 DLL,以及 using namespace 以启用仅通过名称引用类型)。

    • 请注意,相关的 Import-Module cmdlet 在这种情况下 起作用,因为它在 运行时 执行。

因此,正如 PetSerAl 所建议的那样:

  • 将您的 classes 存储在 module 文件(独立 *.psm1最简单情况下的文件)

  • 然后使用using moduleTesla模块导入Car模块和MyScript.ps1 脚本导入 Tesla 模块,使用 相对于封闭脚本/模块位置 .

    的路径
    • 警告:从 PowerShell Core 6.1.0-preview.4 开始,有一个 bug 要求您使用 \ 作为相对路径中与 using module 的路径分隔符,即使在类 Unix 平台上,您通常会使用 /.
MyScript.ps1
classes\
    Car.psm1    # Note the .psm1 extension
    Tesla.psm1  # Ditto

Car.psm1:

class Car {}

Tesla.psm1:

using module .\Car.psm1

class Tesla : Car {}

MyScript.ps1:

using module .\classes\Tesla.psm1

$tesla = [Tesla]::new()