gpt4 book ai didi

具有单参数构造函数的 PowerShell 类不验证数据类型

转载 作者:行者123 更新时间:2023-12-05 00:43:13 35 4
gpt4 key购买 nike

我正在设计一个模块并使用类对我的参数进行类型验证。我注意到,在尝试对输入参数进行类型验证时,具有单参数构造函数的类似乎充当了类型加速器,而不是验证数据类型。

例子:

Class stack {
$a
$b
stack($inp) {
$this.a = $inp
$this.b = 'anything'
}
}

function foo {
Param(
[stack]$bar
)
$bar
}

PS>foo -bar 'hello'
a b
- -
hello anything

$bar 已被类型加速到堆栈的实例化中。

将其与具有带 2 个参数的构造函数的同一类进行比较:

Class stack {
$a
$b
stack($inp,$inp2) {
$this.a = $inp
$this.b = 'anything'
}
}

function foo {
Param(
[stack]$bar
)
$bar
}

PS>foo -bar 'hello'
foo : Cannot process argument transformation on parameter 'bar'. Cannot convert the "hello" value of type "System.String" to type "stack".

现在类类型正在正确验证输入参数。

我第一次看到这个是在 Windows 10 的 PS5.1 上,但我只是在我的私有(private)笔记本电脑上用 pwsh 7.2.1 试了一下,似乎是一样的。

是否有解决此问题的方法?是bug吗?

编辑:嗯,经过进一步测试,我意识到如果我为带有 2 个参数的构造函数提供 2 个输入参数,例如 foo -bar 'hello' 'world',也会发生这种情况。所以我想这可能是故意的,我做错了什么。我可以使用类来验证输入参数的数据类型吗?怎么样?

最佳答案

您所看到的与 type accelerators 无关,它们只是 .NET 类型名称的 短别名;例如,[regex][System.Text.RegularExpressions.Regex] 的缩写。

相反,您会看到 PowerShell 灵活的自动类型转换,其中包括翻译 casts(例如 [stack] .. .)和类型约束(同上,在赋值上下文中或在param(...) block 内)到构造函数调用::Parse() 调用,如 this answer 中所述.

  • 因此,假设您的 [stack] 类有一个(非类型约束的)single-argument 构造函数,类似于 [stack] 'hello ' 会自动转换为 [stack]::new('hello'),即构造函数调用 - 当您传递 argument 时也会发生这种情况'hello' 到一个类型为 [stack]parameter

我建议不要与这些自动转化作斗争,因为它们通常很有帮助。

在极少数情况下,您确实需要确保传递的参数的类型完全是参数声明中指定的类型(或 派生的 em> type),您可以使用以下技术(以 type [datetime] 为例,其完整的 .NET 类型名称为 System.DateTime) :

function Foo {

param(
# Ensure that whatever argument is passed is already of type [datetime]
[PSTypeName('System.DateTime')]
$Bar
)

"[$Bar]"
}

感谢您发现此用例的 [PSTypeName()] 属性。

  • 如果没有 [PSTypeName(...)] 属性,像 Foo 1/1/1970 这样的调用会工作,因为 string '1/1/1970' 会被 PowerShell 自动转换为 [datetime]

  • [PSTypeName(...)]属性,只接受一个实际的 [datetime] 参数(或者,对于可以子类化的类型,从指定的 派生 类型的实例类型)。

    • 重要:指定目标类型的完整 .NET类型名称(例如'System.DateTime' 而不仅仅是 'datetime') 来明确定位它。

      • 但是,对于 PowerShell 自定义 classes,它们的名称 全名(它们不在 命名空间内 em>),因此对于您的 [stack] 类,属性将是 [PSTypeName('stack')]
    • 接受任何类型名称,即使它不引用现有的 .NET 类型或自定义 class任何此类不存在的类型都需要一个参数来使用匹配的虚拟 ETS (PowerShell's Extended Type System)输入名称。事实上,支持此类虚拟类型名称是该属性的主要目的[1] 例如,如果 [PSTypeName('如果使用了 Bar')],您可以传递一个 自定义对象,其 ETS 类型名称为 Bar,如下所示:
      [pscustomobject] @{ PSTypeName = 'Bar'; Baz = 'quux' }


[1] 引用链接文档(强调添加):“此属性用于限制参数的类型名称,当类型超出 .NET 类型系统时。”

关于具有单参数构造函数的 PowerShell 类不验证数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70703731/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com