2015-04-09 14 views
5

Angenommen, ich habe ein Array von Hashes in v3 Powershell:Wie kann ich ein Array von PSCustomObjects aus einem Array von Hashes in Powershell v3 generieren?

> $co = [PSCustomObject] $hashes[0] 
> $co | ft -AutoSize 

Value Name 
----- ---- 
    1 Item 1 

> $co.GetType() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  False PSCustomObject       System.Object 

So weit, so gut:

> $hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}} 

ich einen einzelnen Hash in ein PSCustomObject wie diese umwandeln kann. Das Problem tritt auf, wenn ich versuche, die gesamte Hash-Array in PSCustomObjects in einer Pipeline zu konvertieren:

> ($hashes | foreach { [PSCustomObject] $_})[0].getType() 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  True  Hashtable        System.Object 

Wie Sie sehen, ich bin eine Reihe von Hashtable Objekte bekommen, nicht PSCustomObjects. Warum bekomme ich ein unterschiedliches Verhalten und wie kann ich erreichen, was ich will?

Danke.

Antwort

2

Ich habe noch die genaue Ursache herauszufinden (Jeder noch etwas lernt), aber das Problem ist irgendwie mit dem $_ Rohrelement bezogen. Ich kann Ihren Code Arbeit machen, wenn ich eine Besetzung des $_ zwingen

$hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}} 
$hashes | %{([pscustomobject][hashtable]$_)} 

Ausgabe

Value Name 
----- ---- 
    1 Item 1 
    2 Item 2 
    3 Item 3 
    4 Item 4 
    5 Item 5 

Etwas neugierig

ich nicht Name und Value mochte, während ich testete (das war, was eine literale Hash-Tabelle für Header hatte und ich fand es verwirrend, während ich testete), also änderte ich das später zu Data und dann ist die Ausgabe unterschiedlich. Ich poste es nur, weil es neugierig ist. Es ist schwer, die Ergebnisse in der Post zu zeigen.

Name                                      Data 
----                                      ---- 
Item 1                                      1 
Item 2                                      2 
Item 3                                      3 
Item 4                                      4 
Item 5                                      5 
+0

Ja, die [hashtable] Besetzung macht den Trick. Ich würde gerne wissen, warum das nötig ist. – David

+0

Ich habe dies aus der Dokumentation ausgegraben und es könnte einen Hinweis geben: Ein Basisobjekt vom Typ PSCustomObject teilt der Windows PowerShell-Laufzeit mit, dass das einkapselnde PSObject-Objekt kein sinnvolles Basisobjekt hat. Dieser Typ des kapselnden PSObject-Objekts bietet jedoch einen Typnameneigenschaften-Bag, dem Cmdlet-Entwickler erweiterte Member hinzufügen können. Entwickler können auch den Typnamen des Objekts angeben, wodurch dieses Objekt seine erweiterten Member mit anderen PSObject-Objekten desselben Typs teilen kann. –

+0

Ich bekomme andere Ergebnisse, wenn ich Data = "$ _" setze. Es scheint, Zeichenfolgen anders als Ints anzuzeigen. –

2

Statt Gießen, versuchen New-Object direkt anrufen:

# > ($hashes | foreach { New-Object -TypeName PSCustomObject -Property $_})[0].getType() 

IsPublic IsSerial Name          BaseType                                     
-------- -------- ----          --------                                     
True  False PSCustomObject       System.Object  

Auch seltsam, scheint dies zu funktionieren:

# > (0..4 | foreach { ([PSCustomObject]$hashes[$_])})[0].GetType() 

IsPublic IsSerial Name          BaseType                                     
-------- -------- ----          --------                                     
True  False PSCustomObject       System.Object     

Warum? Ich habe keine Ahnung, es scheint Probleme zu haben, den Cast mit einem Pipeline-Hashtable-Eintrag auszuführen.

+0

Sie zweiter Ansatz ist ähnlich wie die Ergebnisse in der Frage ops, als er '$ Hashes genannt [0]' – Matt

+0

Die New-Object Problemumgehung funktioniert. So ist Matts [hashtable] besetzt. Seltsam. – David

1

Dies scheint zu funktionieren:

$hashes = 1..5 | foreach { @{Name="Item $_"; Value=$_}} 

foreach ($hash in $hashes) 
{([PSCustomObject]$hash).gettype()} 
+0

In diesem Fall verwenden Sie das Foreach-Sprachkonstrukt. Innerhalb einer Pipeline wird "foreach" als Alias ​​für den ForEach-Object-Befehl behandelt. Siehe das Hilfethema about_Foreach. – David

+0

@David - Ich weiß, es ist eine foreach-Schleife.Ich war mir nicht bewusst, dass es eine Pipeline-Lösung sein musste oder dass die Hash-Tabellensammlung bereits im Speicher vorhanden ist, was einen besonderen Vorteil darstellt. – mjolinor

1

Es scheint, dass Wert der Pipeline Variable $_ in PSObject gewickelt zu bekommen und dass Bruch geworfen PSCustomObject.

> [email protected]{Value=1},[PSObject]@{Value=2} 

> $hashes[0].GetType().FullName 
System.Collections.Hashtable 
> $hashes[1].GetType().FullName 
System.Collections.Hashtable 
# It seems that both $hashes elements are Hashtable, 

> [Type]::GetTypeArray($hashes).FullName 
System.Collections.Hashtable 
System.Management.Automation.PSObject 
# But, as you can see, second one is not. 

> ([PSCustomObject]$hashes[0]).GetType().FullName 
System.Management.Automation.PSCustomObject 
> ([PSCustomObject]$hashes[1]).GetType().FullName 
System.Collections.Hashtable 
# And that difference break cast to PSCustomObject. 
+0

Sie sind immer für Casting und Tippfragen :) – Matt

Verwandte Themen