Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Kort beskrivning
Beskriver hur du kan använda klasser för att skapa egna anpassade typer.
Lång beskrivning
PowerShell 5.0 lägger till en formell syntax för att definiera klasser och andra användardefinierade typer. Genom att lägga till klasser kan utvecklare och IT-proffs använda PowerShell för ett bredare utbud av användningsfall. Det förenklar utvecklingen av PowerShell-artefakter och påskyndar täckningen av hanteringsytor.
En klassdeklaration är en skiss som används för att skapa instanser av objekt vid körning. När du definierar en klass är klassnamnet namnet på typen. Om du till exempel deklarerar en klass med namnet Device och initierar en variabel $dev till en ny instans av Deviceär $dev ett objekt eller en instans av typen Device. Varje instans av Enhet kan ha olika värden i sina egenskaper.
Scenarier som stöds
- Definiera anpassade typer i PowerShell med hjälp av välbekant objektorienterad programmeringssemantik som klasser, egenskaper, metoder, arv osv.
- Felsök typer med hjälp av PowerShell-språket.
- Generera och hantera undantag med hjälp av formella mekanismer.
- Definiera DSC-resurser och deras associerade typer med hjälp av PowerShell-språket.
Syntax
Klasser deklareras med hjälp av följande syntax:
class <class-name> [: [<base-class>][,<interface-list]] {
[[<attribute>] [hidden] [static] <property-definition> ...]
[<class-name>([<constructor-argument-list>])
{<constructor-statement-list>} ...]
[[<attribute>] [hidden] [static] <method-definition> ...]
}
Klasser instansieras med någon av följande syntaxer:
[$<variable-name> =] New-Object -TypeName <class-name> [
[-ArgumentList] <constructor-argument-list>]
[$<variable-name> =] [<class-name>]::new([<constructor-argument-list>])
Anmärkning
När du använder [<class-name>]::new( syntax är hakparenteser runt klassnamnet obligatoriska. Hakparenteserna signalerar en typdefinition för PowerShell.
Exempel på syntax och användning
Det här exemplet visar den minsta syntax som krävs för att skapa en användbar klass.
class Device {
[string]$Brand
}
$dev = [Device]::new()
$dev.Brand = "Microsoft"
$dev
Brand
-----
Microsoft
Klassegenskaper
Egenskaper är variabler som deklareras i klassomfånget. En egenskap kan vara av vilken inbyggd typ som helst eller en instans av en annan klass. Klasser har ingen begränsning i antalet egenskaper de har.
Exempelklass med enkla egenskaper
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
}
$device = [Device]::new()
$device.Brand = "Microsoft"
$device.Model = "Surface Pro 4"
$device.VendorSku = "5072641000"
$device
Brand Model VendorSku
----- ----- ---------
Microsoft Surface Pro 4 5072641000
Exempel på komplexa typer i klassegenskaper
I det här exemplet definieras en tom rackklass med hjälp av Device klassen . Exemplen, som följer den här, visar hur du lägger till enheter i racket och hur du börjar med ett förinstallerat rack.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
}
class Rack {
[string]$Brand
[string]$Model
[string]$VendorSku
[string]$AssetId
[Device[]]$Devices = [Device[]]::new(8)
}
$rack = [Rack]::new()
$rack
Brand :
Model :
VendorSku :
AssetId :
Devices : {$null, $null, $null, $null...}
Klassmetoder
Metoder definierar de åtgärder som en klass kan utföra. Metoderna kan ta parametrar som ger indata. Metoder kan returnera utdata. Data som returneras av en metod kan vara vilken definierad datatyp som helst.
Exempel på enkel klass med egenskaper och metoder
Utöka klassen Rack för att lägga till och ta bort enheter till eller från den.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
[string]ToString(){
return ("{0}|{1}|{2}" -f $this.Brand, $this.Model, $this.VendorSku)
}
}
class Rack {
[int]$Slots = 8
[string]$Brand
[string]$Model
[string]$VendorSku
[string]$AssetId
[Device[]]$Devices = [Device[]]::new($this.Slots)
[void] AddDevice([Device]$dev, [int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $dev
}
[void]RemoveDevice([int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $null
}
[int[]] GetAvailableSlots(){
[int]$i = 0
return @($this.Devices.foreach{ if($_ -eq $null){$i}; $i++})
}
}
$rack = [Rack]::new()
$surface = [Device]::new()
$surface.Brand = "Microsoft"
$surface.Model = "Surface Pro 4"
$surface.VendorSku = "5072641000"
$rack.AddDevice($surface, 2)
$rack
$rack.GetAvailableSlots()
Slots : 8
Brand :
Model :
VendorSku :
AssetId :
Devices : {$null, $null, Microsoft|Surface Pro 4|5072641000, $null...}
0
1
3
4
5
6
7
Utdata i klassmetoder
Metoderna ska ha en definierad returtyp. Om en metod inte returnerar utdata ska utdatatypen vara [void].
I klassmetoder skickas inga objekt till pipelinen förutom de som nämns i -instruktionen return . Det finns inga oavsiktliga utdata till pipelinen från koden.
Anmärkning
Detta skiljer sig i grunden från hur PowerShell-funktioner hanterar utdata, där allt går till pipelinen.
Metodutdata
Det här exemplet visar inga oavsiktliga utdata till pipelinen från klassmetoder, förutom för -instruktionen return .
class FunWithIntegers
{
[int[]]$Integers = 0..10
[int[]]GetOddIntegers(){
return $this.Integers.Where({ ($_ % 2) })
}
[void] GetEvenIntegers(){
# this following line doesn't go to the pipeline
$this.Integers.Where({ ($_ % 2) -eq 0})
}
[string]SayHello(){
# this following line doesn't go to the pipeline
"Good Morning"
# this line goes to the pipeline
return "Hello World"
}
}
$ints = [FunWithIntegers]::new()
$ints.GetOddIntegers()
$ints.GetEvenIntegers()
$ints.SayHello()
1
3
5
7
9
Hello World
Konstruktor
Med konstruktorer kan du ange standardvärden och validera objektlogik när du skapar -instansen av klassen. Konstruktorer har samma namn som klassen. Konstruktorer kan ha argument för att initiera datamedlemmarna i det nya objektet.
Klassen kan ha noll eller fler konstruktorer definierade. Om ingen konstruktor har definierats får klassen en standardkonstruktor utan parameter. Den här konstruktorn initierar alla medlemmar till deras standardvärden. Objekttyper och strängar får null-värden. När du definierar konstruktorn skapas ingen standardparameterlös konstruktor. Skapa en parameterlös konstruktor om det behövs.
Grundläggande syntax för konstruktor
I det här exemplet Device definieras klassen med properties och en konstruktor. Om du vill använda den här klassen måste användaren ange värden för de parametrar som anges i konstruktorn.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
Device(
[string]$b,
[string]$m,
[string]$vsk
){
$this.Brand = $b
$this.Model = $m
$this.VendorSku = $vsk
}
}
[Device]$surface = [Device]::new("Microsoft", "Surface Pro 4", "5072641000")
$surface
Brand Model VendorSku
----- ----- ---------
Microsoft Surface Pro 4 5072641000
Exempel med flera konstruktorer
I det här exemplet definieras klassen Device med egenskaper, en standardkonstruktor och en konstruktor för att initiera instansen.
Standardkonstruktorn anger varumärket till Undefined och lämnar model och vendor-sku med null-värden .
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
Device(){
$this.Brand = 'Undefined'
}
Device(
[string]$b,
[string]$m,
[string]$vsk
){
$this.Brand = $b
$this.Model = $m
$this.VendorSku = $vsk
}
}
[Device]$somedevice = [Device]::new()
[Device]$surface = [Device]::new("Microsoft", "Surface Pro 4", "5072641000")
$somedevice
$surface
Brand Model VendorSku
----- ----- ---------
Undefined
Microsoft Surface Pro 4 5072641000
Dolt attribut
Attributet hidden gör en egenskap eller metod mindre synlig. Egenskapen eller metoden är fortfarande tillgänglig för användaren och är tillgänglig i alla omfång där objektet är tillgängligt. Dolda medlemmar är dolda från cmdleten Get-Member och kan inte visas med hjälp av tabbifyllning eller IntelliSense utanför klassdefinitionen.
Exempel med dolda attribut
När ett rackobjekt skapas är antalet platser för enheter ett fast värde som inte bör ändras när som helst. Det här värdet är känt när det skapas.
Genom att använda det dolda attributet kan utvecklaren hålla antalet platser dolda och förhindra oavsiktliga ändringar av rackets storlek.
class Device {
[string]$Brand
[string]$Model
}
class Rack {
[int] hidden $Slots = 8
[string]$Brand
[string]$Model
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack ([string]$b, [string]$m, [int]$capacity){
## argument validation here
$this.Brand = $b
$this.Model = $m
$this.Slots = $capacity
## reset rack size to new capacity
$this.Devices = [Device[]]::new($this.Slots)
}
}
[Rack]$r1 = [Rack]::new("Microsoft", "Surface Pro 4", 16)
$r1
$r1.Devices.Length
$r1.Slots
Brand Model Devices
----- ----- -------
Microsoft Surface Pro 4 {$null, $null, $null, $null...}
16
16
Observera att egenskapen Slots inte visas i $r1 utdata. Storleken ändrades dock av konstruktören.
Statiskt attribut
Attributet static definierar en egenskap eller en metod som finns i klassen och som inte behöver någon instans.
En statisk egenskap är alltid tillgänglig, oberoende av klass-instansiering. En statisk egenskap delas mellan alla instanser av klassen. En statisk metod är alltid tillgänglig. Alla statiska egenskaper är aktiva under hela sessionsintervallet.
Exempel med statiska attribut och metoder
Anta att racken som instansieras här finns i ditt datacenter. Så du vill hålla reda på racken i din kod.
class Device {
[string]$Brand
[string]$Model
}
class Rack {
hidden [int] $Slots = 8
static [Rack[]]$InstalledRacks = @()
[string]$Brand
[string]$Model
[string]$AssetId
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack ([string]$b, [string]$m, [string]$id, [int]$capacity){
## argument validation here
$this.Brand = $b
$this.Model = $m
$this.AssetId = $id
$this.Slots = $capacity
## reset rack size to new capacity
$this.Devices = [Device[]]::new($this.Slots)
## add rack to installed racks
[Rack]::InstalledRacks += $this
}
static [void]PowerOffRacks(){
foreach ($rack in [Rack]::InstalledRacks) {
Write-Warning ("Turning off rack: " + ($rack.AssetId))
}
}
}
Det finns en statisk egenskap och metod för testning
PS> [Rack]::InstalledRacks.Length
0
PS> [Rack]::PowerOffRacks()
PS> (1..10) | ForEach-Object {
>> [Rack]::new("Adatum Corporation", "Standard-16",
>> $_.ToString("Std0000"), 16)
>> } > $null
PS> [Rack]::InstalledRacks.Length
10
PS> [Rack]::InstalledRacks[3]
Brand Model AssetId Devices
----- ----- ------- -------
Adatum Corporation Standard-16 Std0004 {$null, $null, $null, $null...}
PS> [Rack]::PowerOffRacks()
WARNING: Turning off rack: Std0001
WARNING: Turning off rack: Std0002
WARNING: Turning off rack: Std0003
WARNING: Turning off rack: Std0004
WARNING: Turning off rack: Std0005
WARNING: Turning off rack: Std0006
WARNING: Turning off rack: Std0007
WARNING: Turning off rack: Std0008
WARNING: Turning off rack: Std0009
WARNING: Turning off rack: Std0010
Observera att antalet rack ökar varje gång du kör det här exemplet.
Attribut för egenskapsvalidering
Med valideringsattribut kan du testa att värden som ges till egenskaper uppfyller definierade krav. Valideringen utlöses när värdet tilldelas. Se about_functions_advanced_parameters.
Exempel med valideringsattribut
class Device {
[ValidateNotNullOrEmpty()][string]$Brand
[ValidateNotNullOrEmpty()][string]$Model
}
[Device]$dev = [Device]::new()
Write-Output "Testing dev"
$dev
$dev.Brand = ""
Testing dev
Brand Model
----- -----
Exception setting "Brand": "The argument is null or empty. Provide an
argument that is not null or empty, and then try the command again."
At C:\tmp\Untitled-5.ps1:11 char:1
+ $dev.Brand = ""
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
Arv i PowerShell-klasser
Du kan utöka en klass genom att skapa en ny klass som härleds från en befintlig klass. Den härledda klassen ärver basklassens egenskaper. Du kan lägga till eller åsidosätta metoder och egenskaper efter behov.
PowerShell stöder inte multipelt arv. Klasser kan inte ärva från mer än en klass. Du kan dock använda gränssnitt för detta ändamål.
Arvsimplementering definieras av operatorn : , vilket innebär att utöka den här klassen eller implementera dessa gränssnitt. Den härledda klassen ska alltid stå längst till vänster i klassdeklarationen.
Exempel med enkel arvssyntax
Det här exemplet visar den enkla syntaxen för arv av PowerShell-klass.
Class Derived : Base {...}
Det här exemplet visar arv med en gränssnittsdeklaration som kommer efter basklassen.
Class Derived : Base.Interface {...}
Exempel på enkelt arv i PowerShell-klasser
I det här exemplet är klasserna Rack och Device som användes i föregående exempel bättre definierade för att: undvika egenskapsupprepningar, bättre justera vanliga egenskaper och återanvända vanlig affärslogik.
De flesta objekt i datacentret är företagets tillgångar, vilket är klokt att börja spåra dem som tillgångar. Enhetstyper definieras av uppräkningen DeviceType , se about_Enum för mer information om uppräkningar.
I vårt exempel definierar Rack vi bara och ComputeServer; båda tilläggen Device till klassen.
enum DeviceType {
Undefined = 0
Compute = 1
Storage = 2
Networking = 4
Communications = 8
Power = 16
Rack = 32
}
class Asset {
[string]$Brand
[string]$Model
}
class Device : Asset {
hidden [DeviceType]$devtype = [DeviceType]::Undefined
[string]$Status
[DeviceType] GetDeviceType(){
return $this.devtype
}
}
class ComputeServer : Device {
hidden [DeviceType]$devtype = [DeviceType]::Compute
[string]$ProcessorIdentifier
[string]$Hostname
}
class Rack : Device {
hidden [DeviceType]$devtype = [DeviceType]::Rack
hidden [int]$Slots = 8
[string]$Datacenter
[string]$Location
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack (){
## Just create the default rack with 8 slots
}
Rack ([int]$s){
## Add argument validation logic here
$this.Devices = [Device[]]::new($s)
}
[void] AddDevice([Device]$dev, [int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $dev
}
[void] RemoveDevice([int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $null
}
}
$FirstRack = [Rack]::new(16)
$FirstRack.Status = "Operational"
$FirstRack.Datacenter = "PNW"
$FirstRack.Location = "F03R02.J10"
(0..15).ForEach({
$ComputeServer = [ComputeServer]::new()
$ComputeServer.Brand = "Fabrikam, Inc." ## Inherited from Asset
$ComputeServer.Model = "Fbk5040" ## Inherited from Asset
$ComputeServer.Status = "Installed" ## Inherited from Device
$ComputeServer.ProcessorIdentifier = "x64" ## ComputeServer
$ComputeServer.Hostname = ("r1s" + $_.ToString("000")) ## ComputeServer
$FirstRack.AddDevice($ComputeServer, $_)
})
$FirstRack
$FirstRack.Devices
Datacenter : PNW
Location : F03R02.J10
Devices : {r1s000, r1s001, r1s002, r1s003...}
Status : Operational
Brand :
Model :
ProcessorIdentifier : x64
Hostname : r1s000
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
ProcessorIdentifier : x64
Hostname : r1s001
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
<... content truncated here for brevity ...>
ProcessorIdentifier : x64
Hostname : r1s015
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
Anropa basklasskonstruktorer
Om du vill anropa en basklasskonstruktor från en underklass lägger du till nyckelordet base .
class Person {
[int]$Age
Person([int]$a)
{
$this.Age = $a
}
}
class Child : Person
{
[string]$School
Child([int]$a, [string]$s ) : base($a) {
$this.School = $s
}
}
[Child]$littleone = [Child]::new(10, "Silver Fir Elementary School")
$littleone.Age
10
Anropa basklassmetoder
Om du vill åsidosätta befintliga metoder i underklasser deklarerar du metoder med samma namn och signatur.
class BaseClass
{
[int]days() {return 1}
}
class ChildClass1 : BaseClass
{
[int]days () {return 2}
}
[ChildClass1]::new().days()
2
Om du vill anropa basklassmetoder från åsidosatta implementeringar omvandlar du till basklassen ([baseclass]$this) vid anrop.
class BaseClass
{
[int]days() {return 1}
}
class ChildClass1 : BaseClass
{
[int]days () {return 2}
[int]basedays() {return ([BaseClass]$this).days()}
}
[ChildClass1]::new().days()
[ChildClass1]::new().basedays()
2
1
Gränssnitt
Syntaxen för att deklarera gränssnitt liknar C#. Du kan deklarera gränssnitt efter bastyper eller omedelbart efter ett kolon (:) när det inte finns någon angiven bastyp. Avgränsa alla typnamn med kommatecken.
class MyComparable : system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
class MyComparableBar : bar, system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
Importera klasser från en PowerShell-modul
Import-Module och #requires-instruktionen importerar endast modulfunktioner, alias och variabler enligt modulens definition. Klasser importeras inte. Satsen using module importerar de klasser som definierats i modulen. Om modulen inte läses in i den aktuella sessionen misslyckas instruktionen using .