Пользовательский Хост PowerShell и Преобразовывающий PSObject назад в базовый тип

Когда хостинг времени выполнения PowerShell является этим возможный преобразовать a PSObject назад в его исходный тип некоторые, как?

Например:

У меня есть cmdlet, который звонит WriteObject и продвигает набор ClassXzy в конвейере. Когда я звоню PowerShell.Invoke от конца хоста вещей я получаю набор PSObjects с a BaseObject свойство. Кастинг BaseObject кому: ClassXyz сбои.

Есть ли какой-либо путь вокруг отображения каждого значения свойства к его соответствующему исходному объекту?
Я предполагаю, что PowerShell делает это так или иначе, поскольку можно передать PSObjects к cmdlets и они переводятся в типы Параметра. Но как?

Я потратил вдоль времени, разорвавшись в блоки PS с Отражателем, но действительно не закрепил, как это волшебство происходит.

Какие-либо идеи?

Править: Я забыл одну очень важную деталь. PSObject то, что я тестирую против, является удаленным объектом таким образом BaseObject тип называют Deserialized.ClassXyz. Поэтому я вижу такое странное поведение.

12
задан ΩmegaMan 27 April 2017 в 23:38
поделиться

2 ответа

Кит ответил на ваш вопрос до того, как вы упомянули процесс десериализации.

Что касается сериализации/десериализации

Я сомневаюсь, что можно получить оригинальный объект. Я не знаю, какой тип сериализации использует PowerShell, но если рассматривать простую Xml сериализацию, то можно понять, что вы можете сериализовать только свойства и ничего больше.
Вы не можете сериализовать тела методов.
Вы не можете сериализовать всех подписчиков его событий (или, возможно, в некоторых случаях это возможно, но я не такой уж эксперт в .NET).
А поскольку тип (как в моем примере) может быть недоступен (например, сборка присутствует только на удаленном компьютере), всю информацию о типе придется передавать.

Речь идет не только о типе, но и обо всей иерархии наследования и интерфейсах, которые реализует объект. Их тоже придется как-то сериализовать.

Просто попробуйте этот пример:

$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(), уже не отражает изменение даты - это замороженное значение.

Я не вижу никакой разницы между сериализацией для remoting, сериализацией в clixml (через Export-CliXml) или при Receive-Job при рассмотрении того, что я написал выше, поэтому я думаю, что в обоих случаях это невозможно.

10
ответ дан 2 December 2019 в 21:23
поделиться

Вы можете получить доступ либо к свойству BaseObject на PSObject (которое обходит каждый PSObject, пока не достигнет реального базового объекта), либо к ImmediateBaseObject, которое просто захватывает следующий объект в цепочке.

3
ответ дан 2 December 2019 в 21:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: