You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PowerShell静态方法中动态引用类与静态属性?

在PowerShell中实现Active Record模式的动态类引用

我有一个名为DatabaseObject的超类,它实现了Active Record设计模式,所有访问数据库的类都将继承它。

其他语言的实现参考

PHP

在PHP中,可以通过self::和static::实现动态类引用,代码示例:

class DatabaseObject {
    protected static $database;
    ...

    public static function set_database($database) {
        self::$database = $database;
    }

    public static function find_all() {
        $sql = "SELECT * FROM " . static::$table_name;
        return static::find_by_sql($sql);
    }

    protected static function instantiate($record) {
        $object = new static;
        foreach($record as $property => $value) {
            if( property_exists($object, $property) ) {
                $object->$property = $value;
            }
        }
        return $object;
    }
    ...
}

这里static::会动态指向调用该方法的子类,甚至可以直接用new static创建子类实例。

Python

Python通过类方法的cls参数实现动态引用:

@classmethod
def _instantiate(cls, record):
    # 创建子类实例
    obj = cls()
    # 为实例属性赋值逻辑
    ...
    return obj

TypeScript

TypeScript在静态方法中用this指代当前类:

protected static instantiate(record: object): object {
    const obj = new this();
    // 为实例属性赋值逻辑
    ...
    return obj;
}

PowerShell的问题与解决方案

目前我只能写出这样的代码:

static [void]SetDatabase($Database) {
        [DatabaseObject]::Database = $Database
}

必须显式写出类名,一旦类被继承,这种写法就失效了。

正确实现方式

在PowerShell的静态方法中,可以通过$MyInvocation.MyCommand.DeclaringType获取当前执行方法的类类型(无论是父类还是子类),以此实现动态类引用。

1. 动态设置静态属性

static [void] SetDatabase($Database) {
    # 获取当前调用该方法的类类型
    $declaringType = $MyInvocation.MyCommand.DeclaringType
    # 动态设置静态属性
    $declaringType::Database = $Database
}

2. 动态创建子类实例

static [object] Instantiate($record) {
    $declaringType = $MyInvocation.MyCommand.DeclaringType
    # 创建当前类的实例(子类调用时就是子类实例)
    $obj = New-Object -TypeName $declaringType
    # 遍历记录为实例属性赋值
    foreach ($property in $record.PSObject.Properties) {
        if ($obj.PSObject.Properties.Name -contains $property.Name) {
            $obj.$($property.Name) = $property.Value
        }
    }
    return $obj
}

3. 动态调用其他静态方法

static [System.Collections.ArrayList] FindAll() {
    $declaringType = $MyInvocation.MyCommand.DeclaringType
    # 获取子类的静态表名属性
    $tableName = $declaringType::TableName
    $sql = "SELECT * FROM $tableName"
    # 动态调用子类的FindBySql方法
    return $declaringType::FindBySql($sql)
}

4. 处理返回类型问题

如果静态方法直接返回自定义子类实例存在类型约束,可以返回包含子类实例的ArrayList:

static [System.Collections.ArrayList] FindBySql($sql) {
    $declaringType = $MyInvocation.MyCommand.DeclaringType
    $database = $declaringType::Database
    # 执行SQL查询获取记录(示例逻辑)
    $records = $database.Query($sql)
    $resultList = New-Object -TypeName System.Collections.ArrayList
    foreach ($record in $records) {
        $obj = $declaringType::Instantiate($record)
        [void]$resultList.Add($obj)
    }
    return $resultList
}

更新(感谢@Santiago Squarzon的贡献):
为了帮助后续开发者,补充细节:

  • 该类包含实例属性和方法,示例中为简洁未展示。
  • 静态方法需要支持设置静态属性、调用(带参数的)其他静态方法。
  • 静态方法直接返回自定义子类实例可能存在类型问题,推荐返回包含子类实例的ArrayList。

内容的提问来源于stack exchange,提问作者Leonardo Pinheiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:43:17