首页 > 解决方案 > Powershell:如何从另一个静态方法调用静态方法

问题描述

我有一类“utils”和一些静态方法。我想从另一种方法中调用一种方法。如果我使用 $this,它会告诉我“无法在静态方法或静态属性的初始化程序中访问非静态成员 'this'。” 但是没有 $this 就找不到方法。我也不想硬编码类名 - 但如果这是唯一的解决方案,那么我必须这样做。你能在这里点亮一些灯吗?环境:Win10/Powershell 7.1 下面请找代码

class MyDateUtils
{
    
    Static [DateTime] ToLocalTime([String]$fromDate,[String]$fromTZ, [String]$format)
    {
    
        if($fromTZ -eq $null -or $fromTZ -eq "")
        {
            $fromTZ = 'Eastern Standard Time'
        }
        
        $tz = [TimeZoneInfo]::FindSystemTimeZoneById($fromTZ)

        $nominalDate = FormatDate($fromDate, $format)

        $utcOffset = $tz.GetUtcOffset($nominalDate)

        $dto = [DateTimeOffset]::new($nominalDate.Ticks, $utcOffset)

        return $dto.LocalDateTime

       
    }
    
    Static [DateTime] FormatDate([String]$date)
    {
        return FormatDate($date, $null)
    }

    Static [DateTime] FormatDate([String]$date,[String]$format)
    {
    
        #$dateString = $date.split(' ')[0]
    
        if($format -ne $null -and $format -ne "")
        {
            return [Datetime]::ParseExact( $date, $format, $null)
        }
    
    
        $formatList =  'MM/dd/yyyy', 'MM/dd/yyyy HH:mm:ss', 'MM/dd/yyyy HH:mm',`
                       'M/d/yyyy', 'M/d/yyyy HH:mm:ss', 'M/d/yyyy HH:mm',  
                       'MM/d/yyyy', 'MM/d/yyyy HH:mm:ss', 'MM/d/yyyy HH:mm',
                       'M/dd/yyyy', 'M/dd/yyyy HH:mm:ss',    'M/dd/yyyy HH:mm',
                       'yyyy-MM-dd', 'yyyy-MM-dd HH:mm:ss', 'yyyy-MM-dd HH:mm'
    
    
        $result = $null
    
        foreach($f in $formatList)
        {
          try{
            $result = [Datetime]::ParseExact( $date, $f, $null)
          }catch {
            
          }
          
          if($result -ne $null)
          {
            return $result
          }
        }
    
        return $result
    }
    
    


} 

然后,如果我从命令行运行以下命令,则会收到以下错误:

[MyDateUtils]::ToLocalTime('2021-02-23 07:10', $null, $null)
line |
  14 |          $nominalDate = FormatDate($fromDate, $format)
     |                         ~~~~~~~~~~
     | The term 'FormatDate' is not recognized as a name of a cmdlet, function, script file, or executable
     | program. Check the spelling of the name, or if a path was included, verify that the path is correct
     | and try again.

如果我在 FormatDate 之前添加了 $this 然后填充静态/此错误感谢您的帮助

标签: powershell

解决方案


我不想硬编码类名 - 但如果这是唯一的解决方案,那么我必须这样做。

实际上,与 C# 不同,例如,您必须显式使用类名来引用类的静态成员,即使是在该类内部

使用简化示例:

以下 C# 类的(近)等效项:

// C#
public class Foo {
  public static string Bar() {
    // Calling fellow static function Baz() requires NO qualifier.
    return Baz();
  }
  static string Baz() {
    return "baz C#";
  }
}

在 PowerShell 中是以下内容:

# PowerShell
class Foo {
  static [string] Bar() {
    # To call the fellow static Baz() method,
    # you MUST use the class name explicitly.
    # Otherwise, due to PowerShell's *dynamic scoping*, PowerShell would 
    # look for a command named 'Baz' in the enclosing scope and its ancestors.
    return [Foo]::Baz()
  }
  hidden static [string] Baz() {
    return 'baz'
  }
}

注意:Baz()没有限定符和没有参数实际上是语法错误,但是有一个或多个参数 PowerShell 确实会Baz在运行时查找一个命名的命令——即使使用方法(...)语法(用分隔符括起来的参数列表,不适用于命令——参见此答案以获取更多信息。

PowerShell总是需要一个明确的限定符来进行类内部成员访问:

  • $this实例成员需要;例如,$this.PropA需要访问声明为的实例属性[string] $PropA,并$this.OtherMethod()调用其他实例方法OtherMethod

  • 对于静态成员,表示类本身的对象,在最简单的情况下是类型文字,例如[Foo],尤其是::而不是.,如上所示。

有关详细信息,请参阅概念about_Classes帮助主题。

虽然自动(隐式声明)$this变量是引用类实例的方便抽象,但类本身不存在类似变量,总是导致需要在类内部重复类名,这既有点麻烦又需要维护关心。

如果-且仅当-您从实例成员引用静态成员,则可以使用以下方法解决重复类名的需要$this.GetType()

class Foo {
  # Bar() is now an *instance* method.
  [string] Bar() {
    # Because $this is now defined to refer to the instance,
    # you can use $this.GetType() to refer to the class.
    return $this.GetType()::Baz()
  }
  hidden static [string] Baz() {
    return 'baz'
  }
}

[Foo]::new().Bar() # -> 'baz'

当然,具有类似于 的自动变量$this会有所帮助,例如$thisType(如果将来要支持接口$thisClass定义,则语义上会太窄)。

如果您对拥有这样一个变量感到足够强烈,我鼓励您在 PowerShell 的 GitHub 存储库中创建一个功能请求

笔记:

  • 考虑到 PowerShell 的动态范围,引入新的自动变量时的一个普遍问题 是潜在的名称冲突。

  • 类是在 PowerShell 发展的后期引入的,虽然 PowerShell 完全支持与预先存在的 .NET 类(类型)进行交互,但在 PowerShell 本身中定义它们的需求并不那么紧迫,特别是对于临时使用(使用创建的临时对象[pscustomobject] @{ ... }通常会这样做) )。虽然 PowerShell 的类支持永远不会赶上 C#,但正在考虑进行各种改进-请参阅GitHub 问题 #6652


推荐阅读