【问题标题】:How can I change how PowerShell displays a property of my custom type?如何更改 PowerShell 显示自定义类型的属性的方式?
【发布时间】:2013-07-15 09:45:25
【问题描述】:

在 PowerShell 中,当我在表格(或列表)中查看我的自定义 MyStuff.Document 类型时,它的 Content 属性不会使用我的 ToString() 函数显示。相反,PowerShell 会迭代集合并显示其中的项目。我希望它使用我的ToString() 函数。

例子:

$doc = New-Object MyStuff.Document
$doc.Content.Add("Segment 1")
$doc.Content.Add("Segment 2")

$doc | select Content

目前显示:

Content
-------
{Segment 1, Segment 2}

当我希望它显示时:

Content
-------
something custom

“自定义的东西”是我的 ToString() 函数的输出。

我已经深入研究了*.format.ps1xml 文件,我认为这些文件是我需要使用的,但我不知道如何做我想做的事。 Update-TypeData 看起来也很有希望,但我也没有运气。

任何帮助将不胜感激。

这些是我正在使用的自定义类型:

namespace MyStuff
{
    public class Document
    {
        public string Name { get; set; }
        public FormattedTextBlock Content { get; set; }
    }

    public class FormattedTextBlock : ICollection<FormattedTextSegment>
    {
        public void Add(string text)
        {
            this.Add(new FormattedTextSegment() { Text = text });
        }

        // ... ICollection implementation clipped

        public override string ToString()
        {
            // ... reality is more complex
            return "something custom";
        }
    }

    public class FormattedTextSegment
    {
        public string Text { get; set; }

        public override string ToString()
        {
            return Text;
        }
    }
}

更新

需要明确的是,我知道像 $doc | select @{ Expression = { $_.Content.ToString() }; Label = "Content" } 这样的策略。我正在寻找告诉 PowerShell 默认情况下如何格式化我的属性。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    这里有两个问题。

    首先,当您执行Select -Property Content 时,您真正告诉powershell 的是“请给我一个具有所选属性的新对象以供进一步处理”。这有效,因此您可以继续使用管道。

    其次,如果管道结束,并且没有其他地方可以放置数据,那么格式化魔法就会发生。例如$doc | Select Content | format-table 将给出您现在看到的显示。然而,format-table 收到的是一个 PSCustomObject,其动态类型称为Selected.MyStuff.Document。您可以为此创建魔术类型信息,但由于 Selected.MyStuff.Document 是动态的,因此您的格式信息很可能不正确。

    或者,如果您只有一个 $doc,或者如果您有一组 MyStuff.Document 对象 $doc | % { $_.Content.ToString() },您可以执行类似 $doc.Content.ToString() 的操作,而不是 select。这些都失去了标题。

    如果您想格式化整个 MyStuff.Document 对象(无 Select):$doc | format-table,您可以在 format.ps1xml 文件中使用以下内容,奇迹发生了。注意,我只为 MyStuff.Document 类型实现了 Format-Table。您应该能够为您的 FormattedTextBlock 做类似的事情。

    <?xml version="1.0" encoding="utf-8" ?>
    <Configuration>
        <ViewDefinitions>
            <View>
                <Name>MyStuff.Document</Name>
                <ViewSelectedBy>
                    <TypeName>MyStuff.Document</TypeName>
                </ViewSelectedBy>
                <TableControl>
                    <TableHeaders>
                        <TableColumnHeader>
                            <Label>Name</Label>
                        </TableColumnHeader>
                        <TableColumnHeader>
                            <Label>Content</Label>
                        </TableColumnHeader>
                    </TableHeaders>
                    <TableRowEntries>
                        <TableRowEntry>
                            <TableColumnItems>
                                <TableColumnItem>
                                    <Alignment>Left</Alignment>
                                    <PropertyName>Name</PropertyName>
                                </TableColumnItem>
                                <TableColumnItem>
                                    <Alignment>Left</Alignment>
                                    <ScriptBlock>$_.Content.ToString()</ScriptBlock> 
                                </TableColumnItem>
                            </TableColumnItems>
                        </TableRowEntry>
                    </TableRowEntries>
                </TableControl>
            </View>
        </ViewDefinitions>
    </Configuration>
    

    【讨论】:

    • 谢谢!这真的很接近理想。我希望 PowerShell 有办法说“这种类型的默认字符串表示 (MyStuff.FormattedTextBlock) 应该是 { $_.ToString() }”。不过这已经很接近了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    相关资源
    最近更新 更多