Усилители типа PowerShell: PSObject vs PSCustomObject

В PowerShell v3.0 PSCustomObject. Это как PSObject, но лучше. Среди других улучшений (например, сохранение порядка сохранения) упрощается создание объекта из хэш-таблицы:

[PSCustomObject]@{one=1; two=2;}

Теперь кажется очевидным, что это утверждение:

[System.Management.Automation.PSCustomObject]@{one=1; two=2;}

будет работать одинаково, потому что PSCustomObject является "псевдонимом" для полного пространства имен + имя класса. Вместо этого я получаю сообщение об ошибке:

Невозможно преобразовать значение "System.Collections.Hashtable" типа "System.Collections.Hashtable", чтобы ввести "System.Management.Automation.PSCustomObject".

Я перечислил ускорители для обоих типов объектов:

[accelerators]::get.GetEnumerator() | where key -Like ps*object

    Key            Value
    ---            -----
    psobject       System.Management.Automation.PSObject
    pscustomobject System.Management.Automation.PSObject

и обнаружил, что оба ссылаются на один и тот же класс PSObject - это означает, что использование ускорителей может сделать кучу других вещей, чем просто сделать код короче.

Мои вопросы по этой проблеме:

  • Есть ли у вас интересные примеры различий между использованием ускорителя и использованием полного имени типа?
  • Следует ли избегать использования полного имени типа всякий раз, когда ускоритель доступен в качестве общей лучшей практики?
  • Как проверить, может быть, использовать отражение, если ускоритель делает другие вещи, а не просто указывает на базовый класс?

Ответ 1

Глядя на статические методы:

PS C:\> [PSCustomObject] | gm -Static -MemberType Method



   TypeName: System.Management.Automation.PSObject

Name            MemberType Definition                                                        
----            ---------- ----------                                                        
AsPSObject      Method     static psobject AsPSObject(System.Object obj)                     
Equals          Method     static bool Equals(System.Object objA, System.Object objB)        
new             Method     psobject new(), psobject new(System.Object obj)                   
ReferenceEquals Method     static bool ReferenceEquals(System.Object objA, System.Object o...



PS C:\> [System.Management.Automation.PSCustomObject] | gm -Static -MemberType Method



   TypeName: System.Management.Automation.PSCustomObject

Name            MemberType Definition                                                        
----            ---------- ----------                                                        
Equals          Method     static bool Equals(System.Object objA, System.Object objB)        
ReferenceEquals Method     static bool ReferenceEquals(System.Object objA, System.Object o...

У ускорителя типа есть несколько новых статических методов. Я подозреваю, что он использует один из них в качестве конструктора.

Ответ 2

[PSObject] и [PSCustomObject] - это псевдонимы для того же типа - System.Management.Automation.PSObject. Я не могу сказать, что для этого есть веская причина, но это, по крайней мере, наводит на размышления о двух разных целях и, возможно, об этой причине.

System.Management.Automation.PSObject используется для обертывания объектов. Он был представлен для обеспечения общего отражения api над любым объектом, который PowerShell обертывает -.Net, WMI, COM, ADSI или простые пакеты свойств.

System.Management.Automation.PSCustomObject - это просто деталь реализации. Когда вы создаете PSObject, PSObject должен что-то обернуть. Для пакетов свойств объект, обернутый, - System.Management.Automation.PSCustomObject.SelfInstance(внутренний член.) Этот экземпляр скрыт от обычного использования PowerShell, единственный способ его наблюдения - с отражением.

Пакеты свойств создаются несколькими способами в PowerShell:

$o1 = [pscustomobject]@{Prop1 = 42}
$o2 = new-object psobject -Property @{Prop1 = 42 }

Оба $o1 и $o2 выше будут экземпляром PSObject, а PSObject будет обернуть PSCustomObject.SelfInstance. PSCustomObject.SelfInstance используется внутри PowerShell, чтобы рассказать о различии между простой сумкой свойств и обернуть любой другой объект.