仅供学习。
假设我有一个变量,在本例中是一个文本框,如何一次设置多个属性而无需一遍又一遍地输入变量名称。
我自己尝试过一些东西,其中一个由于某种奇怪的原因而起作用。
这个例子有效。 Break 用于缩短循环。
$Textbox | % {
$_.Text = "Hello World"
$_.Background = "Black"
$_.Foreground = "Green"
Break
}
这两个示例不起作用,在这里只是为了看看我尝试过什么。
这有或没有“$_.”,而不是“.”。我用过“=”和“+=”,但都不起作用。
$Textbox.@{
Text = "Hello World"
Background = "Black"
Foreground = "Green"
}
$Textbox.({
$_.Text = "Hello World"
$_.Background = "Black"
$_.Foreground = "Green"
})
可能有更简单的方法,我在谷歌上没有找到任何东西。
您正在寻找的是一种语言构造,例如 VB[Script] 的 With
语句,它允许您在内部为“无对象”属性引用(例如
.Text
)设置隐含上下文一个块。PowerShell 中
没有这样的构造。
您的第一次尝试是 PowerShell 中最接近的模拟,尽管以牺牲性能为代价(尽管这可能并不重要):在管道中,自动变量$_
允许对输入对象进行简洁引用手。
重要:不要在管道内使用break
:它不仅会退出管道,还会退出任何封闭的循环,以及在没有循环的情况下退出封闭脚本。 使用
return
代替。
也就是说,在当前的情况下,只有一个单个输入对象,不需要return
。
:
@{...}
仅用于
哈希表文字。尝试使用此语法作为属性名称会导致语法错误。
(...)
计算所包含的任何单个命令/表达式;
{...}
定义了一个脚本块。
的脚本块(需要&
),当在
字符串上下文中使用时 - 例如此处的属性名称,计算出其在
{
和 之间的文字内容}
,即一个多行字符串,显然not代表
$TextBox
的现有属性的名称,因此总体结果是$null
。
下运行的脚本 - 使用 Set-StrictMode -Version 2
或更高模式 - 会将上述尝试
访问不存在的属性标记为错误。 相比之下,尝试分配
构造对象的上下文中提供了方便的多属性初始化,在 PowerShell 中,您通常也可以通过hashtable初始化器使用casts来实现。
# Cast a hashtable with property name/value pairs to
# [System.Windows.Forms.TextBox], which implicitly constructs
# an instance with the specified property values:
$TextBox = [System.Windows.Forms.TextBox] @{
Text = "Hello World"
Location = [Point]::new(10, 50)
}
需要注意的是,此技术的可用性取决于目标类型是否具有
function Set-Properties(
[parameter(ValueFromPipeline)] $inputObject,
[hashtable] $properties,
[switch] $passThru
) {
process {
Add-Member -InputObject $inputObject -NotePropertyMembers $properties -force
if ([bool]$passThru) { $inputObject }
}
}
用途:
Set-Properties $Textbox @{
Text = "Hello World"
Background = "Black"
Foreground = "Green"
}
$Textbox1, $Textbox2 | Set-Properties -properties @{
Text = "Hello World"
Background = "Black"
Foreground = "Green"
} -passThru | ForEach {
# do something
}
即使类没有无参数构造函数,也可以通过使用 -ArgumentList [Object[]] 和 -Property [IDictionary] 的组合来初始化对象。
Class TestClass
{
[string]$ConstructorProperty
[string]$PublicProperty
[string]$PublicProperty1
# ...
# Note: a constructor is defined.
TestClass([string]$ConstructorProperty) {
$this.ConstructorProperty = $ConstructorProperty
}
}
New-Object TestClass `
-ArgumentList @('c0') `
-Property @{ PublicProperty = 'p0'; PublicProperty1 = 'p1'}