Micah R Ledbetter
Micah R Ledbetter

Reputation: 1096

Change the type name of a Powershell object from PSCustomObject to something I choose?

I have a script that uses custom objects. I create them with a pseudo-constructor like this:

function New-TestResult 
{
    $trProps = @{
        name = "";
        repo = @{};

        vcs   = $Skipped;

        clean = New-StageResult; # This is another pseudo-constructor
        build = New-StageResult; # for another custom object.
        test  = New-StageResult; #     - Micah

        start = get-date;
        finish = get-date;
    }

    $testResult = New-Object PSObject -Property $trProps
    return $testResult
}

These are useful because they can be passed to something like ConvertTo-Csv or ConvertTo-Html (unlike, say, a hashtable, which would otherwise accomplish my goals). They are typed as PSCustomObject objects. This code:

$tr = new-testresult
$tr.gettype()

returns this:

IsPublic IsSerial Name                     BaseType
-------- -------- ----                     --------
True     False    PSCustomObject           System.Object

Can I change the Name field returned there from PSCustomObject to something else?

Later on when I'm collating test results, I'll pass to another function what will sometimes be an individual result, and sometimes an array of results. I need to be able to do something different depending on which of those I get.

Any help is appreciated.

Upvotes: 6

Views: 11177

Answers (3)

Justin
Justin

Reputation: 1503

A more efficient way to get the custom TypeName is:

$x.psobject.TypeNames[0] 

rather than using get-member

if there is no custom typename it will simply return System.Management.Automation.PSCustomObject

Upvotes: 0

Andy
Andy

Reputation: 1423

I created a special cmdlet to detect the type name of the object under the powershell quickly.

For custom objects,.getType() Method cannot get the ETS type name.


function Get-PsTypeName {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        $InputObject
    )
        
    begin {

    }
        
    process {
        ((Get-Member -InputObject $InputObject)[0].TypeName)
    }
        
    end {
    }
}

Upvotes: 1

Keith Hill
Keith Hill

Reputation: 202092

Sure, try this after creating $testResult:

$testResult.psobject.TypeNames.Insert(0, "MyType")

The heart of the PowerShell extended type system is the psobject wrapper (at least in V1 and V2). This wrapper allows you to add properties and methods, modify type names list and get at the underlying .NET object e.g.:

C:\PS > $obj = new-object psobject
C:\PS > $obj.psobject


BaseObject          :
Members             : {string ToString(), bool Equals(System.Object obj), int GetHashCode(), type GetType()}
Properties          : {}
Methods             : {string ToString(), bool Equals(System.Object obj), int GetHashCode(), type GetType()}
ImmediateBaseObject :
TypeNames           : {System.Management.Automation.PSCustomObject, System.Object}

Or try this from the prompt:

C:\PS> $d = [DateTime]::Now
C:\PS> $d.psobject
...

Upvotes: 12

Related Questions