托管 PowerShell 运行时时,是否可以通过某种方式将 PSObject
转换回其原始类型?
例如:
我有一个调用 WriteObject
并在管道中推送 ClassXzy 集合的 cmdlet。当我从事物的主机端调用 PowerShell.Invoke
时,我检索了一个具有 BaseObject
属性的 PSObject
集合。将 BaseObject
转换为 ClassXyz
失败。
有没有办法将每个属性值映射到其对应的原始对象?
我假设 PowerShell 以某种方式执行此操作,因为您可以将 PSObject
传递给 cmdlet,它们会被转换为参数类型。但是怎么办?
我花了很多时间使用 Reflector 研究 PS 组件,但还没有真正弄清楚这种魔法是如何发生的。
有什么想法吗?
编辑:我忘记了一个非常重要的细节。我正在测试的 PSObject
是一个远程对象,因此 BaseObject
类型被命名为 Deserialized.ClassXyz
。这就是为什么我看到这种奇怪的行为。
最佳答案
在你提到反序列化过程之前,Keith 已经回答了你的问题。
至于序列化/反序列化
我怀疑是否有可能获得原始对象。我不知道 PowerShell 使用什么类型的序列化,但如果您考虑简单的 Xml 序列化,您就会意识到您可以序列化仅属性,而不能序列化其他任何内容。
你不能序列化它的方法体。
你不能序列化所有它的事件订阅者(或者在某些情况下它是可能的,但我不是这样的 .NET 专家)。
并且由于类型(如我的示例)可能不可用(例如,程序集仅存在于远程计算机上),因此需要传输所有类型信息。
它不仅与类型有关,还与对象实现的所有继承层次结构和接口(interface)有关。它们也会以某种方式被序列化。
试试这个例子:
$deserialized = Start-Job {
Add-Type -TypeDefinition @"
public class Parent {
public override string ToString() { return "overriden parent"; }
public int IntParent { get { return 1; } }
}
public class TestClass : Parent
{
public string GString() { return "this is a test string"; }
public override string ToString() { return "overriden tostring" + System.DateTime.Now.ToString(); }
public int IntProp { get { return 3451; } }
}
"@
New-Object TestClass
} | Wait-Job | Receive-Job
$deserialized.ToString()
$deserialized | gm -for
你会看到,PowerShell
- 扁平化继承层次结构。
- 仅“实现”属性
- 并且因为它知道
ToString()
的值,所以它也可以添加该方法的结果。但是正如您所见,从ToString()
返回的信息不再反射(reflect)日期更改 - 它是卡住值。
在考虑我所写的内容时,我看不出远程序列化、clixml 序列化(通过 Export-CliXml
)或 Receive-Job
之间有什么区别以上,所以我认为在这两种情况下都是不可能的。
关于c# - 自定义 PowerShell 主机并将 PSObject 转换回基本类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2330659/