我尝试使用$ function:foo值和get-item函数:foo。所有尝试都成功修改了临时函数对象,但在重新分配给存储函数时(通过$ function:foo = ...或set-item function:foo ...),缺少附加属性。
以下是我尝试的结果(全部失败):
设置
$=>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被异常处理。这是语言的一些深奥的角落吗?
答案 0 :(得分:4)
我首先想到的是,当您将此属性附加到对象时,您将它附加到该对象的特定实例。当您的变量丢失对该对象的引用时,对该新属性的任何知识都将丢失。
我的猜测是下次你得到那个项目时,你正在用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。
编辑(解决评论):我理解你要做的是什么,但失败的原因是新属性被“嫁接”到PSObject包装器上,允许动态添加属性。新属性永远不会是您从PSDrive中检索的FunctionInfo对象的一部分。
此外,函数提供程序(函数:psdrive)没有用于存储该附加属性的机制。它知道并使用FunctionInfo对象。当您从Function:PSDrive中请求某个项时,Function提供程序返回一个FunctionInfo对象。将函数保存到Function:PSDrive时,提供程序只能存储它知道如何处理的属性的值。可以编写一个自定义提供程序来处理PSObject包装器中的新属性,但这不是此提供程序中默认功能的一部分。
编辑#2:好的,这一直困扰着我。 I blogged about a workaround