2009-02-13 93 views
3

我试图使用$ function:foo值和get-item函数:foo。所有尝试都成功修改临时函数对象,但重新分配给存储函数时(通过$ function:foo = ...或set-item function:foo ...),附加属性会丢失。如何将属性添加到PowerShell PSDrive上的函数对象“function:”?

这里是我的尝试的结果(全部失败):

设置

 
$=>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异常处理。这是这个语言的一些深奥的角落吗?

回答

4

我的第一个想法是,当你将这个属性附加到一个对象时,你将它附加到该对象的特定实例。当你的变量失去对该对象的引用时,任何有关该新属性的知识都将丢失。

我的猜测是下一次获取该项目时,您正在使用foo的属性(存储在函数提供程序中)创建一个新的FunctionInfo对象。

当您调用Get-Item或Get-ChildItem时,它将对象引用返回到代表基础项目的.NET类型。这些项目不会无限期地存在于内存中(设想每个本地驱动器上的每个文件都有一个FileInfo对象,并且每个映射的驱动器都驻留在内存中)。由于PowerShell每次调用Get-Item时都会创建一个新实例,因此您将获得基本的FunctionInfo对象。

如果您想要将属性添加到特定类型的所有项目中,可以使用PowerShell的可扩展类型系统。您可以创建自定义的.ps1xml文件,并将其加载到PowerShell会话中,该会话可以将属性添加到类型的每个实例。 PowerShell团队博客上的一些很好的例子在这里 - >Hate Add-MemberLeveraging the PowerShell Type Extensions to Get Documentation。编辑(解决评论):我理解你正在尝试做什么,但失败的原因是新属性被“嫁接”到一个PSObject包装器,允许实时添加属性。新属性永远不会是您从PSDrive中检索的那个FunctionInfo对象的一部分。

另外,函数提供者(函数:psdrive)没有存储该附加属性的机制。它知道并使用FunctionInfo对象。当您要求Function:PSDrive中的项目时,函数提供程序返回一个FunctionInfo对象。当你将一个函数保存到Function:PSDrive中时,提供者只能存储它知道如何处理的属性的值。可以编写一个自定义提供程序来处理来自PSObject包装器的新属性,但这不属于此提供程序的默认功能。

编辑#2:好吧,这一直在窃听我。 I blogged about a workaround

+0

我只想将属性附加到特定项目而不是全部类型。我赞同这个附件的临时性质。但我重新分配对象并将其保存到函数:PSDrive中。其他属性保留(有任何更改),但添加的属性丢失。 – rivy 2009-02-13 20:11:26