Как добавить свойство в объект функции в PowerShell PSDrive «функция:»? - PullRequest
3 голосов
/ 13 февраля 2009

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

1 Ответ

4 голосов
/ 13 февраля 2009

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

Полагаю, в следующий раз, когда вы получите этот элемент, вы создаете новый объект 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, поставщик Function возвращает объект FunctionInfo. Когда вы сохраняете функцию в Function: PSDrive, поставщик может хранить значения только для свойств, которые он знает, как обрабатывать. Можно написать собственный поставщик, который будет обрабатывать новые свойства из оболочки PSObject, но это не является частью функций по умолчанию в этом поставщике.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...