如何在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
相关产品推荐
相关产品推荐

