Powershell类实现获取设置属性

问题描述 投票:0回答:3

如何使用 PowerShell 类实现获取/设置属性? 请看下面我的例子:

Class TestObject
{
  [DateTime]$StartTimestamp = (Get-Date)
  [DateTime]$EndTimestamp = (Get-Date).AddHours(2)

  [TimeSpan] $TotalDuration {
    get {
      return ($this.EndTimestamp - $this.StartTimestamp)
    }
  }
  
  hidden [string] $_name = 'Andreas'
  [string] $Name {
    get {
      return $this._name
    }
    set {
      $this._name = $value
    }
  }
}

New-Object TestObject
powershell class properties getter-setter
3个回答
15
投票

你可以使用

Add-Member ScriptProperty
来实现一种getter和setter:

class c {
    hidden $_p = $($this | Add-Member ScriptProperty 'p' `
        {
            # get
            "getter $($this._p)"
        }`
        {
            # set
            param ( $arg )
            $this._p = "setter $arg"
        }
    )
}

新建它会调用

$_p
的初始化程序,它会添加 scriptproperty
p
:

PS C:\> $c = [c]::new()

使用属性

p
会产生以下结果:

PS C:\>$c.p = 'arg value'
PS C:\>$c.p
getter setter arg value

这种技术有一些缺陷,主要与

Add-Member
行的冗长和容易出错有关。 为了避免这些陷阱,我实现了
Accessor
,您可以在 here 找到它。

使用

Accessor
代替
Add-Member
可以进行大量错误检查,并将原始类实现简化为:

class c {
    hidden $_p = $(Accessor $this {
        get {
            "getter $($this._p)"
        }
        set {
            param ( $arg )
            $this._p = "setter $arg"
        }
    })
}

1
投票

这就是我的做法

  [string]$BaseCodeSignUrl;   # Getter defined in __class_init__.  Declaration allows intellisense to pick up property
  [string]$PostJobUrl;        # Getter defined in __class_init__.  Declaration allows intellisense to pick up property
  [hashtable]$Headers;        # Getter defined in __class_init__.  Declaration allows intellisense to pick up property
  [string]$ReqJobProgressUrl; # Getter defined in __class_init__.  Declaration allows intellisense to pick up property

  # Powershell lacks a way to add get/set properties.  This is a workaround
  hidden $__class_init__ = $(Invoke-Command -InputObject $this -NoNewScope -ScriptBlock {
    $this | Add-Member -MemberType ScriptProperty -Name 'BaseCodeSignUrl' -Force -Value {
      if ($this.Production) { [CodeSign]::CodeSignAPIUrl } else { [CodeSign]::CodeSignTestAPIUrl }
    }
    $this | Add-Member -MemberType ScriptProperty -Name 'PostJobUrl' -Force -Value {
      "$($this.BaseCodeSignUrl)/Post?v=$([CodeSign]::ServiceApiVersion)"
    }
    $this | Add-Member -MemberType ScriptProperty -Name 'Headers' -Force -Value {
      @{
        _ExpireInMinutes=[CodeSign]::Timeout.Minutes;
        _CodeSigningKey=$this.Key;
        _JobId=$this.JobId;
        _Debug=$this.Dbg;
        _Token=$this.Token;
      }
    }
    $this | Add-Member -MemberType ScriptProperty -Name 'ReqJobProgressUrl' -Force -Value {
      "$($this.BaseCodeSignUrl)Get?jobId=$($this.JobId)"
    }
  });

0
投票

迄今为止我发现的最佳解决方案是使用“Update-TypeData”。

关于_类_属性 更新类型数据

以下文件是如何使用它的小示例。 初始化.psq

#-------------------------------------------------------------------------------
# (c) public domain

function InitMyClass
{
    <#
    .SYNOPSIS
    Static constuctor for MyClass.
    #>
    [OutputType( [void] )]
    [CmdletBinding()]
    param ()
    
    #-------------------------------------------------------------------------------
    # Add a new Property.
    # You need to use a string. [MyClass].Name will not work.

    Update-TypeData `
        -TypeName    'MyClass' `
        -MemberName  'Help' `
        -MemberType  ScriptProperty `
        -Value       { return GetHelpMyClass $this } `
        -SecondValue { param( [string]$psHelp ) 

SetHelpMyClass $this $psHelp }

    #-------------------------------------------------------------------------------
    # Just fpr the fun of it.

    Remove-Item Function:InitMyClass

} # function InitMyClass

#-------------------------------------------------------------------------------

return

#------------------------------------- EOF -------------------------------------

Func.ps1

#-------------------------------------------------------------------------------
# (c) public domain

function GetHelpMyClass
{
    <#
    .SYNOPSIS
    Static constuctor for MyClass.
    #>
    [OutputType( [string] )]
    [CmdletBinding()]
    param
    (
        [Parameter( Mandatory = $true )]
        [MyClass]
        $pcThis
    )

    #-------------------------------------------------------------------------------
    # Do what ever you want and return the value.

    return ('Help: ' + $pcThis.msHelp )

} # function InitMyClass

function SetHelpMyClass
{
    <#
    .SYNOPSIS
    Does somthing and may store it in the instance.

    .NOTES
    Parameter may have alll attributes.
    #>
    [OutputType( [void] )]
    [CmdletBinding()]
    param
    (
        [Parameter( Mandatory = $true )]
        [MyClass]
        $pcThis,
        [Parameter( Mandatory = $true )]
        [AllowEmptyString()]
        [string]
        $psNewHelp
    )
    #-------------------------------------------------------------------------------
    # Do whatever you want and store the value.

    if( [string]::IsNullOrEmpty( $psNewHelp ))
    {
        $pcThis.msHelp = 'No help.'
        return

    } # if( [string]::IsNullOrEmpty( $psNewHelp ))

    $pcThis.msHelp = $psNewHelp

} # function InitMyClass

#-------------------------------------------------------------------------------

return

#------------------------------------- EOF -------------------------------------

类.ps1

#-------------------------------------------------------------------------------
# (c) public domain

#-------------------------------------------------------------------------------
# Avoid double definition of the class
# To debug initiator issues break on the first access to the class (next 
# statement) and step into.

if( [MyClass]::mbExist )
{ return }

Write-Error 'If this point is reached the class has an issue.'

#-------------------------------------------------------------------------------

Class MyClass
{
    #-------------------------------------------------------------------------------
    # visible properties

    #-------------------------------------------------------------------------------
    # Hiddden property for the Get/Set functions.
    # Is not neccesssary but for this sample.

    hidden [string]$msHelp

    #-------------------------------------------------------------------------------
    # Hidden static
    # Avoid double definition of the class.

    hidden static [bool]$mbExist = $true

    #-------------------------------------------------------------------------------
    # Constructor

    MyClass()
    {
        SetHelpMyClass $this 'No help given'

    } # MyClass() 
    MyClass(
        [string]$psNewHelp
    )
    {
        SetHelpMyClass $this $psNewHelp

    } # MyClass( [string] )

    #-------------------------------------------------------------------------------
    # Static Constructor

    static MyClass()
    {
        InitMyClass

    } # static MyClass()

} # Class MyClass

#-------------------------------------------------------------------------------

return

#------------------------------------- EOF -------------------------------------

测试.ps1

#-------------------------------------------------------------------------------
# (c) public domain

#-------------------------------------------------------------------------------
# Get the class

. .\Init.ps1
. .\Func.ps1
. .\Class.ps1

#-------------------------------------------------------------------------------
# Test the class

Write-Output '#'*80
Write-Output '[MyClass]$gcHelp = [MyClass]::new()'
[MyClass]$gcHelp = [MyClass]::new()

$gcHelp.msHelp
$gcHelp.Help

Write-Output ( '#' * 80 )
Write-Output '$gcHelp.Help = 'there is help''
$gcHelp.Help = 'there is help'
$gcHelp.msHelp
$gcHelp.Help

Write-Output ( '#' * 80 )
Write-Output '$gcHelp.Help = $null'
$gcHelp.Help = $null
$gcHelp.msHelp
$gcHelp.Help

Write-Output ( '#' * 80 )
Write-Output '$gcHelp.msHelp = 'there is another help''
$gcHelp.msHelp = 'there is another help'
$gcHelp.msHelp
$gcHelp.Help

Write-Output ( '#' * 80 )
Write-Output 'Write-Output '#'*80'
$gcHelp.msHelp = $null
$gcHelp.msHelp
$gcHelp.Help

#------------------------------------- EOF -------------------------------------
© www.soinside.com 2019 - 2024. All rights reserved.