Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell: Array of Class objects inside a Class

I've created a class containing simple values:

Class Volumes {
  [String]$ID
  [String]$Name
}

Now I'd like to create another class that contains an array of Volume Objects.

Something like:

Class Storage {
  [String]$Name
  [String]$IP
  [Array]@Volumes  # <- I know this is wrong, but I don't know how to do it
}

Thus, 2 questions:

  • How to create an array of objects inside the class ?
  • How to access / modify the array members, once I've built a new Object of class Storage ?

Thx in advance, Ralf.

like image 703
Ralf Draeger Avatar asked Dec 23 '21 09:12

Ralf Draeger


People also ask

How do you create an array of objects in PowerShell?

Use += to Add Objects to an Array of Objects in PowerShell The Plus Equals += is used to add items to an array. Every time you use it, it duplicates and creates a new array. You can use the += to add objects to an array of objects in PowerShell.

How do you create an array of variables in PowerShell?

To create and initialize an array, assign multiple values to a variable. The values stored in the array are delimited with a comma and separated from the variable name by the assignment operator ( = ). The comma can also be used to initialize a single item array by placing the comma before the single item.

How do I create a string array in PowerShell?

To create a string array, we can declare the variable name. Another way is to create using the @(). One more way is by creating the system. collections.

How do you append to an array in PowerShell?

The += operator is a shortcut that tells PowerShell to add this item to the existing array. This shortcut prevents you from having to type out the array name twice and is much more common than using the full syntax.

How do I create an array of objects in PowerShell?

$array = foreach ( $node in (1..5)) { "ATX-SQL-$node" } Array Types. By default, an array in PowerShell is created as a [PSObject[]] type. This allows it to contain any type of object or value. This works because everything is inherited from the PSObject type. Strongly typed arrays. You can create an array of any type using a similar syntax.

What are classes in PowerShell?

PowerShell classes represent definitions or schemas of those objects. Although you may be familiar with creating objects with commands like New-Object and using the pscustomobject type accelerator, these aren’t “new” objects. The kinds of objects these methods produce are of a specific type. PowerShell classes define the type.

What is an object in PowerShell?

It is used as a model to define the structure of objects. An object contains data that we access through properties and that we can work on using methods. PowerShell has been all about objects since the beginning. Even without knowing it, you have been working with objects since you used your first cmdlet.

What is instantiating an object in PowerShell?

The action of creating the new instance is called "instantiating" the object. It creates a new object in memory based on a particular class. The example below demonstrates how you can create your own object derived from the PSObject class that comes with PowerShell. This was the method used for creating custom objects prior to PowerShell version 5.


1 Answers

The below example should get you going for now!

You define an array of objects by simply putting [] after the type, so Volume[]

At the bottom of the snippet are 2 examples that show how to access the volumes data too.

Class Volume {
  [String]$ID
  [String]$Name 
}

Class Storage {
  [String]$Name
  [String]$IP
  [Volume[]]$Volumes 
}

# Create a volume object
$volume1 = New-Object Volume
$volume1.ID = '1'
$volume1.Name = 'Data'

# Create another volume object
$volume2 = New-Object Volume
$volume2.ID = '2'
$volume2.Name = 'Log'

# Create a storage object
$storage = New-Object Storage
$storage.Name = 'SomeStorage'
$storage.IP = '0.0.0.0'

# Add the volume objects
$storage.Volumes += $volume1
$storage.Volumes += $volume2

# access a volume by name or index
$storage.Volumes | Where-Object {$_.Name -eq 'Data'}
$storage.Volumes[0]

Educational N.B by zett42 and santiago squarzon

The array is inefficient when you add many elements one-by-one. You might want to have a look at ArrayList / List types.

You could instead use [List[Volume]]$Volumes = [List[Volume]]::new() in your Storage class. Make sure to put a using namespace System.Collections.Generic at the top of your script. Then when you add volumes do $storage.Volumes.Add($volume1)


I did some performance testing for this, i added 10_000 volumes to the object. The array took 9.3 seconds, and the list took 0.93 seconds, a 10 fold performance improvement.

Array - Quadratic - O(N²)

+= recreates the entire array, it copies the old contents into a new array along with the new element.

ArrayList - Constant - O(1)

ArrayList has O(n) time complexity for arbitrary indices of add/remove, but O(1) for the operation at the end of the list.

using namespace System.Collections.Generic

Class Volume {
  [String]$ID
  [String]$Name 
}

Class Storage {
  [String]$Name
  [String]$IP
  [List[Volume]]$Volumes = [List[Volume]]::new()
}

# Create volume objects
$volume1 = New-Object Volume
$volume1.ID = '1'
$volume1.Name = 'Data'

# Create another volume object
$volume2 = New-Object Volume
$volume2.ID = '2'
$volume2.Name = 'Log'

# Create a storage object
$storage = New-Object Storage
$storage.Name = 'SomeStorage'
$storage.IP = '0.0.0.0'

# Add the volume objects
$storage.Volumes.Add($volume1)
$storage.Volumes.Add($volume2)

# access a volume by name or index
$storage.Volumes | Where-Object {$_.Name -eq 'Data'}
$storage.Volumes[0]
like image 176
Otter Avatar answered Oct 17 '22 23:10

Otter