- 10/05/2020
- 8 minute de citit
-
- j
- m
- s
- j
- c
.
PSCustomObject
sunt un instrument excelent de adăugat în centura de instrumente PowerShell. Să începem cu elementele de bazăși să ne îndreptăm spre funcțiile mai avansate. Ideea din spatele utilizării unui PSCustomObject
este de aavea o modalitate simplă de a crea date structurate. Aruncați o privire la primul exemplu și veți avea o idee mai bună despre ce înseamnă asta.
Note
Versiunea originală a acestui articol a apărut pe blogul scris de @KevinMarquette. EchipaPowerShell îi mulțumește lui Kevin pentru că a împărtășit acest conținut cu noi. Vă rugăm să consultați blogul său laPowerShellExplained.com.
- Crearea unui PSCustomObject
- Conversia unui hashtable
- Abordare de legitate
- Salvare într-un fișier
- Lucrul cu proprietățile
- Adăugarea de proprietăți
- Îndepărtarea proprietăților
- Enumerarea numelor de proprietăți
- Accesarea dinamică a proprietăților
- Convertiți PSCustomObject într-un hashtable
- Testarea proprietăților
- Adaugarea de metode de obiect
- Obiecte vs. tipuri de valori
- psobject.copy()
- PSTypeName pentru tipurile de obiecte personalizate
- Utilizarea DefaultPropertySet (the long way)
- Update-TypeData with DefaultPropertySet
- Update-TypeData with ScriptProperty
- Parametrii funcțiilor
- Function OutputType
- Gânduri de încheiere
Crearea unui PSCustomObject
Îmi place să folosesc în PowerShell. Crearea unui obiect utilizabil nu a fost niciodată mai ușoară. din acest motiv, voi trece peste toate celelalte moduri în care puteți crea un obiect, dar trebuie să menționez că majoritatea acestor exemple sunt PowerShell v3.0 și mai noi.
$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
Această metodă funcționează bine pentru mine, deoarece folosesc hashtables pentru aproape orice. Dar există momente în care aș dori ca PowerShell să trateze hashtables mai mult ca pe un obiect. Primul loc în care observați diferența este atunci când doriți să folosiți Format-Table
sau Export-CSV
și vă dați seama că ahashtable este doar o colecție de perechi cheie/valoare.
Apoi puteți accesa și folosi valorile așa cum ați face-o cu un obiect normal.
$myObject.Name
Conversia unui hashtable
Dacă tot sunt pe subiect, știați că puteți face acest lucru:
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable
Prefer să creez obiectul de la început, dar există momente în care trebuie să lucrați mai întâi cu ahashtable. Acest exemplu funcționează deoarece constructorul ia un hashtable pentru objectproperties. O notă importantă este că, deși această metodă funcționează, nu este un echivalent exact. Cea mai mare diferență este faptul că ordinea proprietăților nu este păstrată.
Abordare de legitate
Poate ați văzut oameni care folosesc New-Object
pentru a crea obiecte personalizate.
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable
Acest mod este destul de lent, dar poate fi cea mai bună opțiune pe versiunile timpurii ale PowerShell.
Salvare într-un fișier
Constat că cel mai bun mod de a salva un hashtable într-un fișier este să îl salvați ca JSON. Puteți să o importați înapoi îna
$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path$myObject = Get-Content -Path $Path | ConvertFrom-Json
Copăr mai multe moduri de a salva obiecte într-un fișier în articolul meu despreCele mai multe moduri de a citi și scrie în fișiere.
Lucrul cu proprietățile
Adăugarea de proprietăți
Puteți adăuga în continuare noi proprietăți la PSCustomObject
dvs. cu Add-Member
.
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID
Îndepărtarea proprietăților
Puteți, de asemenea, îndepărta proprietăți de pe un obiect.
$myObject.psobject.properties.remove('ID')
psobject
este o proprietate ascunsă care vă oferă acces la metadatele obiectului de bază.
Enumerarea numelor de proprietăți
Câteodată aveți nevoie de o listă a tuturor numelor de proprietăți ale unui obiect.
$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
Puteți obține aceeași listă și din proprietateapsobject
.
$myobject.psobject.properties.name
Accesarea dinamică a proprietăților
Am menționat deja că puteți accesa direct valorile proprietăților.
$myObject.Name
Puteți folosi un șir de caractere pentru numele proprietății și tot va funcționa.
$myObject.'Name'
Puteți face încă un pas înainte și folosi o variabilă pentru numele proprietății.
$property = 'Name'$myObject.$property
Știu că pare ciudat, dar funcționează.
Convertiți PSCustomObject într-un hashtable
Pentru a continua de la ultima secțiune, puteți parcurge în mod dinamic proprietățile și crea un hashtable din ele.
$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}
Testarea proprietăților
Dacă aveți nevoie să știți dacă o proprietate există, puteți verifica dacă acea proprietate are o valoare.
if( $null -ne $myObject.ID )
Dar dacă valoarea ar putea fi $null
, puteți verifica dacă există, verificândpsobject.properties
pentru aceasta.
if( $myobject.psobject.properties.match('ID').Count )
Adaugarea de metode de obiect
Dacă trebuie să adăugați o metodă de script la un obiect, o puteți face cu Add-Member
și aScriptBlock
. Trebuie să folosiți referința automată a variabilei this
la obiectul curent. Iată ascriptblock
pentru a transforma un obiect într-un hashtable. (același cod din ultimul exemplu)
Apoi o adăugăm obiectului nostru ca o proprietate de script.
Apoi putem apela funcția noastră astfel:
$myObject.ToHashtable()
Obiecte vs. tipuri de valori
Obiectele și tipurile de valori nu tratează atribuirile de variabile în același mod. Dacă atribuiți tipuri de valori la fiecare dintre ele, doar valoarea este copiată în noua variabilă.
$first = 1$second = $first$second = 2
În acest caz, $first
este 1 și $second
este 2.
Variabilele obiect dețin o referință la obiectul real. Atunci când atribuiți un obiect unei variabile noi, ele fac în continuare referire la același obiect.
$third = @{Key=3}$fourth = $third$fourth.Key = 4
Pentru că $third
și $fourth
fac referire la aceeași instanță a unui obiect, atât $third.key
cât și$fourth.Key
sunt 4.
psobject.copy()
Dacă aveți nevoie de o copie fidelă a unui obiect, îl puteți clona.
$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4
Clona creează o copie superficială a obiectului. Ele au acum instanțe diferite și $third.key
este 3și $fourth.Key
este 4 în acest exemplu.
Aceasta o numesc copie superficială pentru că dacă aveți obiecte imbricate. (în care proprietățile conțin alte obiecte). Sunt copiate doar valorile de nivel superior. Obiectele copil se vor referi unele la altele.
PSTypeName pentru tipurile de obiecte personalizate
Acum că avem un obiect, mai sunt câteva lucruri pe care le putem face cu el și care s-ar putea să nu fie la fel de evidente. Primul lucru pe care trebuie să-l facem este să-i dăm un PSTypeName
. Acesta este cel mai comun mod în care văd că o fac oamenii:
$myObject.PSObject.TypeNames.Insert(0,"My.Object")
Am descoperit recent un alt mod de a face acest lucru din această postare de către /u/markekraus. Am făcut puțină cercetare și mai multe postări despre ideea de la Adam Bertram și Mike Shepard în care vorbesc despre această abordare care vă permite să o definiți inline.
$myObject = @{ PSTypeName = 'My.Object' Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
Îmi place cât de bine se potrivește acest lucru pur și simplu în limbaj. Acum că avem un obiect cu un typename corespunzător, putem face mai multe lucruri.
Nota
Puteți crea, de asemenea, tipuri PowerShell personalizate folosind clase PowerShell. Pentru mai multe informații, consultațiPowerShell Class Overview.
Utilizarea DefaultPropertySet (the long way)
PowerShell decide pentru noi ce proprietăți să afișeze în mod implicit. O mulțime de comenzi native au un fișier de formatare.ps1xml
care face toată treaba grea. Din această postare a lui Boe Prox,există o altă modalitate prin care putem face acest lucru pe obiectul nostru personalizat folosind doar PowerShell. Îi putem da unMemberSet
pentru ca acesta să îl folosească.
Acum, când obiectul meu doar cade în shell, va arăta doar acele proprietăți în mod implicit.
Update-TypeData with DefaultPropertySet
Este frumos, dar am văzut recent o modalitate mai bună când am urmăritPowerShell unplugged 2016 cu Jeffrey Snover & Don Jones. Jeffrey foloseaUpdate-TypeData pentru a specifica proprietățile implicite.
$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData
Este suficient de simplu încât aproape că aș putea să mi-l amintesc dacă nu aș avea această postare ca referință rapidă. Acum pot să creez cu ușurință obiecte cu o mulțime de proprietăți și totuși să le dau o vedere frumoasă și curată atunci când le privesc din shell. Dacă am nevoie să accesez sau să văd acele alte proprietăți, ele rămân acolo.
$myObject | Format-List *
Update-TypeData with ScriptProperty
Altul pe care l-am mai reținut din acel videoclip a fost crearea de proprietăți de script pentru obiectele dumneavoastră. Acesta ar fi un moment bun pentru a sublinia faptul că acest lucru funcționează și pentru obiectele existente.
Puteți face acest lucru înainte ca obiectul dvs. să fie creat sau după și va funcționa în continuare. Aceasta este ceea ce face ca acest lucru să fie diferit de utilizarea Add-Member
cu o proprietate de script. Când folosiți Add-Member
în modul în care Ireferențiat mai devreme, acesta există doar pe acea instanță specifică a obiectului. Aceasta se aplică la toate obiectele cu acest TypeName
.
Parametrii funcțiilor
Acum puteți folosi aceste tipuri personalizate pentru parametrii din funcțiile și scripturile dumneavoastră. Puteți face ca o singurăfuncție să creeze aceste obiecte personalizate și apoi să le treacă în alte funcții.
param( $Data )
PowerShell cere ca obiectul să fie de tipul pe care l-ați specificat. Aruncă o eroare de validare dacă tipul nu se potrivește în mod automat pentru a vă scuti de pasul de a testa acest lucru în codul dumneavoastră. Un exemplu excelent de a lăsa PowerShell să facă ceea ce știe să facă cel mai bine.
Function OutputType
De asemenea, puteți defini un OutputType
pentru funcțiile dvs. avansate.
function Get-MyObject{ param ( ...
Valoarea atributului OutputType este doar o notă de documentare. Nu este derivată din codul funcției și nici nu este comparată cu ieșirea reală a funcției.
Motivul principal pentru care ați folosi un tip de ieșire este pentru ca informațiile meta despre funcția dvs. să reflecte intențiile dvs. Lucruri precum Get-Command
și Get-Help
de care mediul dvs. de dezvoltare poate profita. Dacă doriți mai multe informații, atunci aruncați o privire la ajutorul pentru acesta:about_Functions_OutputTypeAttribute.
După aceasta, dacă folosiți Pester pentru a vă testa unitar funcțiile, atunci ar fi o idee bună să validați că obiectele de ieșire se potrivesc cu OutputType-ul dumneavoastră. Acest lucru ar putea prinde variabilele care pur și simplu cad în țeavă atunci când nu ar trebui.
Gânduri de încheiere
Contextul a fost tot despre , dar multe dintre aceste informații se aplică obiectelor în general.
Am mai văzut cele mai multe dintre aceste caracteristici în trecere, dar nu le-am văzut niciodată prezentate ca o colecție de informații pe PSCustomObject
. Chiar săptămâna trecută am dat peste o alta și am fost surprinscă nu o mai văzusem înainte. Am vrut să reunesc toate aceste idei, astfel încât să sperăm că puteți vedea imaginea de ansamblu și să fiți conștienți de ele atunci când veți avea ocazia să le folosiți. Sper că ați învățat ceva și că puteți găsi o modalitate de a lucra cu acestea în scripturile dumneavoastră.
.