我有一个使用很多委托的.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?
答案 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,但它们是值得理解的选项。