PowerShell自定义类实现未赋值属性隐藏及-Force显示需求
实现动态属性可见性的Package类
纯PowerShell类无法直接实现「未赋值属性默认隐藏、赋值后显示、-Force强制显示」的逻辑,因此用C#通过Add-Type来实现,同时保留字符串引用返回Name的行为。
完整代码
Add-Type @" using System; using System.Collections.Generic; using System.ComponentModel; using System.Management.Automation; public class Package : ICustomTypeDescriptor { public string Name { get; set; } public string Latest { get; set; } public string Prerelease { get; set; } public override string ToString() { return this.Name; } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return GetProperties(false); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { bool force = false; foreach (Attribute attr in attributes) { if (attr is PSPropertyInfoAttribute psAttr && psAttr.Force) { force = true; break; } } return GetProperties(force); } private PropertyDescriptorCollection GetProperties(bool force) { var props = new List<PropertyDescriptor>(); props.Add(TypeDescriptor.GetProperties(this)["Name"]); props.Add(TypeDescriptor.GetProperties(this)["Latest"]); if (force || Prerelease != null) { props.Add(TypeDescriptor.GetProperties(this)["Prerelease"]); } return new PropertyDescriptorCollection(props.ToArray()); } // 以下为ICustomTypeDescriptor接口的默认实现,无需修改 AttributeCollection ICustomTypeDescriptor.GetAttributes() => TypeDescriptor.GetAttributes(this); string ICustomTypeDescriptor.GetClassName() => TypeDescriptor.GetClassName(this); string ICustomTypeDescriptor.GetComponentName() => TypeDescriptor.GetComponentName(this); TypeConverter ICustomTypeDescriptor.GetConverter() => TypeDescriptor.GetConverter(this); EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this); PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this); object ICustomTypeDescriptor.GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType); EventDescriptorCollection ICustomTypeDescriptor.GetEvents() => TypeDescriptor.GetEvents(this); EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) => TypeDescriptor.GetEvents(this, attributes); object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) => this; } "@ # 测试示例 $test = [Package]::new() $test.Name = 'Example' $test.Latest = '0.1' Write-Host "=== 默认输出(Prerelease未赋值,隐藏) ===" $test | Format-Table Write-Host "`n=== 赋值Prerelease后输出(显示属性) ===" $test.Prerelease = '0.1-beta' $test | Format-Table Write-Host "`n=== -Force强制输出(无论赋值状态都显示) ===" $test.Prerelease = $null $test | Format-Table -Force Write-Host "`n=== 字符串引用输出(返回Name) ===" "$test"
逻辑说明
- 通过实现
ICustomTypeDescriptor接口,接管属性枚举逻辑:- 默认模式下,仅返回
Name和Latest属性;当Prerelease被赋值(非null)时,才将其加入属性列表 - 检测到
-Force参数时(通过PSPropertyInfoAttribute.Force标识),强制包含Prerelease属性,无论是否赋值
- 默认模式下,仅返回
- 重写
ToString()方法,确保字符串插值(如"$test")时返回Name值 - 其余接口方法使用默认实现,保证对象的常规行为不受影响
内容的提问来源于stack exchange,提问作者Maybe
相关产品推荐
相关产品推荐

