2009-02-13 51 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