防止 PowerShell 将值类型包装在 PSObject 中

2024-04-11

我有一个使用大量委托的 .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 而不是实际的双精度值。我的 .NET API 对 PowerShell 一无所知,并且我不想添加对 PowerShell DLL 的引用,这样我就可以为这个特定场景添加特殊处理。

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


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# 关键字dynamic,例如:

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

防止 PowerShell 将值类型包装在 PSObject 中 的相关文章

随机推荐