ScubaManDan
ScubaManDan

Reputation: 839

A property referencing another property in a PowerShell Class

Is it possible to have a property in a class reference another? For example, something like this. I've tried a few ways and I'm now not sure if I can do this...:

class TestClass {

    [string]
    $SQLInstanceName

    [string]
    $Server = "$($env:COMPUTERNAME)\$SQLInstanceName"

    [string]myResult()
    {
        return $this.Server
    }
}

....Thanks

Upvotes: 2

Views: 860

Answers (2)

alx9r
alx9r

Reputation: 4194

Yes. Here it is implemented in your class definition:

class TestClass {

    [string]
    $SQLInstanceName

    hidden $_Server = $($this | Add-Member ScriptProperty 'Server' `
        {
            # get
            "$($env:COMPUTERNAME)\$($this.SQLInstanceName)"
        }
    )

    [string]myResult()
    {
        return $this.Server
    }
}

To see this working, new up an instance and assign a value to SQLInstanceName.

$c = [TestClass]::new()
$c.SQLInstanceName = 'MyDB'

Then invoking

$c.Server
$c.myResult()

results in

ComputerName\MyDB
ComputerName\MyDB

Upvotes: 3

Matt
Matt

Reputation: 46680

You should be using $this if you want to refer to a non-static property/method in the same object just like you have done with your myResult() method. Also your current sample has no default value or constructor so the SQLInstanceName is blank so just adding $this, without setting the variable, might give you misleading results. The following example might be something to consider but it is flawed.

class TestClass {

    [string]$SQLInstanceName = "Test"

    [string]$Server = "$($env:COMPUTERNAME)\$($this.SQLInstanceName)"

    [string]myResult()
    {
        return $this.Server
    }
}

$tcobject = New-Object TestClass
$tcobject.myResult()

However this does not work if you change the SQLInstanceName property since you are just setting default values. Classes in v5 don't really have get and set truly implemented in the same way as a .Net class so you would have to roll your own solution for that as discussed in this answer but also on this blog about v5 classes in general.

So a simple solution would work like this to get what I think you want.

class TestClass {

    [string]
    $SQLInstanceName = "Test"

    [string]
    $Server = $env:COMPUTERNAME

    [string]myResult()
    {
        return "$($this.Server)\$($this.SQLInstanceName)"
    }
}

$tcobject = New-Object TestClass
$tcobject.SQLInstanceName = "server\prod"
$tcobject.myResult()

This would be a design choice but I would not be trying to dynamically change one property based on the value of another in this case. Since you are using a value of them combined a simple method could work.

Upvotes: 2

Related Questions