我有一个使用大量委托(delegate)的 .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 脚本 block 返回的是 PSObject 而不是实际的 double 值。我的 .NET API 对 PowerShell 一无所知,我不想添加对 PowerShell DLL 的引用,以便我可以为这个特定场景添加特殊处理。
有没有办法让我的脚本 block 返回实际值类型而不是 PSObjects?或者我的 .NET 库是否有一种与 PowerShell 无关的方式来处理 PSObject?
最佳答案
PowerShell 将在它认为合适的情况下将内容包装在 PSObject 中,在接受任意脚本 block 时没有干净的方法可以避免这种情况。通过一些纪律,您可以编写解包 PSObject 的脚本 block ,例如以下内容可能工作正常:
[MyClass]::DoSomethingWithDouble({ (123.4).PSObject.BaseObject })
如果可能,更好的选择是让您的 api 接受具有更具体返回类型的委托(delegate)。
public static void DoSomethingWithDouble(Func<double> myFunc)
在这种情况下,PowerShell 会将返回值转换为委托(delegate)所期望的类型。当返回类型为 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,但它们是值得理解的选项。
关于powershell - 防止 PowerShell 在 PSObjects 中包装值类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20803345/