The Surly Admin

Father, husband, IT Pro, cancer survivor

Dynamic Fields in Objects – what?

Short post today, but I wanted to talk about dynamic properties in objects.  I haven’t had too much need for this kind of thing, but the fact that PowerShell can do it so easily is pretty cool.  Imagine having an object where you plug a value into one field and dynamically another field in the object changes based on that first value.  Kind of sounds like a function, but it’s all done right in the object itself.

A little background.  Colleague of mine was trying to use CMD.exe DIR command to make a fast Get-ChildItem, one that doesn’t get every single object property for a file, which in theory would retrieve that information much faster then Get-ChildItem.  For now he’s abandoned the project because the speed wasn’t there but it brought up some interesting points, and one of them was directory name.  When using DIR you often only get the BaseName property, not the full path but as a scripter I almost always want the full path.  Certainly ways of getting that information but we would really want to display both.  What if we could just have the object do it and not worry about?

What if you were dealing with a lot of disk size values and wanted the flexibility of seeing MB and GB conversions?  Sure you could send it off to a function but lets consider another way.

Add-Member

It all begins with Add-Member.  Let’s keep it simple and go with the BaseName calculation I mentioned before.  First let’s define some things:


$dir = "C:\Users\mpugh\AppData\Local\ActiveState\KomodoEdit\8.5\codeintel\db"
$DynamicObject = [PSCustomObject]@{FullName = $Dir}

No real drama, get some data and create an object with that data as a property (FullName).  Now I want to add my dynamic property:


$DynamicObject | Add-Member -MemberType ScriptProperty -Name BaseName -Value {
$this.FullName.Split("\")[-1]
}

This is where it gets cool.  We take the object we created and pipe it into Add-Member which will add a property, in this case a ScriptProperty which will evaluate it’s value based on the scriptblock in the Value field.  This is a pretty simple script function where I take the current object ($this) take the FullName property and split that on the back slash.  Then take the last element in the returned array for display (which will be the last folder in the path–in this case).


$DynamicObject
FullName BaseName
——– ——-
C:\Users\mpugh\AppData\Local\ActiveState\KomodoEdit\8.5\codeintel\db db

Cool.  But we could have just assigned the BaseName value when we created the object right?  Check this out:


PS C:\Users\mpugh> $DynamicObject.FullName = "C:\Users\mpugh\AppData\Local"
PS C:\Users\mpugh> $DynamicObject
FullName BaseName
——– ——–
C:\Users\mpugh\AppData\Local Local

Notice all we did was change the FullName property, but the BaseName property dynamically changed.  You’ve essentially created a class that dynamically changes itself based on the values you assign.  You could still mimic all of this behavior by using Functions but it’s pretty interesting none the less.  With PowerShell 5.0, Microsoft is promising us the ability to create classes without having to drop into C# which would really open up these kinds of techniques.

Imagine something like this:


Get-ChildItem $Path -Recurse | Select -Class MyDynamicFileObject -Property BaseName,FullName,SizeGB,SizeMB

Where you’ve defined a class that automatically takes the Length property and converts it to MB and GB for you.

Follow-up post that coming soon that explains this tweet:

Holy crap. Add-Member may be my new performance go to!

Love finding new technique’s that increase performance…. do you?

January 26, 2015 - Posted by | PowerShell | ,

No comments yet.

Leave a comment