Supposing I have a method that gets a collection of enums of my enum type ProjectName
and a have a collection of Server
objects I want to associate with those ProjectName
s in a type called Project
; how would I do this in a Powershell Select-Object
(or some other equivalent of LINQ's Select
).
The C# equivalent of what I want to produce in Powershell is this:
var servers = new[]
{
new Server(/*someOtherProjectsCollection goes here*/),
new Server(/*someOtherProjectsCollection goes here*/),
new Server(/*someOtherProjectsCollection goes here*/)
};
var projects = GetProjectNames().Select(projectName => new Project(projectName, servers.Where(server => server.Projects.Any(serverProject => serverProject.Name == projectName))));
But what I have is this:
$servers = [Server]::new(/*someOtherProjectsCollection goes here*/), [Server]::new(/*someOtherProjectsCollection goes here*/), [Server]::new(/*someOtherProjectsCollection goes here*/)
$projects = (GetProjectNames()) | Select-Object {
$selectedProjectName = $_
return [Project]::new($_, ($servers | Where-Object { $_.projects.Where({ $_ -eq $selectedProjectName }).Count -gt 0 }))
}
When I try and read $projects
back in Powershell LSE (whilst on a breakpoint after this last line), it just returns the code as a string and I can't even cast it to [Project[]]
. I think the problem might be with the use of curly braces with Select-Object
but I'm not sure how else to create a new Project
object within the Select-Object
.
You want ForEach-Object
instead of Select-Object
to return a new [Project]
instance for each project name; also, your code can be streamlined:
$projects = GetProjectNames | ForEach-Object {
$projectName = $_
[Project]::new(
$projectName,
$servers.Where({ $_.projects -eq $projectName })
)
}
Select-Object
is for creating new custom objects based on select properties from the input objects; by contrast, you're constructing a new, specific type instance from each input object, which must be done in a ForEach-Object
call, where you explicitly control the output.
$_.projects -eq $projectName
as a conditional relies on PowerShell's ability to use -eq
with an array as the LHS, in which case filtering is performed, and a filtered subarray is returned; since .Where()
interprets the script block's output as a Boolean, an empty subarray is interpreted as $false
, whereas one with at least one element is interpreted as $true
.
Also note that you don't need an explicit return
, given PowerShell's implicit output behavior: since the newly constructed [Project]
instance isn't assigned to a variable or sent elsewhere, it is automatically returned.