为何按微软示例使用Add-Member为字符串添加ScriptMethod失败?
为什么用Add-Member给字符串对象添加ScriptMethod失败?
问题背景
我完全按照微软官方示例(Get-Help Add-Member -Examples)给对象添加ScriptMethod,但自己的代码却无法运行。
微软可正常运行的示例代码
$A = Get-ChildItem C:\Temp\test.txt $S = {[math]::Round(($this.Length / 1MB), 2)} $A | Add-Member -MemberType ScriptMethod -Name "SizeInMB" -Value $S $A.SizeInMB() # 输出结果: 0.43
我的代码及错误
$A = 'someTestText_andSome-more*Text' $S = { $first, $rest = Split-String -String $this $first + (Get-Culture).TextInfo.ToTitleCase($rest) -replace ' ' } $A | Add-Member -MemberType ScriptMethod -Name ToCamelCase -Value $S $A.ToCamelCase() # 错误信息: InvalidOperation: Method invocation failed because [System.String] does not contain a method named 'ToCamelCase'.
期望结果:someTestTextAndSomeMoreText
核心原因
问题出在字符串是.NET值类型,而微软示例里的FileInfo是引用类型:
- 引用类型(比如
FileInfo):Add-Member直接修改原对象实例,原变量能拿到修改后的结果。 - 值类型(比如
System.String):PowerShell管道会创建对象副本,Add-Member修改的是这个副本,原变量$A还是指向原来的字符串实例,自然找不到新增的方法。
另外你的脚本块里还有个小问题:PowerShell没有内置Split-String命令,得用-split运算符替代。
解决方法
方法1:用-PassThru参数获取修改后的对象
通过-PassThru让Add-Member返回修改后的副本,重新赋值给原变量:
$A = 'someTestText_andSome-more*Text' $S = { $parts = $this -split '[-_*]' $first = $parts[0] $rest = $parts[1..($parts.Count-1)] -join ' ' $first + (Get-Culture).TextInfo.ToTitleCase($rest) -replace ' ' } $A = $A | Add-Member -MemberType ScriptMethod -Name ToCamelCase -Value $S -PassThru $A.ToCamelCase()
方法2:把字符串包装成自定义对象
将字符串放入PSCustomObject(引用类型)后再添加方法:
$A = [PSCustomObject]@{ Content = 'someTestText_andSome-more*Text' } $S = { $parts = $this.Content -split '[-_*]' $first = $parts[0] $rest = $parts[1..($parts.Count-1)] -join ' ' $first + (Get-Culture).TextInfo.ToTitleCase($rest) -replace ' ' } $A | Add-Member -MemberType ScriptMethod -Name ToCamelCase -Value $S $A.ToCamelCase()
内容的提问来源于stack exchange,提问作者jeremywat
相关产品推荐
相关产品推荐

