mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Dynamic (DLR) objects work in some places today, but not others. This change expands that support to ForEach-Object, Where-Object and the family of cmdlets that use 'MshExpression' (Select-Object, etc.).
This change addresses both wildcard and non-wildcard cases. In wildcard cases, it uses the existing support of generating PSDynamicMember objects for names returned by GetDynamicMemberNames.
In non-wildcard cases, a dynamic property access is attempted whether or not the name shows up in GetDynamicMemberNames, but a truly "blind" access is only attempted if we see that the base object is an IDMOP. If the dynamic access fails, you'll get the same or a similar error experience as before ("The property 'Blarg' cannot be found", or no error at all, depending on the cmdlet and the strict mode setting).
The included test coverage includes a stub for the.ForEach operator--once people are happy with this change, I can continue by adding support there.
This change should allegedly also have positive perf impact, though in actual perf testing, although it does seem ever-so-slightly faster, I found it difficult to measure much difference at all.
146 lines
4.6 KiB
PowerShell
146 lines
4.6 KiB
PowerShell
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
# Licensed under the MIT License.
|
|
Add-TestDynamicType
|
|
|
|
Describe "Where-Object" -Tags "CI" {
|
|
BeforeAll {
|
|
$Computers = @(
|
|
[PSCustomObject]@{
|
|
ComputerName = "SPC-1234"
|
|
IPAddress = "192.168.0.1"
|
|
NumberOfCores = 1
|
|
Drives = 'C','D'
|
|
},
|
|
[PSCustomObject]@{
|
|
ComputerName = "BGP-5678"
|
|
IPAddress = ""
|
|
NumberOfCores = 2
|
|
Drives = 'C','D','E'
|
|
},
|
|
[PSCustomObject]@{
|
|
ComputerName = "MGC-9101"
|
|
NumberOfCores = 3
|
|
Drives = 'C'
|
|
}
|
|
)
|
|
}
|
|
|
|
It "Where-Object -Not Prop" {
|
|
$Result = $Computers | Where-Object -Not 'IPAddress'
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$true -ne $_.Prop}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$true -ne $_.IPAddress}
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It "Where-Object Prop" {
|
|
$Result = $Computers | Where-Object 'IPAddress'
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$true -eq $_.Prop}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$true -eq $_.IPAddress}
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -contains Value}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.Drives -contains 'D'}
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object Prop -contains Value' {
|
|
$Result = $Computers | Where-Object Drives -contains 'D'
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -in $Array}' {
|
|
$Array = 'SPC-1234','BGP-5678'
|
|
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -in $Array}
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object $Array -in Prop' {
|
|
$Array = 'SPC-1234','BGP-5678'
|
|
$Result = $Computers | Where-Object ComputerName -in $Array
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -ge 2}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -ge 2}
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object Prop -ge 2' {
|
|
$Result = $Computers | Where-Object NumberOfCores -ge 2
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -gt 2}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -gt 2}
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object Prop -gt 2' {
|
|
$Result = $Computers | Where-Object NumberOfCores -gt 2
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -le 2}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -le 2}
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object Prop -le 2' {
|
|
$Result = $Computers | Where-Object NumberOfCores -le 2
|
|
$Result.Count | Should -Be 2
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -lt 2}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -lt 2}
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object Prop -lt 2' {
|
|
$Result = $Computers | Where-Object NumberOfCores -lt 2
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -Like Value}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -like 'MGC-9101'}
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object Prop -like Value' {
|
|
$Result = $Computers | Where-Object ComputerName -like 'MGC-9101'
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object -FilterScript {$_.Prop -Match Pattern}' {
|
|
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -match '^MGC.+'}
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object Prop -like Value' {
|
|
$Result = $Computers | Where-Object ComputerName -match '^MGC.+'
|
|
$Result.Count | Should -Be 1
|
|
}
|
|
|
|
It 'Where-Object should handle dynamic (DLR) objects' {
|
|
$dynObj = [TestDynamic]::new()
|
|
$Result = $dynObj, $dynObj | Where FooProp -eq 123
|
|
$Result.Count | Should -Be 2
|
|
$Result[0] | Should -Be $dynObj
|
|
$Result[1] | Should -Be $dynObj
|
|
}
|
|
|
|
It 'Where-Object should handle dynamic (DLR) objects, even without property name hint' {
|
|
$dynObj = [TestDynamic]::new()
|
|
$Result = $dynObj, $dynObj | Where HiddenProp -eq 789
|
|
$Result.Count | Should -Be 2
|
|
$Result[0] | Should -Be $dynObj
|
|
$Result[1] | Should -Be $dynObj
|
|
}
|
|
}
|