如何使用 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
你可以使用
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"
}
})
}
这就是我的做法
[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)"
}
});
迄今为止我发现的最佳解决方案是使用“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 -------------------------------------