Bagikan melalui


Semua yang ingin Anda ketahui tentang PSCustomObject

PSCustomObject adalah alat yang bagus untuk ditambahkan ke sabuk alat PowerShell Anda. Mari kita mulai dengan dasar-dasar dan melanjutkan ke fitur yang lebih canggih. Ide di balik penggunaan PSCustomObject adalah memiliki cara sederhana untuk membuat data terstruktur. Lihat contoh pertama dan Anda akan memiliki gambaran yang lebih baik tentang apa artinya itu.

Nota

Versi asli artikel ini muncul di blog yang ditulis oleh @KevinMarquette. Tim PowerShell berterima kasih kepada Kevin karena telah membagikan konten ini kepada kami. Silakan lihat blognya di PowerShellExplained.com.

Membuat PSCustomObject

Saya suka menggunakan [pscustomobject] di PowerShell. Membuat objek yang dapat digunakan tidak pernah lebih mudah. Karena itu, saya akan melewati semua cara lain yang dapat Anda buat objek tetapi saya perlu menyebutkan bahwa sebagian besar contoh ini adalah PowerShell v3.0 dan yang lebih baru.

$myObject = [pscustomobject]@{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}

Metode ini bekerja dengan baik untuk saya karena saya menggunakan hashtable untuk hampir semuanya. Ada kalanya saya ingin PowerShell memperlakukan hashtabel lebih seperti objek. Tempat pertama yang Anda perhatikan perbedaannya adalah ketika Anda ingin menggunakan Format-Table atau Export-Csv dan Anda menyadari bahwa hashtable hanyalah kumpulan pasangan kunci/nilai.

Anda kemudian dapat mengakses dan menggunakan nilai seperti objek normal.

$myObject.Name

Mengonversi sebuah tabel hash

Sementara saya sedang dalam topik, tahukah Anda bahwa Anda bisa melakukan ini:

$myHashtable = @{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}
$myObject = [pscustomobject]$myHashtable

Saya lebih suka membuat objek dari awal, tetapi ada kalanya Anda harus bekerja dengan sebuah hashtable terlebih dahulu. Contoh ini berfungsi karena konstruktor (fungsi pembangun) menggunakan hashtable untuk properti objek. Salah satu catatan penting adalah bahwa meskipun metode ini berfungsi, metode ini tidak sama persis. Perbedaan terbesar adalah urutan properti tidak dipertahankan.

Jika Anda ingin mempertahankan urutan, lihat tabel hash yang diurutkan .

Pendekatan warisan

Anda mungkin telah melihat orang menggunakan New-Object untuk membuat objek kustom.

$myHashtable = @{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}

$myObject = New-Object -TypeName psobject -Property $myHashtable

Cara ini cukup lambat tetapi mungkin merupakan opsi terbaik Anda pada versi awal PowerShell.

Menyimpan ke file

Saya menemukan cara terbaik untuk menyimpan hashtable ke file adalah dengan menyimpannya sebagai JSON. Anda dapat mengimpornya kembali ke [pscustomobject]

$myObject | ConvertTo-Json -Depth 1 | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json

Saya membahas lebih banyak cara untuk menyimpan objek ke file di artikel saya di Banyak cara untuk membaca dan menulis ke file.

Bekerja dengan properti

Menambahkan properti

Anda masih dapat menambahkan properti baru ke PSCustomObject Anda dengan Add-Member.

$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'

$myObject.ID

Hapus properti

Anda juga dapat menghapus properti dari objek.

$myObject.psobject.Properties.Remove('ID')

.psobject adalah anggota intrinsik yang memberi Anda akses ke metadata objek dasar. Untuk informasi selengkapnya tentang anggota intrinsik, lihat about_Intrinsic_Members.

Menghitung nama properti

Terkadang Anda memerlukan daftar semua nama properti pada objek.

$myObject | Get-Member -MemberType NoteProperty | select -ExpandProperty Name

Kita bisa mendapatkan daftar yang sama ini dari properti psobject juga.

$myobject.psobject.Properties.Name

Nota

Get-Member mengembalikan properti dalam urutan alfabet. Menggunakan operator akses anggota untuk menghitung nama properti mengembalikan properti dalam urutan yang ditentukan pada objek.

Mengakses properti secara dinamis

Saya sudah menyebutkan bahwa Anda dapat mengakses nilai properti secara langsung.

$myObject.Name

Anda dapat menggunakan string sebagai nama properti, dan tetap akan berfungsi.

$myObject.'Name'

Kita dapat mengambil satu langkah lagi ini dan menggunakan variabel untuk nama properti.

$property = 'Name'
$myObject.$property

Aku tahu itu terlihat aneh, tapi berhasil.

Mengonversi PSCustomObject menjadi hashtable

Untuk melanjutkan dari bagian terakhir, Anda dapat secara dinamis menelusuri properti dan membuat hashtable dari properti tersebut.

$hashtable = @{}
foreach( $property in $myobject.psobject.Properties.Name )
{
    $hashtable[$property] = $myObject.$property
}

Pengujian sifat-sifat

Jika Anda perlu tahu apakah properti ada, Anda bisa memeriksa apakah properti tersebut memiliki nilai.

if( $null -ne $myObject.ID )

Tetapi jika nilainya bisa $null Anda dapat memeriksa apakah nilai tersebut ada dengan memeriksa psobject.Properties untuk nilai tersebut.

if( $myobject.psobject.Properties.Match('ID').Count )

Menambahkan metode objek

Jika Anda perlu menambahkan metode skrip ke objek, Anda dapat melakukannya dengan Add-Member dan ScriptBlock. Anda harus menggunakan variabel otomatis this mereferensikan objek saat ini. Berikut adalah scriptblock untuk mengubah objek menjadi tabel hash. (kode yang sama membentuk contoh terakhir)

$ScriptBlock = {
    $hashtable = @{}
    foreach( $property in $this.psobject.Properties.Name )
    {
        $hashtable[$property] = $this.$property
    }
    return $hashtable
}

Kemudian kita menambahkannya ke objek kita sebagai properti skrip.

$memberParam = @{
    MemberType = "ScriptMethod"
    InputObject = $myobject
    Name = "ToHashtable"
    Value = $scriptBlock
}
Add-Member @memberParam

Kemudian kita dapat memanggil fungsi kita seperti ini:

$myObject.ToHashtable()

Jenis objek vs Nilai

Objek dan jenis nilai tidak menangani penetapan variabel dengan cara yang sama. Jika Anda menetapkan jenis nilai satu sama lain, hanya nilainya yang akan disalin ke variabel baru.

$first = 1
$second = $first
$second = 2

Dalam hal ini, $first adalah 1 dan $second adalah 2.

Variabel objek menyimpan referensi ke objek aktual. Saat Anda menetapkan satu objek ke variabel baru, objek tersebut masih mereferensikan objek yang sama.

$third = [pscustomobject]@{Key=3}
$fourth = $third
$fourth.Key = 4

Karena $third dan $fourth mereferensikan instans objek yang sama, baik $third.key maupun $fourth.Key adalah 4.

psobject. Copy()

Jika Anda memerlukan salinan objek yang benar, Anda dapat mengkloningnya.

$third = [pscustomobject]@{Key=3}
$fourth = $third.psobject.Copy()
$fourth.Key = 4

Mengklon membuat salinan dangkal dari objek. Sekarang, mereka memiliki contoh kejadian yang berbeda dan $third.key adalah 3 dan $fourth.Key adalah 4 dalam contoh ini.

Saya menyebutnya salinan dangkal karena jika Anda memiliki objek berlapis (objek dengan properti berisi objek lain), hanya nilai tingkat atas yang disalin. Objek anak akan merujuk satu sama lain.

PSTypeName untuk jenis objek kustom

Sekarang setelah kita memiliki objek, ada beberapa hal lagi yang dapat kita lakukan dengannya yang mungkin tidak begitu jelas. Langkah pertama yang perlu kita lakukan adalah memberikan PSTypeNamepadanya. Ini adalah cara paling umum saya melihat orang melakukannya:

$myObject.psobject.TypeNames.Insert(0,"My.Object")

Saya baru-baru ini menemukan cara lain untuk melakukan ini dari Redditor u/markekraus. Dia berbicara tentang pendekatan ini yang memungkinkan Anda menentukannya secara langsung.

$myObject = [pscustomobject]@{
    PSTypeName = 'My.Object'
    Name       = 'Kevin'
    Language   = 'PowerShell'
    State      = 'Texas'
}

Saya suka betapa cocoknya ini dengan bahasa. Sekarang kita memiliki objek dengan nama jenis yang tepat, kita dapat melakukan beberapa hal lagi.

Nota

Anda juga dapat membuat jenis PowerShell kustom menggunakan kelas PowerShell. Untuk informasi selengkapnya, lihat Ikhtisar Kelas PowerShell.

Menggunakan DefaultPropertySet (jalan panjang)

PowerShell memutuskan properti apa yang akan ditampilkan secara default. Banyak perintah asli memiliki file pemformatan .ps1xml yang menangani semua tugas rumit. Dari posting ini oleh Boe Prox, ada cara lain bagi kita untuk melakukan ini pada objek kustom kita dengan hanya menggunakan PowerShell. Kita bisa mengatur MemberSet untuk digunakan.

$defaultDisplaySet = 'Name','Language'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$MyObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers

Sekarang ketika objek saya jatuh pada antarmuka shell, itu hanya akan menampilkan properti-properti tersebut secara default.

Update-TypeData dengan DefaultPropertySet

Ini bagus tetapi baru-baru ini saya melihat cara yang lebih baik menggunakan Update-TypeData untuk menentukan properti default.

$TypeData = @{
    TypeName = 'My.Object'
    DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData

Itu cukup sederhana sehingga saya hampir bisa mengingatnya jika saya tidak memiliki posting ini sebagai referensi cepat. Sekarang saya dapat dengan mudah membuat objek dengan banyak properti dan tetap memberikan tampilan bersih yang bagus saat melihatnya dari shell. Jika saya perlu mengakses atau melihat properti lain tersebut, properti tersebut masih ada.

$myObject | Format-List *

Update-TypeData dengan ScriptProperty

Sesuatu yang saya pelajari dari video itu adalah cara membuat properti skrip untuk objek Anda. Ini akan menjadi waktu yang tepat untuk menunjukkan bahwa ini juga berfungsi untuk objek yang ada.

$TypeData = @{
    TypeName = 'My.Object'
    MemberType = 'ScriptProperty'
    MemberName = 'UpperCaseName'
    Value = {$this.Name.ToUpper()}
}
Update-TypeData @TypeData

Anda dapat melakukan ini sebelum objek Anda dibuat atau setelahnya dan itu akan tetap berfungsi. Inilah yang membuat ini berbeda dari menggunakan Add-Member dengan properti skrip. Ketika Anda menggunakan Add-Member dengan cara yang telah saya sebutkan sebelumnya, hanya ada pada contoh objek tersebut. Yang satu ini berlaku untuk semua objek dengan TypeNameini.

Parameter fungsi

Anda sekarang dapat menggunakan jenis kustom ini untuk parameter dalam fungsi dan skrip Anda. Anda dapat memiliki satu fungsi membuat objek kustom ini lalu meneruskannya ke fungsi lain.

param( [PSTypeName('My.Object')]$Data )

PowerShell mengharuskan objek adalah jenis yang Anda tentukan. Ini menghasilkan kesalahan validasi jika jenisnya tidak cocok secara otomatis, sehingga Anda tidak perlu melakukan pengujian dalam kode Anda. Contoh yang bagus untuk membiarkan PowerShell melakukan apa yang terbaik.

Fungsi OutputType

Anda juga dapat menentukan OutputType untuk fungsi lanjutan Anda.

function Get-MyObject
{
    [OutputType('My.Object')]
    [CmdletBinding()]
        param
        (
            ...

Nilai atribut OutputType hanyalah catatan dokumentasi. Ini tidak berasal dari kode fungsi atau dibandingkan dengan output fungsi aktual.

Alasan utama Anda akan menggunakan jenis output adalah agar informasi meta tentang fungsi Anda mencerminkan niat Anda. Hal-hal seperti Get-Command dan Get-Help yang dapat dimanfaatkan oleh lingkungan pengembangan Anda. Jika Anda ingin informasi lebih lanjut, lihat bantuan untuk itu: about_Functions_OutputTypeAttribute.

Dengan demikian, jika Anda menggunakan Pester untuk menyatukan pengujian fungsi Anda maka akan menjadi ide yang baik untuk memvalidasi objek output yang cocok dengan OutputType Anda. Ini bisa menangkap variabel yang tanpa sengaja masuk ke dalam pipa saat seharusnya tidak boleh.

Pemikiran Akhir

Konteksnya adalah tentang [pscustomobject], tetapi banyak informasi ini berlaku untuk objek secara umum.

Saya telah melihat sebagian besar fitur ini hanya sekilas sebelumnya tetapi tidak pernah melihatnya disajikan sebagai kumpulan informasi tentang PSCustomObject. Minggu lalu aku tersandung satu lagi dan terkejut bahwa aku belum pernah melihatnya sebelumnya. Saya ingin menarik semua ide-ide ini bersama-sama sehingga Anda mudah-mudahan dapat melihat gambaran yang lebih besar dan menyadarinya ketika Anda memiliki kesempatan untuk menggunakannya. Saya harap Anda belajar sesuatu dan dapat menemukan cara untuk menerapkannya ke dalam skrip Anda.