奇怪的行为 -> .GetEnumerator() | .Reset() -> 寻找解决方法
Strange behaviour -> .GetEnumerator() | .Reset() -> Looking for a way around
我在 PowerShell 中使用一个简单的 XML 文件,由于我使用 GetEnumerator()
方法,我在使用我的脚本时看到一些奇怪的东西。当我使用 GetEnumerator()
方法将某些内容保存在对象中时,我只能使用该对象一次。之后我必须重新设置才能再次使用它。
我想摆脱这种行为。下面是一个示例脚本,它基本上展示了我如何在我的脚本中使用它。在函数的真实脚本中,我经常使用变量 $ControlObject
,每次都必须重新设置它。
我怎样才能简单地防止这种情况发生?
$XMLTargetPath = Join-Path -Path $PSScriptRoot -ChildPath "XMLConfig.xml"
# Save XML in File for easy and fast reproduction
$XMLContentForFile = [xml]@"
<OuterNode>
<BaseSettings>
<Setting1>Blabla</Setting1>
</BaseSettings>
<DynamicSettings>
<item>
<Number>1</Number>
<Name>January</Name>
</item>
<item>
<Number>2</Number>
<Name>February</Name>
</item>
</DynamicSettings>
</OuterNode>
"@
$XMLContentForFile.Save($XMLTargetPath)
function MyFunction {
Param(
[Parameter(Mandatory=$true, Position=0)]
$ControlObject
)
$ControlObject # Output the Object
$ControlObject # PROBLEM - I get no output ...
# I need to make a reset to output the object again ...
$ControlObject.Reset()
$ControlObject
}
[xml]$xml = Get-Content -Path $XMLTargetPath
# Pass the XML-Node "Dynamic-Settings" into Function
MyFunction -ControlObject $xml.OuterNode.DynamicSettings.GetEnumerator()
我认为您误解了枚举器和 PowerShell 默认输出的工作方式。 PowerShell automagically appends | Out-Default
用于输出处理:
It calls the engine to get the prompt but then it displays it and collects user input. It then takes that input, concatenates | Out-Default
and submits it to the engine for execution. … YES, under the covers every command entered in through the console host is piped to Out-Default
.
但是,管道会自动展开枚举器(否则它将无法显示枚举或可枚举集合的元素)。因此,仅回显一个变量在本质上与遍历 enumerator:
相同
while ($ControlObject.MoveNext()) {
$ControlObject.Current
}
枚举器在输出操作后位于枚举的末尾,所以需要先将其移动到开头,然后才能再次枚举元素。这就是 Reset()
所做的。
为什么管道不自动重置枚举?我不知道,但可能不会产生无限循环。
底线:蛋糕不能吃。需要展开枚举以便显示元素,并且由于枚举不会自动重置,您需要自己执行此操作才能再次枚举元素。
如果您只想要所选节点的嵌套元素,您应该使用 ChildNodes
属性 而不是枚举器。
MyFunction -ControlObject $xml.OuterNode.DynamicSettings.ChildNodes
我在 PowerShell 中使用一个简单的 XML 文件,由于我使用 GetEnumerator()
方法,我在使用我的脚本时看到一些奇怪的东西。当我使用 GetEnumerator()
方法将某些内容保存在对象中时,我只能使用该对象一次。之后我必须重新设置才能再次使用它。
我想摆脱这种行为。下面是一个示例脚本,它基本上展示了我如何在我的脚本中使用它。在函数的真实脚本中,我经常使用变量 $ControlObject
,每次都必须重新设置它。
我怎样才能简单地防止这种情况发生?
$XMLTargetPath = Join-Path -Path $PSScriptRoot -ChildPath "XMLConfig.xml"
# Save XML in File for easy and fast reproduction
$XMLContentForFile = [xml]@"
<OuterNode>
<BaseSettings>
<Setting1>Blabla</Setting1>
</BaseSettings>
<DynamicSettings>
<item>
<Number>1</Number>
<Name>January</Name>
</item>
<item>
<Number>2</Number>
<Name>February</Name>
</item>
</DynamicSettings>
</OuterNode>
"@
$XMLContentForFile.Save($XMLTargetPath)
function MyFunction {
Param(
[Parameter(Mandatory=$true, Position=0)]
$ControlObject
)
$ControlObject # Output the Object
$ControlObject # PROBLEM - I get no output ...
# I need to make a reset to output the object again ...
$ControlObject.Reset()
$ControlObject
}
[xml]$xml = Get-Content -Path $XMLTargetPath
# Pass the XML-Node "Dynamic-Settings" into Function
MyFunction -ControlObject $xml.OuterNode.DynamicSettings.GetEnumerator()
我认为您误解了枚举器和 PowerShell 默认输出的工作方式。 PowerShell automagically appends | Out-Default
用于输出处理:
It calls the engine to get the prompt but then it displays it and collects user input. It then takes that input, concatenates
| Out-Default
and submits it to the engine for execution. … YES, under the covers every command entered in through the console host is piped toOut-Default
.
但是,管道会自动展开枚举器(否则它将无法显示枚举或可枚举集合的元素)。因此,仅回显一个变量在本质上与遍历 enumerator:
相同while ($ControlObject.MoveNext()) {
$ControlObject.Current
}
枚举器在输出操作后位于枚举的末尾,所以需要先将其移动到开头,然后才能再次枚举元素。这就是 Reset()
所做的。
为什么管道不自动重置枚举?我不知道,但可能不会产生无限循环。
底线:蛋糕不能吃。需要展开枚举以便显示元素,并且由于枚举不会自动重置,您需要自己执行此操作才能再次枚举元素。
如果您只想要所选节点的嵌套元素,您应该使用 ChildNodes
属性 而不是枚举器。
MyFunction -ControlObject $xml.OuterNode.DynamicSettings.ChildNodes