Search code examples
c#powershellmoduleextension-methods

Powershell C# Extension How too select the default property to display from nested property this is a list of objects


I have data structure that consists of two classes:

//--------------------------------------------------------
// These classes are external to the powershell extension
//
namespace thosepeskyexternalclasses
{
    public class person
    {
        public int Id {get; set}
        public string Name {get;set;}
    }

    public class activity 
    {
        public int Id {get; set;}
        public string activityName {get; set;}
        public List<person> participants {get ; set;}
    }
}

The class library also has a function called GetActivities() that will return a list of activities.

I then have the following C# PowerShell Extension:

//-----------------------------------------------------
// This is the powershell extension
using System.Management.Automation;
using thosepeskyexternalclasses

[Cmdlet(VerbsCommon.Get, "Activities", SupportsTransactions = false)]
public class GetActivity : PSCmdlet
{
    protected override void ProcessRecord()
    {
        base.ProcessRecord();
        // Get the activities
        List<activity> activities = GetActivities();

        WriteObject(activities);

    }
}

After building and loading the module the Get-Activities cmdlet is available and when call returns the list of activities. However, the list of participants in each activity is displayed using the Id property rather than the Name property.

I understand the use of the PSStandardMembers as it would apply to the list of activities but not how I would apply it the participants.

For example, If I call Get-Activities the returned objects look like this:

Id : 1
activityname: golf
participants: {1, 2, 4}

What I would like to have is:

Id : 1
activityname: golf
participants: {Susan, Frank, Jeff}

As a constraint I can't modify the model or the classes.


Solution

  • Presumably the actual person type doesn't have a .Name property because otherwise this issue shouldn't be reproducible, PowerShell should pick a property named Name and use it as it's default for-display property. However, an easy way you can define which property you want to display by default from an object is using Update-TypeData with the -DefaultDisplayProperty parameter

    Update-TypeData -TypeName thosepeskyexternalclasses.person -DefaultDisplayProperty Name
    

    Using this PowerShell Class definition as example:

    class Test {
        [int] $id
        [string] $otherprop
    }
    
    $testObject = @{
        test = @(
            [Test]@{ id = 1; otherprop = 'foo' }
            [Test]@{ id = 2; otherprop = 'bar' }
        )
    }
    

    Without default display property:

    PS /> $testObject
    
    # Name                           Value
    # ----                           -----
    # test                           {1, 2}
    

    With default display property:

    PS /> Update-TypeData -TypeName Test -DefaultDisplayProperty otherprop
    PS /> $testObject
    
    # Name                           Value
    # ----                           -----
    # test                           {foo, bar}