阻止PowerShell在PSObjects中包装值类型

时间:2013-12-27 15:36:43

标签: powershell return-value psobject

我有一个使用很多委托的.NET API。我的API有几种类似于以下的方法:

public static class MyClass
{
    public static void DoSomethingWithString(Func<object> myFunc)
    {
        string myStringValue = myFunc().ToString();
        Console.WriteLine(myStringValue);
    }

    public static void DoSomethingWithDouble(Func<object> myFunc)
    {
        object unparsedValue = myFunc();
        double parsedValue = Convert.ToDouble(unparsedValue);
        Console.WriteLine(parsedValue);
    }
}

现在在PowerShell中我有以下内容:

[MyClass]::DoSomethingWithString({ "Hello" }); # No error here
[MyClass]::DoSomethingWithDouble({ 123.4 });   # InvalidCastException - can't convert a PSObject to double

问题是我的PowerShell脚本块返回的是PSObject而不是实际的double值。我的.NET API对PowerShell一无所知,我不想添加对PowerShell DLL的引用,因此我可以为这个特定场景添加特殊处理。

有没有办法让我的脚本块返回实际值类型而不是PSObjects?或者我的.NET库是否有与PowerShell无关的方式来处理PSObjects?

1 个答案:

答案 0 :(得分:3)

PowerShell会根据需要将内容包装在PSObject中,在接受任意脚本块时没有简洁的方法可以避免这种情况。通过一些规则,您可以编写解包PSObject的脚本块,例如以下可能正常工作:

[MyClass]::DoSomethingWithDouble({ (123.4).PSObject.BaseObject })

如果可能的话,更好的选择是让你的api接受一个具有更具体的返回类型的委托。

public static void DoSomethingWithDouble(Func<double> myFunc)

在这种情况下,PowerShell会将返回值转换为委托所期望的类型。当返回类型是PSObject时,PowerShell知道PSObject通常会转换为对象,因此它不会解包,但如果返回类型几乎是其他任何东西,则PowerShell会通过展开PSObject来强制执行转换。

为了完整性,如果您使用PowerShell V3,另一个选项是使用C#关键字动态,例如:

public static void DoSomethingWithDouble(Func<object> myFunc)
{
    dynamic unparsedValue = myFunc();
    double parsedValue = (double)(unparsedValue);
    Console.WriteLine(parsedValue);
}

当unparsedValue是PSObject时,即使您没有在C#代码中引用任何PowerShell程序集,PowerShell也会在第二行执行转换为double。

请注意,最后两个选项可能不适合您的真实API,但它们是值得理解的选项。