Skip to content

Instantly share code, notes, and snippets.

@PanosGreg
Created November 7, 2023 14:38
Show Gist options
  • Save PanosGreg/df2b8a262545fe859e621e791a6b5c35 to your computer and use it in GitHub Desktop.
Save PanosGreg/df2b8a262545fe859e621e791a6b5c35 to your computer and use it in GitHub Desktop.
Dynamically generate the PowerShell class code from a pscustomobject or hashtable
function ConvertTo-ClassDefinition {
<#
.EXAMPLE
$hash = @{name='aa';size=10}
$code = $hash | ConvertTo-ClassDefinition
Invoke-Expression $code
$h = [My_Hashtable]::new()
# create and load a class from a hashtable
.EXAMPLE
$obj = [pscustomobject]@{name='aa';size=10}
Invoke-Expression ($obj | ConvertTo-ClassDefinition)
$p = [My_PSCustomObject]::new()
# create and load a class from a ps custom object
.EXAMPLE
$obj = [pscustomobject]@{name='aa';size=10}
$obj | ConvertTo-ClassDefinition -Hidden size
# create a class definition with a hidden property
.EXAMPLE
$obj = [pscustomobject]@{name='aa';size=10}
$code = $obj | ConvertTo-ClassDefinition -Hidden size
Invoke-Expression $code
$p = [My_PSCustomObject]@{Name = 'aa' ; Size = 12}
$p | Select-Object -Property ($p | Get-Member -MemberType Property -Force).Name
# create a class with a hidden property, then instiate it into a new object
# and finally show all of its properties, even the hidden one.
#>
[OutputType([string])] # <-- the powershell class definition as plain text
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory,ValueFromPipeline)]
[ValidateNotNull()]
$InputObject,
[ValidateNotNullOrEmpty()]
[string]$ClassName,
[ValidateNotNullOrEmpty()]
[string[]]$IncludeProperty = '*',
[ValidateNotNullOrEmpty()]
[string[]]$ExcludeProperty,
[ValidateNotNullOrEmpty()]
[string[]]$HiddenProperty
)
# if input has many items, then get only the 1st item
if (([array]$InputObject).Count -ge 2) {$InputObject = $InputObject[0]}
# make sure the input object is either a pscustomobject or a hashtable (ordered or not)
$SupportedTypes = 'System.Collections.Hashtable',
'System.Management.Automation.PSCustomObject',
'System.Collections.Specialized.OrderedDictionary'
$ObjectType = $InputObject.psobject.TypeNames[0]
if ($ObjectType -notin $SupportedTypes) {
Write-Warning 'Please provide a supported data type of either a hashtable (ordered or not) or pscustomobject'
return
}
# convert hashtable into a ps custom object
$HashTypes = 'System.Collections.Hashtable','System.Collections.Specialized.OrderedDictionary'
if ($ObjectType -in $HashTypes) {
$InputObject = [pscustomobject]$InputObject
}
# set the name of the class
$ShortTypeName = $ObjectType.Split('.')[-1]
if ($ClassName) {$BaseClassName = $ClassName}
else {$BaseClassName = 'My_' + $ShortTypeName} # <-- unfortunately PS classes can't take dots in the name
# get properties
$AllProps = $InputObject.psobject.properties
$Filter = {
$_.Name -in $IncludeProperty -and
$_.Name -notin $ExcludeProperty
}
if ($IncludeProperty -ne '*') {$Properties = $AllProps | Where $Filter}
else {$Properties = $AllProps | Where Name -notin $ExcludeProperty}
# start building the class definition
$SB = [System.Text.StringBuilder]::new()
[void]$SB.AppendLine("class $BaseClassName {`n")
# add all properties
foreach ($Property in $Properties) {
$Name = $Property.Name
$Type = $Property.TypeNameOfValue
if ($Name -in $HiddenProperty) {
[void]$SB.AppendLine(" hidden [$Type]`$$Name")
}
else {
[void]$SB.AppendLine(" [$Type]`$$Name")
}
}
# add constructor and end the class
[void]$SB.AppendLine("`n $BaseClassName () {}`n")
[void]$SB.AppendLine('}')
# output the class definition
$SB.ToString()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment