2

我有一个使用大量委托的 .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 的引用,以便为这个特定场景添加特殊处理。

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

4

1 回答 1

4

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 时,PowerShell 将在第二行执行从到 double 的转换,即使您没有在 C# 代码中引用任何 PowerShell 程序集。

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

于 2013-12-27T17:52:51.537 回答