Как добавить свойство к объекту функции в функции PowerShell PSDrive:

Я попытался использовать значение $ 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 обрабатываются необычно. Это какой-то эзотерический уголок языка?


person rivy    schedule 13.02.2009    source источник


Ответы (1)


Моя первая мысль: когда вы прикрепляете это свойство к объекту, вы присоединяете его к определенному экземпляру этого объекта. Когда ваша переменная теряет ссылку на этот объект, любые сведения об этом новом свойстве теряются.

Я предполагаю, что в следующий раз, когда вы получите этот элемент, вы создадите новый объект FunctionInfo со свойствами foo (которые хранятся в поставщике функций).

Когда вы вызываете Get-Item или Get-ChildItem, он возвращает объектные ссылки на типы .NET, которые представляют базовые элементы. Эти элементы не существуют в памяти бесконечно (представьте себе объект FileInfo для каждого файла на каждом локальном диске и каждого подключенного диска, живущего в памяти ... ой). Поскольку PowerShell создает новый экземпляр каждый раз, когда вы вызываете Get-Item, вы получаете базовый объект FunctionInfo.

Если вы хотите добавить свойство ко всем элементам определенного типа, вы можете это сделать с помощью расширяемой системы типов PowerShell. Вы можете создать собственный файл .ps1xml и загрузить его в сеанс PowerShell, который может добавить свойство к каждому экземпляру типа. Вот несколько отличных примеров из блога команды PowerShell -> Hate Add-Member и Использование расширений типов PowerShell для получения документации.

РЕДАКТИРОВАТЬ (адресный комментарий): Я понимаю, что вы пытаетесь сделать, но сбой вызван тем, что новое свойство «привито» к оболочке PSObject, которая позволяет добавлять свойства на лету. Новое свойство никогда не является частью того объекта FunctionInfo, который вы получаете из PSDrive.

Кроме того, поставщик функции (функция: psdrive) не имеет механизма для хранения этого дополнительного свойства. Он знает и работает с объектами FunctionInfo. Когда вы запрашиваете элемент из Function: PSDrive, поставщик функции возвращает объект FunctionInfo. Когда вы сохраняете функцию в Function: PSDrive, поставщик может сохранять только значения для свойств, которые он знает, как обрабатывать. Можно написать собственный поставщик, который будет обрабатывать новые свойства из оболочки PSObject, но это не является частью функциональности по умолчанию в этом поставщике.

РЕДАКТИРОВАТЬ №2: Хорошо, это меня беспокоит. Я писал в блоге об обходном пути.

person Steven Murawski    schedule 13.02.2009
comment
Я хочу прикреплять свойства только к определенным элементам, а не ко всем типам. Я согласен с временным характером привязанности. Но я переназначаю объект и сохраняю его в функции PSDrive, где он остается. Остальные свойства сохраняются (с любыми изменениями), но добавленные отсутствуют. - person rivy; 13.02.2009
comment
Спасибо за разъяснения; это помогает мне понять проблему. И спасибо за обходной путь. - person rivy; 14.02.2009