I've attempted using the $function:foo value and get-item function:foo. All attempts succeed in modifying the temporary function object, but the additional property is missing when reassigned to the stored function (either through $function:foo = ... or set-item function:foo ...).
我尝试使用$ function:foo值和get-item函数:foo。所有尝试都成功修改了临时函数对象,但在重新分配给存储函数时(通过$ function:foo = ...或set-item function:foo ...),缺少附加属性。
Here are the results of my attempts (all fail):
以下是我尝试的结果(全部失败):
Setup
$=>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* >
Not sure what I'm doing wrong. It seems like the properties are being stripped out when reassigned. Is that correct? the defined behavior? I haven't seen any documentation saying that FunctionInfo objects or ScriptBlocks are treated unusually. Is this some esoteric corner of the language?
不知道我做错了什么。看起来这些属性在重新分配时被剥离了。那是对的吗?定义的行为?我没有看到任何文档说FunctionInfo对象或ScriptBlocks被异常处理。这是语言的一些深奥的角落吗?
1 个解决方案
#1
My first thought is when you are attaching this property to an object, you are attaching it to a specific instance of that object. When your variable losses the reference to that object, any knowledge of that new property is lost.
我首先想到的是,当您将此属性附加到对象时,您将它附加到该对象的特定实例。当您的变量丢失对该对象的引用时,对该新属性的任何知识都将丢失。
My guess is the next time you get that item, you are creating a new FunctionInfo object with foo's properties (as stored in the function provider).
我的猜测是下次你得到那个项目时,你正在用foo的属性创建一个新的FunctionInfo对象(存储在函数提供程序中)。
When you call Get-Item or Get-ChildItem, it returns object references to the .NET types that represent the underlying items. Those items do not exist in memory indefinitely (imagine a FileInfo object for every file on every local drive and every mapped drive living in memory.. ouch). Since PowerShell is creating a new instance every time you call Get-Item, you are getting the basic FunctionInfo object.
当您调用Get-Item或Get-ChildItem时,它返回对表示基础项的.NET类型的对象引用。这些项目无限期地存在于内存中(假设每个本地驱动器上的每个文件都有一个FileInfo对象,并且每个映射的驱动器都存在于内存中... ouch)。由于PowerShell每次调用Get-Item时都会创建一个新实例,因此您将获得基本的FunctionInfo对象。
If you want to add a property to all items of a particular type, you can with PowerShell's extensible type system. You can create a custom .ps1xml file and load that into a PowerShell session that can add a property to every instance of a type. Some great examples on the PowerShell Team Blog are here -> Hate Add-Member and Leveraging the PowerShell Type Extensions to Get Documentation.
如果要将属性添加到特定类型的所有项目,可以使用PowerShell的可扩展类型系统。您可以创建自定义.ps1xml文件并将其加载到PowerShell会话中,该会话可以向某个类型的每个实例添加属性。 PowerShell团队博客上的一些很好的示例在这里 - >仇恨添加成员并利用PowerShell类型扩展来获取文档。
EDIT (addressing comment): I understand what you are trying to do, but the failure is due to the new property being "grafted" on to a PSObject wrapper that allows for the on-the-fly addition of properties. The new property is never really part of that FunctionInfo object that you are retrieving from the PSDrive.
EDIT(寻址评论):我理解你要做的是什么,但失败的原因是新属性被“嫁接”到PSObject包装器上,允许动态添加属性。新属性永远不会是您从PSDrive中检索的FunctionInfo对象的一部分。
In addition, the function provider (the function: psdrive), does not have a mechanism for storing that additional property. It knows and works with FunctionInfo objects. When you ask for an item from the Function: PSDrive, the Function provider returns a FunctionInfo object. When you save a function to the Function: PSDrive, the provider can only store values for properties it knows how to handle. One could write a custom provider that would handle new properties from the PSObject wrapper, but that is not part of the default functionality in this provider.
此外,函数提供程序(函数:psdrive)没有用于存储该附加属性的机制。它知道并使用FunctionInfo对象。当您从Function:PSDrive中请求一个项目时,Function提供程序返回一个FunctionInfo对象。将函数保存到Function:PSDrive时,提供程序只能存储它知道如何处理的属性的值。可以编写一个自定义提供程序来处理PSObject包装器中的新属性,但这不是此提供程序中默认功能的一部分。
EDIT #2: Ok, this has been bugging me. I blogged about a workaround.
编辑#2:好的,这一直困扰着我。我在博客上写了一个解决方法。
#1
My first thought is when you are attaching this property to an object, you are attaching it to a specific instance of that object. When your variable losses the reference to that object, any knowledge of that new property is lost.
我首先想到的是,当您将此属性附加到对象时,您将它附加到该对象的特定实例。当您的变量丢失对该对象的引用时,对该新属性的任何知识都将丢失。
My guess is the next time you get that item, you are creating a new FunctionInfo object with foo's properties (as stored in the function provider).
我的猜测是下次你得到那个项目时,你正在用foo的属性创建一个新的FunctionInfo对象(存储在函数提供程序中)。
When you call Get-Item or Get-ChildItem, it returns object references to the .NET types that represent the underlying items. Those items do not exist in memory indefinitely (imagine a FileInfo object for every file on every local drive and every mapped drive living in memory.. ouch). Since PowerShell is creating a new instance every time you call Get-Item, you are getting the basic FunctionInfo object.
当您调用Get-Item或Get-ChildItem时,它返回对表示基础项的.NET类型的对象引用。这些项目无限期地存在于内存中(假设每个本地驱动器上的每个文件都有一个FileInfo对象,并且每个映射的驱动器都存在于内存中... ouch)。由于PowerShell每次调用Get-Item时都会创建一个新实例,因此您将获得基本的FunctionInfo对象。
If you want to add a property to all items of a particular type, you can with PowerShell's extensible type system. You can create a custom .ps1xml file and load that into a PowerShell session that can add a property to every instance of a type. Some great examples on the PowerShell Team Blog are here -> Hate Add-Member and Leveraging the PowerShell Type Extensions to Get Documentation.
如果要将属性添加到特定类型的所有项目,可以使用PowerShell的可扩展类型系统。您可以创建自定义.ps1xml文件并将其加载到PowerShell会话中,该会话可以向某个类型的每个实例添加属性。 PowerShell团队博客上的一些很好的示例在这里 - >仇恨添加成员并利用PowerShell类型扩展来获取文档。
EDIT (addressing comment): I understand what you are trying to do, but the failure is due to the new property being "grafted" on to a PSObject wrapper that allows for the on-the-fly addition of properties. The new property is never really part of that FunctionInfo object that you are retrieving from the PSDrive.
EDIT(寻址评论):我理解你要做的是什么,但失败的原因是新属性被“嫁接”到PSObject包装器上,允许动态添加属性。新属性永远不会是您从PSDrive中检索的FunctionInfo对象的一部分。
In addition, the function provider (the function: psdrive), does not have a mechanism for storing that additional property. It knows and works with FunctionInfo objects. When you ask for an item from the Function: PSDrive, the Function provider returns a FunctionInfo object. When you save a function to the Function: PSDrive, the provider can only store values for properties it knows how to handle. One could write a custom provider that would handle new properties from the PSObject wrapper, but that is not part of the default functionality in this provider.
此外,函数提供程序(函数:psdrive)没有用于存储该附加属性的机制。它知道并使用FunctionInfo对象。当您从Function:PSDrive中请求一个项目时,Function提供程序返回一个FunctionInfo对象。将函数保存到Function:PSDrive时,提供程序只能存储它知道如何处理的属性的值。可以编写一个自定义提供程序来处理PSObject包装器中的新属性,但这不是此提供程序中默认功能的一部分。
EDIT #2: Ok, this has been bugging me. I blogged about a workaround.
编辑#2:好的,这一直困扰着我。我在博客上写了一个解决方法。