提问人:Vopel 提问时间:7/29/2023 最后编辑:Vopel 更新时间:7/29/2023 访问量:73
添加隐藏的属性,除非它有值
Adding a property that is hidden unless it has a value
问:
我正在添加一个与软件包相关的类。以下是用于此问题的准系统版本:
class Package {
$Name; $Latest; $Prerelease
[string]ToString(){ return $this.Name }
}
$test = [Package]::new()
$test.Name = 'Example'
$test.Latest = '0.1'
当我执行命令 or 时,我希望隐藏 $Prerelease 属性,除非它被赋予一个值。$test
$test | Format-Table
而且,虽然下一部分不是必需的,但我也希望在使用类似的东西时公开它。Format-Table -Force
我发誓我目睹了 PowerShell 中的其他对象的类似行为,但我无法回忆起它们是什么。如果这对于使用纯 PowerShell 制作的对象不可行,我不介意通过 .Add-Type
附言关于建议替代方案,请记住,我想引用对象来输出 $Name 属性,就像它在我上面发布的类中所做的那样,例如"$test"
答:
2赞
Mathias R. Jessen
7/29/2023
#1
正如注释中提到的,在有条件地将属性添加到目标哈希表/字典后,只需使用表达式即可更容易实现。[PSCustomObject]
然后,可以将方法的重写添加到生成的对象中:ToString()
function New-VopelPackage {
param(
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$Latest,
[Parameter(Mandatory = $false)]
[switch]$Prerelease
)
# Collect the mandatory properties
$newPackageProperties = [ordered]@{
Name = $Name
Latest = $Latest
}
# Conditionally add the optional one
if ($PSBoundParameters.ContainsKey('Prerelease')) {
$newPackageProperties['Prerelease'] = $Prerelease.IsPresent
}
# Create the object
$package = [PSCustomObject]$newPackageProperties
# ... and override ToString()
$toStringMemberParams = @{
Name = 'ToString'
MemberType = 'ScriptMethod'
Value = { return $this.Name }
Force = $true
PassThru = $true
}
return $package |Add-Member @toStringMemberParams
}
现在,您可以使用以下行为创建包对象:
PS ~> $package = New-VopelPackage Example 0.1
PS ~> $package
Name Latest
---- ------
Example 0.1
PS ~> "$package"
Example
PS ~> $prereleasePackage = New-VopelPackage Example 0.1 -Prerelease
PS ~> $prereleasePackage
Name Latest Prerelease
---- ------ ----------
Example 0.1 True
PS ~> "$prereleasePackage"
Example
评论
0赞
Vopel
7/29/2023
谢谢。它唯一缺少的是另一个命令以某种方式识别它正在处理的对象无疑是“VopelPackage”。有没有办法向它添加一个可以检查的隐藏属性,或者类似的东西?
0赞
Vopel
7/29/2023
我刚刚发现了 PSTypeName,它应该可以满足我的需求。感谢您的帮助。
0赞
Vopel
8/9/2023
所以,我一直在使用这个解决方案,但我并不完全满意。PSTypeName 在执行管道传输到 Select-Object 等操作时往往会掉落,这会搞砸验证。我认为实际上有一种方法可以做我想做的事,但它需要 C# 代码和比我更多的专业知识。我认为关键是扩展“INotifyPropertyChanged”类,这是我第一次在这里读到的。我添加了 OnPropertyChanged 以确保它在 PowerShell 中触发,并且确实如此。Console.WriteLine("test");
0赞
Vopel
8/9/2023
(续)因此,我使用它的想法是将类属性与 System.Automation 一起使用,然后,每当第一次修改其中一个属性时,使用 AddMember 添加一个新的 ScriptProperty,该属性用作它的 getter,名称将是属性名称加上末尾的空格(因为 PowerShell 允许这样做)。如果您能提供您的专业知识,我将不胜感激。[HiddenAttribute]
0赞
Mathias R. Jessen
8/9/2023
我不确定我这里有足够的上下文,也许你想问另一个问题?请具体说明您要实现的目标
评论
Prerelease
"$test"