在PowerShell中为.NET对象定义变量扩展

时间:2014-02-11 07:15:23

标签: variables powershell tostring expansion

快速背景:我是PowerShell的新手,但我是一个精通C#开发者。到目前为止,我对PowerShell的看法很复杂。我爱它有一天,恨它。就在我认为我已经弄明白的时候,我被困了好几个小时试验并且错误一些我认为应该实现的功能但是没有。

我希望PowerShell让我覆盖一个对象的ToString()方法(它所做的),这样当一个对象在双引号字符串中被引用时,它将调用我的自定义ToString方法(它没有)。

示例:

PS C:\> [System.Text.Encoding] | Update-TypeData -Force -MemberType ScriptMethod -MemberName ToString -Value { $this.WebName }

PS C:\> $enc = [System.Text.Encoding]::ASCII

PS C:\> $enc.ToString()  ### This works as expected

us-ascii

PS C:\> "$enc"  ### This calls the object's original ToString() method. 

System.Text.ASCIIEncoding

如何定义.NET对象的变量扩展行为?

2 个答案:

答案 0 :(得分:1)

语言规范没有提及覆盖变量替换的任何内容,因此我认为没有一种确定的方法可以完全按照您的要求进行操作。如果涉及单个类,您可以在C#中对其进行子类化,但对于类层次结构,我能想到的最接近的是在对象周围生成一个具有所需行为的包装器。

$source = @"
using System.Text;
public class MyEncoding
{
    public System.Text.Encoding encoding;
    public MyEncoding()
    {
        this.encoding = System.Text.Encoding.ASCII;
    }

    public MyEncoding(System.Text.Encoding enc)
    {
        this.encoding = enc;
    }
    public override string ToString() { return this.encoding.WebName; }
}
"@
Add-Type -TypeDefinition $Source

然后你可以像这样使用它:

PS C:\scripts> $enc = [MyEncoding][System.Text.Encoding]::ASCII;

PS C:\scripts> "$enc"
us-ascii

PS C:\scripts> $enc = [MyEncoding][System.Text.Encoding]::UTF8;

PS C:\scripts> "$enc"
utf-8

PS C:\scripts> $enc.encoding


BodyName          : utf-8
EncodingName      : Unicode (UTF-8)
HeaderName        : utf-8
WebName           : utf-8
WindowsCodePage   : 1200
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.EncoderReplacementFallback
DecoderFallback   : System.Text.DecoderReplacementFallback
IsReadOnly        : True
CodePage          : 65001

如果您不喜欢额外的.encoding来获取底层对象,您可以将所需的属性添加到包装器中。

答案 1 :(得分:1)

我偶然发现了一个半解决方案,并在Powershell中发现了另一个奇怪的行为。看来,当字符串扩展涉及集合时,将调用ToString()方法的用户定义的ScriptMethod定义,而不是对象的原始ToString()方法。

所以,使用上面的例子,所有必要的是添加一个糟糕的逗号:

PS C:\> [System.Text.Encoding] | Update-TypeData -Force -MemberType ScriptMethod -MemberName ToString -Value { $this.WebName }

PS C:\> $enc = ,[System.Text.Encoding]::ASCII # The unary comma operator creates an array

PS C:\> "$enc"  ### This now works

us-ascii

这对我来说似乎是个错误。

相关问题