Az előző fejezetben láttuk, hogy egy osztály egy konkrét objektumpéldányának hogyan adhatunk újabb tagjellemzőket. Ez nagyon jó lehetőség, csak az a baja – mint ahogy láttuk is – hogy minden újabb objektum példánynál újra létre kell hozni saját tagjellemzőinket. Milyen jó lenne, ha magát az osztályt (típust) tudnánk módosítani és akkor az adott osztály minden objektuma már eleve rendelkezne az általunk definiált tagjellemzővel. Szerencsére ezt is lehetővé teszi a PowerShell!
Az eredeti objektumokat a .NET keretrendszer biztosítja, de az objektumtípusok testre szabásai a PowerShell számára egy types.ps1xml fájlban vannak definiálva a C:\WINDOWS\system32\windowspowershell\v1.0 könyvtárban. Azt senki sem ajánlja, hogy ezt átszerkesszük, de hasonló fájlokat mi is készíthetünk, amelyekkel mindenféle dolgot tehetünk az objektumtípusokhoz: új tulajdonságokat, metódusokat és még azt is, hogy mely tulajdonságait mutassa meg magáról az objektum alapban. Ez utóbbi is nagyon fontos, mert engem zavart, hogy például a get‑services cmdlet alapban miért pont a Status, Name és DisplayName tulajdonságokat adja ki? Hiszen van neki jó néhány egyéb tulajdonsága is:
PS C:\> Get-Service
Status Name DisplayName
------ ---- -----------
Stopped Alerter Alerter
Running ALG Application Layer Gateway Service
Running AppMgmt Application Management
Stopped aspnet_state ASP.NET State Service
...
Erre válasz ez az előbb említett types.ps1xml file. Keressük meg benne a szolgáltatások System.ServiceProcess.ServiceController adattípusát:
...
<Type>
<Name>System.ServiceProcess.ServiceController</Name>
<Members>
<MemberSet>
<Name>PSStandardMembers</Name>
<Members>
<PropertySet>
<Name>DefaultDisplayPropertySet</Name>
<ReferencedProperties>
<Name>Status</Name>
<Name>Name</Name>
<Name>DisplayName</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</MemberSet>
<AliasProperty>
<Name>Name</Name>
<ReferencedMemberName>ServiceName</ReferencedMemberName>
</AliasProperty>
</Members>
</Type>
...
A kiemelésben látszik, hogy azért ezeket a tulajdonságokat mutatja meg alapban a get‑service, mert ezek vannak DefaultDisplayPropertySet -ként definiálva.
Na, de minket most nem ez érdekel, hanem hogy hogyan tudok típust módosítani.
Létrehoztam egy typemember.ps1xml fájlt:
<Types>
<Type>
<Name>System.IO.FileInfo</Name>
<Members>
<NoteProperty>
<Name>Tipus</Name>
<Value>
File
</Value>
</NoteProperty>
</Members>
</Type>
<Type>
<Name>System.IO.DirectoryInfo</Name>
<Members>
<NoteProperty>
<Name>Tipus</Name>
<Value>
Directory
</Value>
</NoteProperty>
</Members>
</Type>
</Types>
A szerkezet magáért beszél. Definiáltam két különböző típusban is egy-egy NoteProperty tulajdonságot, hiszen itt magából a típusból következik, hogy fájlról vagy könyvtárról van szó, így nem kell futási időben kiszámolni semmit sem.
Most már csak be kell etetni a rendszerbe az én típusmódosításomat az Update-TypeData cmdlettel, és már nézhetjük is az eredményt:
[1] PS C:\> Update-TypeData C:\powershell2\Tananyag\typemember.ps1xml
[2] PS C:\> $f = Get-Item C:\filemembers.txt
[3] PS C:\> $f.tipus
File
[4] PS C:\> $f = Get-Item C:\old
[5] PS C:\> $f.tipus
Directory
Megjegyzések:
A ps1xml fájlok a PowerShellben olyan elbírálás alá esnek, mint a szkriptek, azaz a rendszerbe való felvételükhöz a 1.7.1 Szkriptek engedélyezése és indítása fejezetben leírt engedélyezésre van szükség.
Másik fontos tulajdonsága ezeknek a fájloknak, hogy kis-nagybetű érzékenyek, azaz az XML címkéknél és a .NET osztályokra való hivatkozásnál fontos, hogy a kis- és nagybetűket helyesen írjuk.
Továbbá ebben az XML fájlban nem használhatunk ékezetes karaktereket, így a definiált tulajdonság nem Típus, hanem Tipus lett.
Természetesen ez csak egy kis ízelítő volt az osztályok, típusok testre szabásából, a gyakorlati részben visszatérek majd erre gyakorlatiasabb példákkal.