Search code examples
c#powershellpowershell-2.0powershell-3.0

How to create real objects with behavior (methods) in PowerShell?


Probably this question has been answered before.... but I have not found a specific answer to my needs.

BTW I'm using PowerShell 3

Well, I'm new in PowerShell but I have a lot of experience as a C# developer, so working with objects is very important to me.

So I'm wondering if there's a clean way to apply OOP concepts (well not all of them, though that would be awesome) in a PowerShell script, for example there are specific things that I would like to do.

Note: I'm aware that I can write C# code in PowerShell to create DTO's and also that I can create PowerShell binary modules in C#, I have done that in the past, but what I'm looking for now is the ability to write all my code in PowerShell but in an Object Oriented way.

Things I would like to do:

  • Create an object in PowerShell, and expose a function written in PowerShell as well, something like this:

    function New-Person
    (
        [Parameter()][string]$firstName
    )
    {
        function Walk()
        {
            Write-Host "Walking...";
        }
    
        $person = New-Object psobject;
    
        $person | Add-Member -MemberType NoteProperty -Name FirstName -Value $firstName;
    
        #This line does not work
        #$person | Add-Member -MemberType CodeMethod -Name Walk -Value Walk;
    
        return $person;
    }
    
    $MyPerson = New-Person -firstName "JP";
    
    $MyPerson;
    
    #This line does not work
    $MyPerson.Walk();
    
  • Encapsulate behavior, which means create functions inside my object and then mark them as private

  • [Nice to have]. Create base classes so I can inherit and specialize my behavior overriding methods

  • [Nice to have]. Create interfaces so I can start thinking in unit testing in isolation my PowerShell methods (I know there are tools like Pester to do this I'm just focusing on OOP features)

What I have done so far is creating objects with properties only (DTO's) but I'd like to add behavior to my objects

I'd appreciate if you guys point me in the right direction


Solution

  • Two options to create object with methods:

    1. Add-Member
    2. New-Module -AsCustomObject

    Code samples:

    $person | Add-Member -MemberType ScriptMethod -Value {
        'I do stuff!'
    }
    
    $person = New-Module -AsCustomObject -ScriptBlock {
        $Property = 'value'
        [string]$Other = 'Can be strongly typed'
    
        function MyMethod {
            'I do stuff!'
        }
    
    }
    

    EDIT: speaking of private/ public... In latter example property won't show up "by default". You can decide what is public using Export-ModuleMember and specify -Variable (properties) and/or -Function (methods) that will be public. Without explicit Export-ModuleMember it will behave same as in "normal" module - export only functions (methods).