首页 > 解决方案 > Powershell 单例和 $this 行为

问题描述

我正处于重大重构和 PS OOP 教育的阵痛中,当前的主题是单例。我有一些程序状态数据想以单例形式提供,但我看到了一些奇怪的行为。

这适用于前两个 Write-Lines,但随后挂在第三个,它引用了第二个类。

class PxStatus {
    static [PxStatus] $singleton = $null
    [string]$Context = 'machine'
    [datetime]$StartTime = (Get-Date)

    static [PxStatus] Get() {
        if ([PxStatus]::singleton -eq $null) {
            [PxStatus]::singleton = [PxStatus]::new()
        }

        return [PxStatus]::singleton
    }
}

class pxLogFile {
    # Properties
    static [pxLogFile] $singleton = $null
    [string] $nameSeed = "PxTools $(([PxStatus]::Get()).Context) context"
    [string] $path = "$env:TEMP\$(([pxLogFile]::Get()).nameSeed) $((get-date).toString('yyyy-MM-dd-hh-mm-ss')).log"

    static [pxLogFile] Get() {
        if ([pxLogFile]::singleton -eq $null) {
            [pxLogFile]::singleton = [pxLogFile]::new()

        return [pxLogFile]::singleton
    }
}



CLS
Write-Host "$(([PxStatus]::Get()).Context)"
Write-Host "$(([PxStatus]::Get()).StartTime)"
Write-Host "$(([pxLogFile]::Get()).path)"

但是,如果我像这样在构造函数中处理路径,它就可以工作。

class PxStatus {
    static [PxStatus] $singleton = $null
    [string]$Context = 'machine'
    [datetime]$StartTime = (Get-Date)

    static [PxStatus] Get() {
        if ([PxStatus]::singleton -eq $null) {
            [PxStatus]::singleton = [PxStatus]::new()

            #([PxStatus]::singleton).Context = 'machine'
            #([PxStatus]::singleton).StartTime = Get-Date
        }

        return [PxStatus]::singleton
    }
}

class pxLogFile {
    # Properties
    static [pxLogFile] $singleton = $null
    [string] $nameSeed = "PxTools $(([PxStatus]::Get()).Context) context"
    [string] $path = $null

    static [pxLogFile] Get() {
        if ([pxLogFile]::singleton -eq $null) {
            [pxLogFile]::singleton = [pxLogFile]::new()

            ([pxLogFile]::singleton).Path = "$env:TEMP\$(([pxLogFile]::Get()).nameSeed) $((get-date).toString('yyyy-MM-dd-hh-mm-ss')).log"
        }

        return [pxLogFile]::singleton
    }
}



CLS
Write-Host "$(([PxStatus]::Get()).Context)"
Write-Host "$(([PxStatus]::Get()).StartTime)"
Write-Host "$(([pxLogFile]::Get()).path)

我认为问题在于访问同一个单例中的属性,就像我对 nameSeed 所做的那样。或者,我也可以在属性定义中使用它。

[string] $path = "$env:TEMP\$($this.nameSeed) $((get-date).toString('yyyy-MM-dd-hh-mm-ss')).log"

老实说,无论如何,哪个更具可读性。我只是想知道导致失败的第一个到底发生了什么?我是否通过不使用来创建某种奇怪的循环条件$this

标签: powershelloopsingleton

解决方案


[pxLogFile]::Get()调用嵌套在里面

[string] $path = "$env:TEMP\$(([pxLogFile]::Get()).nameSeed) $((get-date).toString('yyyy-MM-dd-hh-mm-ss')).log"

导致无限递归,最终导致堆栈溢出。

只需在初始化中直接引用$nameSeed另一个静态属性$path

class pxLogFile {
    # Properties
    static [pxLogFile] $singleton = $null
    [string] $nameSeed = "PxTools $(([PxStatus]::Get()).Context) context"
    # Refer to $nameSeed instead of to [pxLogFile]::Get()).nameSeed
    [string] $path = "$env:TEMP\$($nameSeed) $((get-date).toString('yyyy-MM-dd-hh-mm-ss')).log"

    static [pxLogFile] Get() {
        if ($null -eq [pxLogFile]::singleton) {
            [pxLogFile]::singleton = [pxLogFile]::new()
        }
        return [pxLogFile]::singleton
    }
}



推荐阅读