2010-10-14 6 views
10

J'ai travaillé sur certaines fonctions PowerShell pour gérer les objets implémentés dans un assemblage que nous avons créé. L'une des classes avec lesquelles j'ai travaillé implémente IEnumerable. Malheureusement, cela provoque PowerShell à dérouler l'objet à chaque occasion. (Je ne peux pas changer le fait que la classe implémente IEnumerable.)Rendre PowerShell pense qu'un objet n'est pas énumérable

J'ai travaillé autour du problème en créant un objet PSObject et en copiant les propriétés de notre objet personnalisé à PSObject, puis en retournant cela à la place de l'objet personnalisé . Mais j'aimerais vraiment retourner notre objet personnalisé. Y a-t-il un moyen, probablement en utilisant mon fichier types.ps1xml, de masquer la méthode GetEnumerator() de cette classe de PowerShell (ou de dire à PowerShell de ne jamais la dérouler).

+1

Vous avez donc une classe de collection personnalisée et vous ne voulez pas que powershell la traite comme une collection? – rerun

+1

Oui, c'est à peu près tout. La classe a des choses autres que la collection. S'il vous plaît, ne laissez pas cela déboucher sur une discussion sur les (dés) mérites de savoir si cette classe devrait ou non être énumérable. – OldFart

Répondre

8

Emballage dans un PSObject est probablement le meilleur moyen.

Vous pouvez également l'inclure explicitement dans une autre collection — PowerShell ne déploie qu'un seul niveau.

Lors de l'écriture d'une cmdlet en C#/VB/... lorsque vous appelez WriteObject, utilisez la surcharge qui prend un deuxième paramètre: si elle est définie sur false, PowerShell n'énumère pas l'objet transmis comme premier paramètre.

5

Vérifiez le remplacement d'écriture-sortie http://poshcode.org/2300 qui a un paramètre -AsCollection qui vous permet d'éviter le déroulement. Mais au fond, si vous écrivez une fonction qui affiche une collection, et vous ne voulez pas que la collecte déroula, vous devez utiliser CmdletBinding et PSCmdlet:

function Get-Array { 
    [CmdletBinding()] 
    Param([Switch]$AsCollection) 

    [String[]]$data = "one","two","three","four" 
    if($AsCollection) { 
     $PSCmdlet.WriteObject($data,$false) 
    } else { 
     Write-Output $data 
    } 
} 

Si vous appelez cela avec -AsCollection vous aurez obtenir des résultats très différents, même s'ils vont regarder la même chose dans la console.

C:\PS> Get-Array 

one 
two 
three 
four 

C:\PS> Get-Array -AsCollection 

one 
two 
three 
four 

C:\PS> Get-Array -AsCollection| % { $_.GetType() } 


IsPublic IsSerial Name  BaseType        
-------- -------- ----  --------        
True  True  String[] System.Array       



C:\PS> Get-Array | % { $_.GetType() } 


IsPublic IsSerial Name  BaseType        
-------- -------- ----  --------        
True  True  String  System.Object       
True  True  String  System.Object       
True  True  String  System.Object       
True  True  String  System.Object 
+0

Le problème est que je veux éviter de le dérouler JAMAIS. Je peux retourner l'objet de ma fonction sans le dérouler en utilisant l'astuce return-as-array (ou ce que vous décrivez). Mais finalement je finirai par le dérouler par accident. – OldFart

+3

Tout simplement: Je ne connais aucun moyen de le faire, mais s'il vous plaît ne pas essayer :) ... Si vous trouvez un moyen, vous finirez par causer un tas de rapports de bogues de personnes incapables de comprendre pourquoi votre La collection n'a rien dedans bien que .Count rapporte un bon grand nombre. – Jaykul