我试过使用$ function:foo值和get-item函数:foo . 所有尝试都成功修改了临时函数对象,但在重新分配给存储函数时(通过$ function:foo = ...或set-item function:foo ...),缺少附加属性 .
以下是我尝试的结果(全部失败):
Build
$=>function foo { "foo" }
$=>$f = $function:foo
$=>$f = $f | add-member noteproperty bar BARvalue -pass
$=>$f | gm b*
TypeName: System.Management.Automation.ScriptBlock
Name MemberType Definition
---- ---------- ----------
bar NoteProperty System.String bar=BARvalue
#1
$=>set-item function:f $f -force
$=>$function:foo | gm b*
>
#2
$=>$function:f = $f
$=>$function:foo | gm b*
>
#3
$=>$f = get-item function:foo
$=>$f | gm
TypeName: System.Management.Automation.FunctionInfo
Name MemberType Definition
---- ---------- ----------
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
ToString Method System.String ToString()
PSDrive NoteProperty System.Management.Automation.PSDriveInfo PSDrive=Function
PSIsContainer NoteProperty System.Boolean PSIsContainer=False
PSPath NoteProperty System.String PSPath=Microsoft.PowerShell.Core\Function::foo
PSProvider NoteProperty System.Management.Automation.ProviderInfo PSProvider=Microsoft....
CmdletBinding Property System.Boolean CmdletBinding {get;}
CommandType Property System.Management.Automation.CommandTypes CommandType {get;}
DefaultParameterSet Property System.String DefaultParameterSet {get;}
Definition Property System.String Definition {get;}
Description Property System.String Description {get;set;}
Module Property System.Management.Automation.PSModuleInfo Module {get;}
ModuleName Property System.String ModuleName {get;}
Name Property System.String Name {get;}
Options Property System.Management.Automation.ScopedItemOptions Options {get;set;}
Parameters Property System.Collections.Generic.Dictionary`2[[System.String, mscorli...
ParameterSets Property System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Man...
ScriptBlock Property System.Management.Automation.ScriptBlock ScriptBlock {get;}
Visibility Property System.Management.Automation.SessionStateEntryVisibility Visibi...
$=>$f = $f | add-member noteproperty bar barValue -pass
$=>$f | gm b*
TypeName: System.Management.Automation.FunctionInfo
Name MemberType Definition
---- ---------- ----------
bar NoteProperty System.String bar=barValue
$=>set-item function:foo $f
$=>$function:foo | gm b*
>
不知道我做错了什么 . 看来这些属性在重新分配时被剥离了 . 那是对的吗?定义的行为?我没有看到任何文档说FunctionInfo对象或ScriptBlocks被异常处理 . 这是语言的一些深奥的角落吗?
1 回答
我首先想到的是,当您将此属性附加到对象时,您将它附加到该对象的特定实例 . 当您的变量丢失对该对象的引用时,对该新属性的任何知识都将丢失 .
我的猜测是下次你得到那个项目时,你正在用foo的属性创建一个新的FunctionInfo对象(存储在函数提供程序中) .
当您调用Get-Item或Get-ChildItem时,它会返回对表示基础项的.NET类型的对象引用 . 这些项目无限期地存在于内存中(想象一下每个本地驱动器上的每个文件的FileInfo对象以及存储在内存中的每个映射驱动器 . ouch) . 由于PowerShell每次调用Get-Item时都会创建一个新实例,因此您将获得基本的FunctionInfo对象 .
如果要为特定类型的所有项添加属性,可以使用PowerShell的可扩展类型系统 . 您可以创建自定义.ps1xml文件并将其加载到PowerShell会话中,该会话可以向某个类型的每个实例添加属性 . PowerShell团队博客上的一些很好的示例在这里 - > Hate Add-Member和Leveraging the PowerShell Type Extensions to Get Documentation .
EDIT(寻址评论):我理解你要做的是什么,但失败的原因是新属性被“嫁接”到PSObject包装器上,允许动态添加属性 . 新属性永远不会是您从PSDrive中检索的FunctionInfo对象的一部分 .
此外,函数提供程序(函数:psdrive)没有用于存储该附加属性的机制 . 它知道并使用FunctionInfo对象 . 当您从Function:PSDrive中请求某个项时,Function提供程序返回一个FunctionInfo对象 . 将函数保存到Function:PSDrive时,提供程序只能存储它知道如何处理的属性的值 . 可以编写一个自定义提供程序来处理PSObject包装器中的新属性,但这不是此提供程序中默认功能的一部分 .
编辑#2:好的,这一直困扰着我 . I blogged about a workaround .