Last Update: Sep 04, 2024 | Published: Sep 09, 2016
I’m having fun with this series and hope you are as well. In my previous article, I introduced you to PowerShell classes and I built a class that I can use with my movie data file. If you are just joining us, you really should take a few minutes to read the previous articles (Making Data Dance with PowerShell & Dancing on the Table with PowerShell), plus part one of this article, Data Transformations with PowerShell Classes, Part 1. Otherwise, let’s pick up where we left off.
First, I’m going to use the same CSV file I’ve been using in the last few articles.
$data = Import-CSV C:scriptsmoviedata.csv
Then I’m going to need my class definition, which I explained in the previous article.
Class MyUpcoming { #properties [string]$Title [datetime]$ReleaseDate [string]$Comments [int]$OpensIn [string]$Rating [boolean]$NowPlaying = $False #methods [MyUpcoming]Update() { $this.OpensIn = ($this.ReleaseDate - (Get-Date)).TotalDays if ((Get-Date) -ge $this.ReleaseDate ) { $this.NowPlaying = $True } return $this } #constructor MyUpcoming([string]$Title,[datetime]$ReleaseDate,[string]$Rating,[string]$Comments) { $this.Title = $Title $this.ReleaseDate = $ReleaseDate $this.Rating = $Rating $this.Comments = $Comments $this.Update() } } #close class definition
Now I’m ready to start creating instances of the class using my data. To create an instance of my class, I need to invoke the constructor and pass it parameter values from the data. Here’s a quick proof of concept with a few items from $data.
$data[0..2] | foreach { [myupcoming]::new($_.Title,$_.ReleaseDate,$_.Rating,$_.comment) }
See how this works? Or I can use New-Object.
$data[3..5] | foreach { New-Object -TypeName MyUpcoming -ArgumentList $_.Title,$_.ReleaseDate,$_.Rating,$_.comment }
If I were building a toolset around this, I might prefer to create a function to abstract the process a bit.
Function New-MyUpcoming { [cmdletbinding()] Param( [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateNotNullorEmpty()] [string]$Title, [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateNotNullorEmpty()] [datetime]$ReleaseDate, [Parameter(ValueFromPipelineByPropertyName)] [ValidateSet("G","PG","PG-13","R","NC-17","UR","NR")] [string]$Rating = "PG-13", [Parameter(ValueFromPipelineByPropertyName)] [string]$Comments ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" } #begin Process { Write-Verbose "[PROCESS] Creating instance for $Title" New-Object -TypeName MyUpcoming -ArgumentList $Title,$ReleaseDate,$Rating,$Comments } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end }
There are some added benefits with using a function. One, it makes it easier to use in a pipelined expression since you can define parameters to take pipeline input. You can also set default values, make critical values mandatory and use parameter validation. Note that I am using a validation set for the Rating parameter because I know what the accepted values will be. This means I can catch discrepancies when I pull in external data. Let’s test it out.
New-MyUpcoming -Title "The Monad Manifesto" -ReleaseDate "12/1/2016" -Comment "starring Tom Hanks as Jeffrey Snover" -Verbose
Excellent. I didn’t have to specify a rating and the function used the default value. The function should also accept pipeline input.
Perfect. Now I can import all of my data and create instances of my class.
Here’s an example of where using the function with parameter validation is valuable. I have an incorrect value in my original CSV file. How you handle this error is really up to you and depends on the larger scope of the toolset you are building around the data. In my case, I’ll simply go back and correct the error then re-run the command.
I now have a collection of objects that I can work with.
The last thing I can do is add custom type or formatting extensions. If you recall from the first article in this series, I used Update-TypeData. I can do the same thing here. The class name is the type name.
Update-TypeData -TypeName MyUpcoming -DefaultDisplayPropertySet "Title","ReleaseDate","Rating","Comments" -Force
Now when I look at the objects in $all I get the default properties.
$all | where {-Not $_.NowPlaying -and $_.releaseDate.year -eq 2016} | sort ReleaseDate
In the data I am using, I really don’t have a need to modify anything or devise any other methods. But you might depending on your data and your expectations for working with it. If you need to build other tooling around it, I’d suggest creating external functions that reference the class and its methods. Then you can include all the benefits of a function from help to parameter validation to support for WhatIf.
Working with data sources in PowerShell can be very rewarding and even fun. Once you have objects then you can exploit all of the PowerShell commands and the pipeline. Your biggest challenge will be finding the best way to bring your data into PowerShell and expose it to a user or yourself. Hopefully I’ve given you a number of options to explore and test.
I’d love to know what you thought about this series of articles so comments are always welcome.