Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to override the Getter/Setter functions in a powershell 5 class?

Tags:

powershell

I recently started creating classes with powershell 5. While I was following this awesome guide https://xainey.github.io/2016/powershell-classes-and-concepts/#methods

I was wondering if it is possible to override the get_x and set_x methods.

Example:

Class Foobar2 {
    [string]$Prop1    
}

$foo = [Foobar2]::new()
$foo | gm



Name        MemberType Definition                    
----        ---------- ----------                    
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()             
GetType     Method     type GetType()                
ToString    Method     string ToString()             
Prop1       Property   string Prop1 {get;set;}  

I would like to do it because I think it would be easier for other to access the properties than using my custom Get and Set methods:

Class Foobar {
    hidden [string]$Prop1

    [string] GetProp1() {
        return $this.Prop1
    }

    [void] SetProp1([String]$Prop1) {
        $this.Prop1 = $Prop1
    }
}
like image 436
OCram85 Avatar asked Dec 05 '16 15:12

OCram85


2 Answers

Unfortunately the new Classes feature does not have facilities for getter/setter properties like you know them from C#.

You can however add a ScriptProperty member to an existing instance, which will exhibit similar behavior as a Property in C#:

Class FooBar
{
    hidden [string]$_prop1
}

$FooBarInstance = [FooBar]::new()
$FooBarInstance |Add-Member -Name Prop1 -MemberType ScriptProperty -Value {
    # This is the getter
    return $this._prop1
} -SecondValue {
    param($value)
    # This is the setter
    $this._prop1 = $value
}

Now you can access $_prop1 through the Prop1 property on the object:

$FooBarInstance.Prop1
$FooBarInstance.Prop1 = "New Prop1 value"
like image 183
Mathias R. Jessen Avatar answered Sep 17 '22 02:09

Mathias R. Jessen


Just to expand on Mathias's answer...

You can include the "add-member" part to a constructor for the class so that it will automagically be added simply by instantiating the class.

Using Mathias's answer as an example:

Class FooBar
{
    hidden [string]$_prop1

    FooBar(){
        $this | Add-Member -Name Prop1 -MemberType ScriptProperty -Value {
            # This is the getter
            return $this._prop1
        } -SecondValue {
            param($value)
            # This is the setter
            If ($value -eq 'foo'){$value = 'bar'}
            $this._prop1 = $value
        }
    }
}

Creating a class method with the same name as the class will override the "constructor" for the class. The section of code in that method will run every time you create a new "foobar" object. Here we are incorporating the Add-Member cmdlet to add the scriptproperty for us just from creating the object.

$FooBarInstance = [FooBar]::new()

$FooBarInstance.Prop1 = 'Egon Spenglar'
Write-host $FooBarInstance.Prop1 -ForegroundColor Green

If you pass anything into it (as in assignment in this case), it will change the _Prop1 property to equal whatever you pass into it. (in this case "Egon Spenglar"). _Prop1 is a "Hidden" property so that you normally wont see it on the object, we're just using it to store and retrieve information with this added script property.

Then, if you call the Prop1 property without any arguments, it will just return the value in _Prop1.

$FooBarInstance.Prop1 = 'foo'
Write-host $FooBarInstance.Prop1 -ForegroundColor Green

And as an example as to why you might want to do something like this, there is a little logic added to the "Add-Member" cmdlet that checks to see if you are passing in the string "foo", and if so, it will store "bar" instead.

This second example will return "bar".

like image 29
Rob Traynere Avatar answered Sep 21 '22 02:09

Rob Traynere